QBasic Trader
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1763 lines
45 KiB

11 years ago
  1. ' ***************
  2. ' * T R A D E R *
  3. ' * v1.0 *
  4. ' ***************
  5. '
  6. ' Copyright 1997 Brennen Bearnes
  7. ' This is an attempted clone of an old Apple II game called Taipan, in which
  8. ' you sailed around, traded in stuff, and battled pirates. Copy and
  9. ' distribute as you like, provided you distribute the original unmodified
  10. ' archive (trader.zip).
  11. ' NOTES:
  12. ' I started this for the last Retro Compo on comp.lang.basic.misc (which got
  13. ' something like 3 entries), and it's been sitting there unfinished for
  14. ' months. There's quite a bit of stuff I'd like to add, but I figured I
  15. ' ought to release what I have. Below is a list of things I'd like to
  16. ' complete for version 2.0.
  17. ' Stuff that needs done:
  18. ' - A story (sort of have one worked out)
  19. ' - More enemies
  20. ' - Cannon and armor upgrades, etc.
  21. ' - More locations within cities
  22. ' - More/better graphics
  23. ' - End game animations
  24. ' The graphics (such as they are), were done with Lior Zur's excellent QBdraw.
  25. ' It can be found at:
  26. ' http://www.geocities.com/SiliconValley/Heights/9246/
  27. ' Comments/ideas/suggestions are, as always, welcome.
  28. ' --
  29. ' Brennen Bearnes | bbearnes@hardlink.com
  30. ' http://www.hardlink.com/~bbearnes/
  31. ' ********
  32. ' * SUBs *
  33. ' ********
  34. DECLARE SUB AddCargo (d%, Item$, AddToPlace%)
  35. DECLARE SUB BankMenu ()
  36. DECLARE SUB BlockPrint (StartY%, StartX%, EndY%, EndX%, ReplaceChar$)
  37. DECLARE SUB Events (d%)
  38. DECLARE SUB FLoad (FileOffset&, DataLength&, Pic1%())
  39. DECLARE SUB FireCannon (startShotX!, startShotY!, shotSpeed!, shotAngle!, FireType, sX, psX)
  40. DECLARE SUB GameOver (OverType%)
  41. DECLARE SUB IconLoad (LoadIcon%, LIType%)
  42. DECLARE SUB IconPut (IconPutX%, IconPutY%, IconPut$)
  43. DECLARE SUB MainMenu ()
  44. DECLARE SUB MarketMenu ()
  45. DECLARE SUB PalLoad (PalFile$)
  46. DECLARE SUB Pause (delay!)
  47. DECLARE SUB ReadIcon ()
  48. DECLARE SUB SeaBattle (PType%, PGuns%)
  49. DECLARE SUB SetPrices (d%)
  50. DECLARE SUB ShipMenu ()
  51. DECLARE SUB WarehouseMenu ()
  52. ' *************
  53. ' * FUNCTIONs *
  54. ' *************
  55. DECLARE FUNCTION BuyPrice% (Item$)
  56. DECLARE FUNCTION GetKey$ ()
  57. DECLARE FUNCTION OpenMix1! (FileName$)
  58. DECLARE FUNCTION SellPrice% (Item$)
  59. DECLARE FUNCTION ShipFree% ()
  60. DECLARE FUNCTION WareFree% ()
  61. ' *********
  62. ' * TYPEs *
  63. ' *********
  64. TYPE World
  65. paidPirates AS INTEGER
  66. gameDate AS INTEGER
  67. END TYPE
  68. TYPE Storage
  69. capacity AS INTEGER
  70. cannon AS INTEGER
  71. wheat AS INTEGER
  72. ore AS INTEGER
  73. luxuries AS INTEGER
  74. contraband AS INTEGER
  75. equipment AS INTEGER
  76. damage AS INTEGER
  77. END TYPE
  78. TYPE CityType
  79. CName AS STRING * 11
  80. CType AS STRING * 3
  81. Hidden AS INTEGER
  82. END TYPE
  83. TYPE PalType
  84. r AS INTEGER
  85. g AS INTEGER
  86. B AS INTEGER
  87. END TYPE
  88. ' *************
  89. ' * Variables *
  90. ' *************
  91. 'The default text color.
  92. DIM SHARED TextCol%
  93. TextCol% = 4
  94. 'World data. Basically, all the misc. stuff that's going on in the game.
  95. DIM SHARED GameState AS World
  96. 'Holds data for the cities you can travel to.
  97. DIM SHARED Ports(8) AS CityType
  98. 'Storage variables.
  99. DIM SHARED WareHouse AS Storage
  100. DIM SHARED Ship AS Storage
  101. DIM SHARED CurrentPrices AS Storage
  102. 'Misc. stuff.
  103. DIM SHARED Credits!, City%, Bank!
  104. DIM SHARED PName$
  105. 'QBdraw MIX loader variables.
  106. CONST MaxMIX = 30 'Max files in a MIX file.
  107. DIM SHARED DimSize AS INTEGER
  108. DIM SHARED pall(256) AS PalType
  109. DIM SHARED pal(768)
  110. DIM SHARED FileSizer AS INTEGER 'The file's number of bytes counter.
  111. DIM SHARED FilesNumber AS INTEGER 'number of picture files in the MIX
  112. DIM SHARED ArraySize(MaxMIX) AS INTEGER 'array size of each file
  113. DIM SHARED StartRead(MaxMIX) AS INTEGER 'start reading place
  114. 'For the cannon ball drawing code.
  115. CONST PI = 3.141592654#
  116. SCREEN 13
  117. PalLoad "draw" 'load palette
  118. CLOSE
  119. N = OpenMix1("icon") 'open the MIX file and get variables.
  120. IF N = 0 THEN 'if no errors
  121. DIM SHARED ShipIcon%(ArraySize(1))
  122. DIM SHARED PirateIcon%(ArraySize(2))
  123. DIM SHARED cannon%(ArraySize(3))
  124. DIM SHARED IndIcon%(ArraySize(4))
  125. DIM SHARED AgrIcon%(ArraySize(5))
  126. DIM SHARED MinIcon%(ArraySize(6))
  127. DIM SHARED FunIcon%(ArraySize(7))
  128. DIM SHARED Splash%(ArraySize(8))
  129. DIM SHARED Cancel%(ArraySize(9))
  130. DIM SHARED TavernSign%(ArraySize(10))
  131. DIM SHARED WareHouseIcon%(ArraySize(11))
  132. DIM SHARED BankSign%(ArraySize(12))
  133. FOR LoadIcon% = 1 TO 12
  134. IconLoad LoadIcon%, 1
  135. NEXT LoadIcon%
  136. END IF
  137. CLOSE
  138. 'Load larger graphics. (just 4, so far.)
  139. N = OpenMix1("bigpics") 'open the MIX file and get variables.
  140. IF N = 0 THEN 'if no errors
  141. DIM SHARED BigShipPic%(ArraySize(1))
  142. DIM SHARED PirateShipPic%(ArraySize(2))
  143. DIM SHARED StormPic%(ArraySize(3))
  144. DIM SHARED PatrolShipPic%(ArraySize(4))
  145. FOR LoadIcon% = 1 TO 4
  146. IconLoad LoadIcon%, 2
  147. NEXT LoadIcon%
  148. END IF
  149. CLOSE
  150. 'The main game menu.
  151. MainMenu
  152. 'Starting stuff. How much your warehouse/ship can hold, what stuff you start
  153. 'out with, what things cost at the beginning.
  154. WareHouse.capacity = 1000
  155. Ship.damage = 100
  156. Ship.capacity = 100
  157. Ship.cannon = 3
  158. Ship.ore = 5
  159. Credits! = 50
  160. CurrentPrices.wheat = 4
  161. CurrentPrices.ore = 45
  162. CurrentPrices.luxuries = 30
  163. CurrentPrices.contraband = 150
  164. CurrentPrices.equipment = 1000
  165. 'Set the date to -1 so that you start out in January.
  166. GameState.gameDate = -1
  167. 'Read the cities. First is always "home base".
  168. FOR LoadCity% = 1 TO 8
  169. READ Ports(LoadCity%).CName
  170. READ Ports(LoadCity%).CType
  171. NEXT LoadCity%
  172. City% = 1
  173. CLS
  174. ' *******************
  175. ' * Main game loop. *
  176. ' *******************
  177. CityMenu:
  178. CLS
  179. 'PUT the city icon
  180. IconPut 10, 10, Ports(City%).CType
  181. LINE (5, 5)-(315, 195), 5, B
  182. LOCATE 4, 6: PRINT "You are in the city of "; Ports(City%).CName
  183. LOCATE 7, 3: PRINT "Where do you want to go?"
  184. IconPut 20, 68, Ports(City%).CType
  185. LOCATE 11, 7: PRINT "1. The Marketplace"
  186. IconPut 20, 92, "ship"
  187. LOCATE 14, 7: PRINT "2. Your Ship"
  188. IF City% = 1 THEN
  189. IconPut 20, 116, "warehouse"
  190. LOCATE 17, 7: PRINT "3. Your Warehouse"
  191. IconPut 20, 140, "banksign"
  192. LOCATE 20, 7: PRINT "4. The Bank"
  193. END IF
  194. SELECT CASE UCASE$(GetKey$)
  195. CASE "1"
  196. MarketMenu
  197. CASE "2"
  198. ShipMenu
  199. CASE "3"
  200. IF City% = 1 THEN
  201. WarehouseMenu
  202. ELSE
  203. GOSUB CityMenu
  204. END IF
  205. CASE "4"
  206. IF City% = 1 THEN
  207. BankMenu
  208. ELSE
  209. GOSUB CityMenu
  210. END IF
  211. CASE CHR$(27)
  212. LOCATE 22, 4: PRINT "Do you want to quit?"
  213. SELECT CASE UCASE$(GetKey$)
  214. CASE "Y"
  215. LOCATE 22, 25: PRINT "Y"
  216. Pause 1
  217. END
  218. CASE ELSE
  219. GOSUB CityMenu
  220. END SELECT
  221. END SELECT
  222. GOSUB CityMenu
  223. ' ********
  224. ' * DATA *
  225. ' ********
  226. 'city data
  227. 'Format: Name, type
  228. 'Agr is Agricultural
  229. 'Min is Mining
  230. 'Ind is industrial, or manufacturing.
  231. 'Fun is a pleasure city or resort.
  232. DATA "Smogville", "Ind"
  233. DATA "Cowstown", "Agr"
  234. DATA "Millwater", "Ind"
  235. DATA "Rockton", "Min"
  236. DATA "Grainville", "Agr"
  237. DATA "Silvercreek", "Min"
  238. DATA "Coalburgh", "Ind"
  239. DATA "Utopia", "Fun"
  240. SUB AddCargo (d%, Item$, AddToPlace%)
  241. SELECT CASE AddToPlace%
  242. CASE 1
  243. SELECT CASE Item$
  244. CASE "cannon"
  245. Ship.cannon = Ship.cannon + d%
  246. CASE "wheat"
  247. Ship.wheat = Ship.wheat + d%
  248. CASE "ore"
  249. Ship.ore = Ship.ore + d%
  250. CASE "luxuries"
  251. Ship.luxuries = Ship.luxuries + d%
  252. CASE "contraband"
  253. Ship.contraband = Ship.contraband + d%
  254. CASE "equipment"
  255. Ship.equipment = Ship.equipment + d%
  256. END SELECT
  257. CASE 2
  258. SELECT CASE Item$
  259. CASE "cannon"
  260. WareHouse.cannon = WareHouse.cannon + d%
  261. CASE "wheat"
  262. WareHouse.wheat = WareHouse.wheat + d%
  263. CASE "ore"
  264. WareHouse.ore = WareHouse.ore + d%
  265. CASE "luxuries"
  266. WareHouse.luxuries = WareHouse.luxuries + d%
  267. CASE "contraband"
  268. WareHouse.contraband = WareHouse.contraband + d%
  269. CASE "equipment"
  270. WareHouse.equipment = WareHouse.equipment + d%
  271. END SELECT
  272. END SELECT
  273. END SUB
  274. SUB BankMenu
  275. MainBank:
  276. CLS
  277. LINE (5, 5)-(315, 195), 5, B
  278. IconPut 10, 10, "banksign"
  279. LOCATE 4, 6: PRINT "The Bank in " + Ports(City%).CName
  280. LOCATE 7, 3: PRINT "Your account contains"; FIX(Bank!); "Credits."
  281. LOCATE 8, 3: PRINT "You have "; FIX(Credits!); " Credits in Cash."
  282. LOCATE 10, 4: PRINT "1. Withdraw Cash"
  283. LOCATE 11, 4: PRINT "2. Deposit Cash"
  284. LOCATE 12, 4: PRINT "3. Back to Main Menu"
  285. SELECT CASE VAL(GetKey$)
  286. CASE 1
  287. LOCATE 14, 5: INPUT "Enter amount to withdraw: ", Transaction!
  288. IF Transaction! > Bank! THEN
  289. LOCATE 16, 7: PRINT "Your account isn't that big."
  290. WHILE INKEY$ = "": WEND
  291. ELSEIF Transaction! <= Bank! THEN
  292. Bank! = Bank! - Transaction!
  293. Credits! = Credits! + Transaction!
  294. LOCATE 16, 7: PRINT "Thanks for your business."
  295. WHILE INKEY$ = "": WEND
  296. END IF
  297. GOSUB MainBank
  298. CASE 2
  299. LOCATE 14, 5: INPUT "Enter amount to deposit: ", Transaction!
  300. IF Transaction! > Credits! THEN
  301. LOCATE 16, 7: PRINT "You don't have that many credits."
  302. WHILE INKEY$ = "": WEND
  303. ELSEIF Transaction! <= Credits! THEN
  304. Bank! = Bank! + Transaction!
  305. Credits! = Credits! - Transaction!
  306. LOCATE 16, 7: PRINT "Thanks for your business."
  307. WHILE INKEY$ = "": WEND
  308. END IF
  309. GOSUB MainBank
  310. CASE 3
  311. EXIT SUB
  312. CASE ELSE
  313. GOSUB MainBank
  314. END SELECT
  315. END SUB
  316. SUB BlockPrint (StartY%, StartX%, EndY%, EndX%, ReplaceChar$)
  317. 'This little sub just prints a block of the specified character at the
  318. 'given coordinates. I use it for clearing a section of the screen, such as
  319. 'a menu.
  320. FOR PrintLine% = StartY% TO EndY%
  321. LOCATE PrintLine%, StartX%: PRINT STRING$((EndX% - StartX%), ReplaceChar$)
  322. NEXT PrintLine%
  323. END SUB
  324. FUNCTION BuyPrice% (Item$)
  325. 'Returns the cost to buy cargo.
  326. SELECT CASE Ports(City%).CType
  327. CASE "Agr"
  328. SELECT CASE Item$
  329. CASE "cannon"
  330. Price% = 0
  331. CASE "wheat"
  332. Price% = CurrentPrices.wheat
  333. CASE "ore"
  334. Price% = 0
  335. CASE "luxuries"
  336. Price% = 0
  337. CASE "contraband"
  338. Price% = 0
  339. CASE "equipment"
  340. Price% = 0
  341. END SELECT
  342. CASE "Ind"
  343. SELECT CASE Item$
  344. CASE "cannon"
  345. Price% = 0
  346. CASE "wheat"
  347. Price% = 0
  348. CASE "ore"
  349. Price% = 0
  350. CASE "luxuries"
  351. Price% = CurrentPrices.luxuries
  352. CASE "contraband"
  353. Price% = 0
  354. CASE "equipment"
  355. Price% = CurrentPrices.equipment
  356. END SELECT
  357. CASE "Min"
  358. SELECT CASE Item$
  359. CASE "cannon"
  360. Price% = 0
  361. CASE "wheat"
  362. Price% = 0
  363. CASE "ore"
  364. Price% = CurrentPrices.ore
  365. CASE "luxuries"
  366. Price% = 0
  367. CASE "contraband"
  368. Price% = 0
  369. CASE "equipment"
  370. Price% = 0
  371. END SELECT
  372. CASE "Fun"
  373. SELECT CASE Item$
  374. CASE "cannon"
  375. Price% = 0
  376. CASE "wheat"
  377. Price% = 0
  378. CASE "ore"
  379. Price% = 0
  380. CASE "luxuries"
  381. Price% = 0
  382. CASE "contraband"
  383. Price% = CurrentPrices.contraband
  384. CASE "equipment"
  385. Price% = 0
  386. END SELECT
  387. END SELECT
  388. BuyPrice% = Price%
  389. END FUNCTION
  390. SUB Events (d%)
  391. 'This sub does all the stuff after you complete a voyage. Interest at the
  392. 'bank, the date, calls SetPrices, etc.
  393. 'Increase the date. Each voyage takes one month.
  394. 'Yeah, I know it's unrealistic.
  395. GameState.gameDate = GameState.gameDate + 1
  396. Year = FIX((GameState.gameDate / 12)) + 1850
  397. Month = GameState.gameDate - ((Year - 1850) * 12)
  398. SELECT CASE Month
  399. CASE 0
  400. Month$ = "January"
  401. CASE 1
  402. Month$ = "February"
  403. CASE 2
  404. Month$ = "March"
  405. CASE 3
  406. Month$ = "April"
  407. CASE 4
  408. Month$ = "May"
  409. CASE 5
  410. Month$ = "June"
  411. CASE 6
  412. Month$ = "July"
  413. CASE 7
  414. Month$ = "August"
  415. CASE 8
  416. Month$ = "September"
  417. CASE 9
  418. Month$ = "October"
  419. CASE 10
  420. Month$ = "November"
  421. CASE 11
  422. Month$ = "December"
  423. END SELECT
  424. 'Calculate interest at the bank.
  425. Bank! = FIX(Bank! + (Bank! * .05))
  426. 'This SUB sets the prices at the marketplace.
  427. SetPrices d%
  428. CLS
  429. LINE (5, 5)-(315, 195), 5, B
  430. IconPut 10, 10, Ports(d%).CType
  431. LOCATE 4, 6: PRINT "Arriving at " + Ports(d%).CName
  432. LOCATE 7, 3: PRINT Month$; Year
  433. SELECT CASE Month$
  434. CASE "January"
  435. 'Every January, the pirate's guild demands tribute. If you pay, you won't
  436. 'be attacked by pirates. Much.
  437. GameState.paidPirates = 0
  438. IF Credits! > 100 AND GameState.paidPirates = 1 THEN
  439. Tribute% = INT(Credits! * .25)
  440. ELSEIF Credits! > 100 AND GameState.paidPirates = 0 THEN
  441. Tribute% = INT(Credits! * .5)
  442. ELSEIF Credits! < 100 THEN
  443. Tribute% = 50
  444. END IF
  445. LOCATE 9, 3: PRINT "The pirate's guild demands "; Tribute%; "in"
  446. LOCATE 10, 3: PRINT "tribute. Will you pay?"
  447. SELECT CASE UCASE$(GetKey$)
  448. CASE "Y"
  449. IF Credits! >= Tribute% THEN
  450. LOCATE 10, 27: PRINT "Y"
  451. Credits! = Credits! - Tribute%
  452. GameState.paidPirates = 1
  453. ELSE
  454. LOCATE 11, 3: PRINT "You can't afford to pay."
  455. END IF
  456. CASE "N"
  457. LOCATE 10, 27: PRINT "N"
  458. END SELECT
  459. CASE "July"
  460. 'The wheat harvest is in or around july, which means that wheat prices
  461. 'fall. They don't pick back up again for several months, which should
  462. 'be an easy way to turn a good profit. (Exercise left to reader.)
  463. LOCATE 9, 3: PRINT "The wheat harvest has been completed."
  464. LOCATE 10, 3: PRINT "Wheat prices are down."
  465. CASE "October"
  466. 'Wheat prices rise again.
  467. LOCATE 9, 3: PRINT "Wheat prices have risen somewhat."
  468. END SELECT
  469. WHILE INKEY$ = "": WEND
  470. END SUB
  471. SUB FireCannon (startShotX, startShotY, shotSpeed, shotAngle, FireType, sX, psX)
  472. 'FireType is what kind of shot it is.
  473. '1 = Your ship, hit
  474. '2 = Your ship, miss
  475. '3 = Pirate ship, hit
  476. '4 = Pirate ship, miss
  477. shotAngle = shotAngle / 180 * PI
  478. startShotXvel = COS(shotAngle) * shotSpeed
  479. startShotYvel = SIN(shotAngle) * shotSpeed
  480. t = 0
  481. EndShot% = 0
  482. DO
  483. FOR paws = 1 TO 900: NEXT paws
  484. CIRCLE (shotX, shotY), 1, 0
  485. t = t + .1
  486. shotX = startShotX + (startShotXvel * t)
  487. shotY = startShotY + ((-1 * (startShotYvel * t)) + (4.9 * t ^ 2)) * (200 / 350)
  488. CIRCLE (shotX, shotY), 1, 24
  489. IF FireType = 1 AND shotX >= psX THEN
  490. CIRCLE (shotX, shotY), 1, 0
  491. EndShot% = 1
  492. ELSEIF FireType = 2 AND shotY >= 94 THEN
  493. CIRCLE (shotX, shotY), 1, 0
  494. PUT (shotX, shotY), Splash%
  495. EndShot% = 1
  496. paws = TIMER: WHILE TIMER <= paws + .5: WEND
  497. PUT (shotX, shotY), Splash%
  498. ELSEIF FireType = 3 AND shotX <= sX + 50 THEN
  499. CIRCLE (shotX, shotY), 1, 0
  500. EndShot% = 1
  501. ELSEIF FireType = 4 AND shotY >= 94 THEN
  502. CIRCLE (shotX, shotY), 1, 0
  503. PUT (shotX - 5, shotY), Splash%
  504. EndShot% = 1
  505. paws = TIMER: WHILE TIMER <= paws + .5: WEND
  506. PUT (shotX - 5, shotY), Splash%
  507. END IF
  508. LOOP UNTIL EndShot% = 1
  509. END SUB
  510. SUB FLoad (FileOffset&, DataLength&, DestArray() AS INTEGER)
  511. '
  512. ' FLoad -- Quickly loads a file's contents into specified integer array.
  513. '
  514. ' --Parameters--
  515. ' FileName$ = The file name to load
  516. ' FileOffset& = The offset of the file to start loading
  517. ' DataLength& = The amount, in bytes, of data to load.
  518. ' DestArray() = The array to load all the data into.
  519. IF FileOffset& = 0 THEN FileOffset& = 1
  520. RemBytes& = DataLength&
  521. BufferSize% = 32766 ' The buffer size to use. If you get out of string
  522. ' space errors, lower it. (result : it's slower)
  523. BufStart% = LBOUND(DestArray) ' Lowest element number of buffer
  524. DEF SEG = VARSEG(DestArray(BufStart%)) ' The segment of the song buffer
  525. Ptr& = VARPTR(DestArray(BufStart%)) ' Pointer to the song buffer
  526. LeftBytes& = RemBytes& MOD BufferSize% ' The amount of left over bytes
  527. SEEK #1, FileOffset&
  528. IF (LeftBytes& < RemBytes&) THEN
  529. FOR QuickLoad% = 1 TO (DataLength& - LeftBytes&) / BufferSize%
  530. Buffer$ = SPACE$(BufferSize%)
  531. GET #1, , Buffer$
  532. FOR x% = 1 TO BufferSize%
  533. POKE Ptr&, ASC(MID$(Buffer$, x%, 1))
  534. Ptr& = Ptr& + 1
  535. NEXT
  536. Buffer$ = ""
  537. RemBytes& = RemBytes& - BufferSize%
  538. NEXT
  539. END IF
  540. IF (LeftBytes& > 0) THEN
  541. Buffer$ = SPACE$(LeftBytes&)
  542. GET #1, , Buffer$
  543. FOR x% = 1 TO LeftBytes&
  544. POKE Ptr&, ASC(MID$(Buffer$, x%, 1))
  545. Ptr& = Ptr& + 1
  546. NEXT
  547. Buffer$ = ""
  548. END IF
  549. DEF SEG
  550. END SUB
  551. SUB GameOver (OverType%)
  552. ' 1 - Sunk by a pirate
  553. ' 2 - Sunk in a storm
  554. ' more to come
  555. SELECT CASE OverType%
  556. CASE 1
  557. CLS
  558. LINE (5, 5)-(315, 195), 5, B
  559. LOCATE 19, 3: PRINT "Your ship has been sunk in a"
  560. LOCATE 20, 3: PRINT "fierce battle with pirates."
  561. Pause 1
  562. FOR MovingShip% = 50 TO 75
  563. WAIT &H3DA, 8
  564. PUT (120, (MovingShip% - 1)), BigShipPic%
  565. PUT (120, MovingShip%), BigShipPic%, PSET
  566. Pause .3
  567. NEXT MovingShip%
  568. LOCATE 22, 3: PRINT "Press a key to continue."
  569. SLEEP
  570. CASE 2
  571. PRINT "Your ship has been sunk in a storm."
  572. PRINT TAB(6); "Press a key to continue."
  573. SLEEP
  574. END SELECT
  575. 'This may be clumsy, but all this does is re-run the program, bringing you
  576. 'back to the main menu, which lets you start a new game, restore, etc.
  577. RUN "trader"
  578. END SUB
  579. FUNCTION GetKey$
  580. 'This just returns a keypress value. Used for all those menus. I think it
  581. 'makes things a little more efficient, anyway.
  582. k$ = ""
  583. WHILE k$ = "": k$ = INKEY$: WEND
  584. GetKey$ = k$
  585. END FUNCTION
  586. SUB IconLoad (LoadIcon%, LIType%)
  587. DatLen& = ArraySize(LoadIcon%) * 2 'just temporary variables
  588. StrRed& = StartRead(LoadIcon%) 'because of Fload.
  589. IF LIType% = 1 THEN
  590. SELECT CASE LoadIcon%
  591. CASE 1
  592. FLoad StrRed&, DatLen&, ShipIcon%()
  593. CASE 2
  594. FLoad StrRed&, DatLen&, PirateIcon%()
  595. CASE 3
  596. FLoad StrRed&, DatLen&, cannon%()
  597. CASE 4
  598. FLoad StrRed&, DatLen&, IndIcon%()
  599. CASE 5
  600. FLoad StrRed&, DatLen&, AgrIcon%()
  601. CASE 6
  602. FLoad StrRed&, DatLen&, MinIcon%()
  603. CASE 7
  604. FLoad StrRed&, DatLen&, FunIcon%()
  605. CASE 8
  606. FLoad StrRed&, DatLen&, Splash%()
  607. CASE 9
  608. FLoad StrRed&, DatLen&, Cancel%()
  609. CASE 10
  610. FLoad StrRed&, DatLen&, TavernSign%()
  611. CASE 11
  612. FLoad StrRed&, DatLen&, WareHouseIcon%()
  613. CASE 12
  614. FLoad StrRed&, DatLen&, BankSign%()
  615. END SELECT
  616. ELSEIF LIType% = 2 THEN
  617. SELECT CASE LoadIcon%
  618. CASE 1
  619. FLoad StrRed&, DatLen&, BigShipPic%()
  620. CASE 2
  621. FLoad StrRed&, DatLen&, PirateShipPic%()
  622. CASE 3
  623. FLoad StrRed&, DatLen&, StormPic%()
  624. END SELECT
  625. END IF
  626. END SUB
  627. SUB IconPut (IconPutX%, IconPutY%, IconPutName$)
  628. SELECT CASE IconPutName$
  629. CASE "Ind"
  630. PUT (IconPutX%, IconPutY%), IndIcon%
  631. CASE "Min"
  632. PUT (IconPutX%, IconPutY%), MinIcon%
  633. CASE "Agr"
  634. PUT (IconPutX%, IconPutY%), AgrIcon%
  635. CASE "Fun"
  636. PUT (IconPutX%, IconPutY%), FunIcon%
  637. CASE "warehouse"
  638. PUT (IconPutX%, IconPutY%), WareHouseIcon%
  639. CASE "banksign"
  640. PUT (IconPutX%, IconPutY%), BankSign%
  641. CASE "tavernsign"
  642. PUT (IconPutX%, IconPutY%), TavernSign%
  643. CASE "ship"
  644. PUT (IconPutX%, IconPutY%), ShipIcon%
  645. CASE "cancel"
  646. PUT (IconPutX%, IconPutY%), Cancel%
  647. END SELECT
  648. END SUB
  649. SUB MainMenu
  650. Start:
  651. CLS
  652. COLOR TextCol%
  653. PRINT
  654. PRINT TAB(13); "T R A D E R"
  655. PRINT
  656. IconPut 20, 44, "ship"
  657. LOCATE 8, 7: PRINT "1. New Game"
  658. IconPut 20, 68, "cancel"
  659. LOCATE 11, 7: PRINT "2. Quit"
  660. SELECT CASE VAL(GetKey$)
  661. CASE 1
  662. GOSUB StartGame
  663. CASE 2
  664. END
  665. CASE ELSE
  666. GOSUB Start
  667. END SELECT
  668. StartGame:
  669. CLS
  670. PRINT
  671. PRINT TAB(6); "What is your name, Trader?"
  672. LOCATE 4, 10: INPUT "]", PName$ 'Get the player's name.
  673. CLS
  674. END SUB
  675. SUB MarketMenu
  676. 'Buy and sell stuff, etc.
  677. MainMarket:
  678. CLS
  679. LINE (5, 5)-(315, 195), 5, B
  680. 'Draw the city icon thingy.
  681. IconPut 10, 10, Ports(City%).CType
  682. LOCATE 4, 6: PRINT "The market in " + Ports(City%).CName
  683. LOCATE 7, 3: PRINT "Cargo Free"
  684. IF ShipFree% >= 0 THEN
  685. LOCATE 8, 3: PRINT USING "#### ####"; (Ship.capacity - ShipFree%); ShipFree%
  686. ELSEIF ShipFree% < 0 THEN
  687. LOCATE 8, 3: PRINT USING "#### Overloaded"; (Ship.capacity - ShipFree%)
  688. END IF
  689. LOCATE 10, 3: PRINT FIX(Credits!); "Credits"
  690. LOCATE 12, 3: PRINT "What do you want to do?"
  691. LOCATE 13, 4: PRINT "1. Sell Items"
  692. LOCATE 14, 4: PRINT "2. Buy Items"
  693. LOCATE 15, 4: PRINT "3. Back to Main Menu"
  694. SELECT CASE VAL(GetKey$)
  695. CASE 1
  696. GOSUB SellMenu
  697. CASE 2
  698. GOSUB BuyMenu
  699. CASE 3
  700. EXIT SUB
  701. CASE ELSE
  702. GOSUB MainMarket
  703. END SELECT
  704. SellMenu:
  705. CLS
  706. LINE (5, 5)-(315, 195), 5, B
  707. LOCATE 5, 3: PRINT "What do you want to sell?"
  708. 'Put the city icon thingy.
  709. IconPut 10, 10, Ports(City%).CType
  710. LOCATE 7, 4: PRINT "Item No."
  711. IF Ship.cannon > 0 THEN LOCATE 9, 4: PRINT USING "(C)annon ####"; Ship.cannon
  712. IF Ship.wheat > 0 THEN LOCATE 10, 4: PRINT USING "(W)heat ####"; Ship.wheat
  713. IF Ship.ore > 0 THEN LOCATE 11, 4: PRINT USING "(O)re ####"; Ship.ore
  714. IF Ship.luxuries > 0 THEN LOCATE 12, 4: PRINT USING "(L)uxury Goods ####"; Ship.luxuries
  715. IF Ship.contraband > 0 THEN LOCATE 13, 4: PRINT USING "Con(t)raband ####"; Ship.contraband
  716. IF Ship.equipment > 0 THEN LOCATE 14, 4: PRINT USING "(E)quipment ####"; Ship.equipment
  717. LOCATE 16, 4: PRINT "(D)one"
  718. 'There has *got* to be a better way to do this...
  719. SELECT CASE UCASE$(GetKey$)
  720. CASE "C"
  721. NumItems% = Ship.cannon: Item$ = "cannon"
  722. CASE "W"
  723. NumItems% = Ship.wheat: Item$ = "wheat"
  724. CASE "O"
  725. NumItems% = Ship.ore: Item$ = "ore"
  726. CASE "L"
  727. NumItems% = Ship.luxuries: Item$ = "luxuries"
  728. CASE "T"
  729. NumItems% = Ship.contraband: Item$ = "contraband"
  730. CASE "E"
  731. NumItems% = Ship.equipment: Item$ = "equipment"
  732. CASE "D"
  733. GOSUB MainMarket
  734. CASE ELSE
  735. GOSUB SellMenu
  736. END SELECT
  737. CalcSale:
  738. SPrice% = SellPrice%(Item$)
  739. LOCATE 18, 3: PRINT "You have "; NumItems%; " Units of " + Item$
  740. LOCATE 19, 3: PRINT Item$ + " is/are selling for "; SPrice%
  741. LOCATE 20, 3: INPUT "Number to Sell: ", d%
  742. IF d% <= NumItems% THEN
  743. AddCargo -d%, Item$, 1
  744. Credits! = Credits! + (SPrice% * d%)
  745. LOCATE 20, 3: PRINT TAB(6); "Items Sold: "; d%; Item$
  746. ELSEIF d% > NumItems% THEN
  747. LOCATE 20, 3: PRINT "You don't have that many " + Item$ + "."
  748. END IF
  749. WHILE INKEY$ = "": WEND
  750. GOSUB SellMenu
  751. 'This is the menu where one buys stuff.
  752. BuyMenu:
  753. CLS
  754. LINE (5, 5)-(315, 195), 5, B
  755. LOCATE 5, 3: PRINT USING "Free space: ####"; ShipFree%
  756. LOCATE 6, 3: PRINT USING "Credits: ##########"; FIX(Credits!)
  757. LOCATE 7, 3: PRINT "What do you want to buy?"
  758. 'Icon thingy again.
  759. IconPut 10, 10, Ports(City%).CType
  760. SELECT CASE Ports(City%).CType
  761. CASE "Agr"
  762. LOCATE 9, 4: PRINT "(W)heat"
  763. CASE "Ind"
  764. LOCATE 9, 4: PRINT "(L)uxury Goods"
  765. LOCATE 10, 4: PRINT "(E)quipment"
  766. CASE "Min"
  767. LOCATE 9, 4: PRINT "(O)re"
  768. CASE "Fun"
  769. LOCATE 9, 4: PRINT "Con(t)raband"
  770. END SELECT
  771. LOCATE 16, 4: PRINT "(D)one"
  772. SELECT CASE UCASE$(GetKey$)
  773. CASE "W"
  774. Item$ = "wheat"
  775. CASE "L"
  776. Item$ = "luxuries"
  777. CASE "E"
  778. Item$ = "equipment"
  779. CASE "O"
  780. Item$ = "ore"
  781. CASE "T"
  782. Item$ = "contraband"
  783. CASE "D"
  784. GOSUB MainMarket
  785. CASE ELSE
  786. GOSUB BuyMenu
  787. END SELECT
  788. CalcPurchase:
  789. BPrice% = BuyPrice%(Item$)
  790. IF BPrice% > 0 THEN
  791. LOCATE 18, 4: PRINT Item$ + " costs "; BPrice%; " per Unit."
  792. LOCATE 19, 4: PRINT "You can afford " + STR$(FIX(Credits! / BPrice%))
  793. LOCATE 20, 4: INPUT "Number to buy: ", d%
  794. IF (d% * BPrice%) <= Credits! THEN
  795. Credits! = Credits! - (d% * BPrice%)
  796. AddCargo d%, Item$, 1
  797. LOCATE 20, 4: PRINT "Number bought: "; d%
  798. IF ShipFree% < 0 THEN
  799. LOCATE 21, 4: PRINT "Your ship is overloaded."
  800. END IF
  801. ELSEIF (d% * BPrice%) > Credits! AND ShipFree% >= d% THEN
  802. LOCATE 20, 4: PRINT "You can't afford that many."
  803. END IF
  804. ELSEIF BPrice% = 0 THEN
  805. GOSUB BuyMenu
  806. END IF
  807. WHILE INKEY$ = "": WEND
  808. GOSUB BuyMenu
  809. END SUB
  810. FUNCTION OpenMix1 (FileName$)
  811. DIM lbyte AS STRING * 1
  812. '(5) 5 char file id -+
  813. ' + |
  814. '(4) 2 integer file version + num files |= calculate
  815. '==== | file header
  816. ' 9 _|
  817. FileSizer = 10 'this is the header size + 1 (1 = starting location)
  818. DIM Dummy AS INTEGER 'just for info inside file that we don't need.
  819. mk = FREEFILE
  820. OPEN FileName$ + ".MIX" FOR BINARY AS mk
  821. IF LOF(mk) <= 0 THEN 'file doesn't exist!
  822. CLOSE
  823. KILL FileName$ + "MIX" ' kill file! (opening file that doesn't
  824. ' exist creates an empty file)
  825. OpenMix1 = -1
  826. EXIT FUNCTION
  827. END IF
  828. id$ = "" 'get file id, to check if it's MIX
  829. FOR I = 1 TO 5 'file...
  830. GET #mk, , lbyte
  831. id$ = id$ + lbyte
  832. NEXT I
  833. IF id$ <> "QBMIX" THEN 'if it's not, EXIT!!!!
  834. OpenMix1 = -2
  835. EXIT FUNCTION
  836. END IF
  837. DIM vers AS INTEGER
  838. GET #mk, , vers 'get version
  839. IF vers <> 1 THEN 'we know how to open only version 1
  840. OpenMix1 = -3
  841. EXIT FUNCTION
  842. END IF
  843. GET #mk, , FilesNumber 'number of pictures inside MIX
  844. IF FilesNumber > MaxMIX OR FilesNumber <= 0 THEN
  845. OpenMix1 = -4 'if it's too big or too small, exit!
  846. EXIT FUNCTION
  847. END IF 'until now file header
  848. FOR I = 1 TO FilesNumber
  849. 'file name (8 bytes)
  850. FOR d = 1 TO 8 'read file name. It's not useful here, so
  851. GET #mk, , lbyte 'we just use a dummy.
  852. FileSizer = FileSizer + 1 'we read one byte at a time.
  853. NEXT d
  854. GET #mk, , ArraySize(I) 'read array size
  855. GET #mk, , Dummy 'read x size
  856. GET #mk, , Dummy 'read y size (we use a dummy)
  857. FileSizer = FileSizer + 6 'we read 3 integers that are 2 bytes
  858. NEXT I 'each.
  859. 'now we have to calculate the place of each picture
  860. 'inside the file
  861. FOR I = 1 TO FilesNumber
  862. StartRead(I) = FileSizer 'array place in bytes
  863. FileSizer = FileSizer + (ArraySize(I) * 2) 'because integer = 2
  864. NEXT I 'bytes
  865. END FUNCTION
  866. SUB PalLoad (PalFile$)
  867. CLOSE
  868. OPEN PalFile$ + ".PAL" FOR BINARY AS #1
  869. IF LOF(1) = 0 THEN
  870. CLOSE #1
  871. KILL PalFile$ + ".PAL"
  872. EXIT SUB
  873. END IF
  874. CLOSE #1
  875. OPEN PalFile$ + ".PAL" FOR INPUT AS #1
  876. FOR I = 1 TO 768
  877. INPUT #1, pal(I)
  878. NEXT I
  879. CLOSE #1
  880. num = 1
  881. an = 1
  882. DO
  883. pall(an).r = pal(num)
  884. num = num + 1
  885. pall(an).g = pal(num)
  886. num = num + 1
  887. pall(an).B = pal(num)
  888. num = num + 1
  889. an = an + 1
  890. LOOP UNTIL num > 768
  891. OUT &H3C7, 0: OUT &H3C8, 0
  892. FOR a% = 1 TO 256 * 3:
  893. OUT &H3C9, pal(a%)
  894. NEXT a%
  895. END SUB
  896. SUB Pause (delay!)
  897. 'This sub just delays for the specified amount of time. Found it in an ABC
  898. 'packet. Seems like a good method.
  899. t! = INT(TIMER)
  900. IF delay! >= 1 THEN
  901. DO
  902. IF t! <> INT(TIMER) THEN
  903. t! = INT(TIMER)
  904. count = count + 1
  905. END IF
  906. LOOP UNTIL count = delay!
  907. ELSEIF delay! < 1 THEN
  908. DO
  909. IF t! <> TIMER THEN
  910. t! = TIMER
  911. count = count + .1
  912. END IF
  913. LOOP UNTIL count = delay!
  914. END IF
  915. END SUB
  916. SUB SeaBattle (PType%, PGuns%)
  917. CLS
  918. LINE (5, 5)-(315, 195), 5, B
  919. SELECT CASE PType%
  920. CASE 1
  921. 'Pirates
  922. EnemyHealth = 40
  923. PDistance = 3
  924. END SELECT
  925. DO
  926. CLS
  927. LINE (5, 5)-(315, 195), 5, B
  928. LINE (5, 110)-(315, 110), 5
  929. 'PUT the cannons
  930. FOR PutIcon% = 1 TO Ship.cannon
  931. PUT (3 + (16 * PutIcon%), 3), cannon%
  932. NEXT PutIcon%
  933. 'PUT the ships.
  934. SELECT CASE PDistance
  935. CASE 3
  936. sX = 25: psX = 215
  937. CASE 2
  938. sX = 45: psX = 185
  939. CASE 1
  940. sX = 70: psX = 150
  941. END SELECT
  942. PUT (sX, 40), BigShipPic%
  943. SELECT CASE PType%
  944. CASE 1
  945. PUT (psX, 40), PirateShipPic%
  946. END SELECT
  947. 'Damage bar
  948. IF Ship.damage > 50 THEN
  949. COLOR 32
  950. ELSE
  951. COLOR 40
  952. END IF
  953. DamagePercent = (Ship.damage / 100) * 100
  954. LOCATE 15, 2: PRINT STRING$((Ship.damage / 4), 219) + " -" + STR$(DamagePercent) + "%"
  955. COLOR TextCol%
  956. 'Here's where the pirates fire at you.
  957. Hits = 0
  958. LOCATE 17, 2: PRINT "They're firing!" + STRING$(10, " ")
  959. FOR Shoot = 1 TO PGuns%
  960. 'The chance they'll actually have a hit.
  961. RANDOMIZE TIMER: HitChance = (RND * 100)
  962. IF PDistance = 1 THEN
  963. IF HitChance >= 15 THEN
  964. 'The most damage, and it's pretty hard to miss. Of course, at this
  965. 'range, it becomes a simple pounding match.
  966. Ship.damage = Ship.damage - 9
  967. Hits = Hits + 1
  968. END IF
  969. ELSEIF PDistance = 2 THEN
  970. IF HitChance >= 35 THEN
  971. Hits = Hits + 1
  972. 'Quite a bit better chance of a hit, and more damage.
  973. Ship.damage = Ship.damage - 7
  974. END IF
  975. ELSEIF PDistance = 3 THEN
  976. IF HitChance >= 72 THEN
  977. Hits = Hits + 1
  978. 'Further away, they have less chance of a hit, and do less damage.
  979. Ship.damage = Ship.damage - 5
  980. END IF
  981. END IF
  982. NEXT Shoot
  983. IF Hits >= 1 THEN
  984. SELECT CASE PDistance
  985. CASE 3
  986. FireCannon psX, 70, 40, 120, 3, sX, psX
  987. CASE 2
  988. FireCannon psX, 70, 35, 140, 3, sX, psX
  989. CASE 1
  990. FireCannon psX, 70, 30, 120, 3, sX, psX
  991. END SELECT
  992. ELSE
  993. RANDOMIZE TIMER: shotSpeedRnd = (RND * 10)
  994. SELECT CASE PDistance
  995. CASE 3
  996. FireCannon psX, 70, 20 + shotSpeedRnd, 125, 4, sX, psX
  997. CASE 2
  998. FireCannon psX, 70, 13 + shotSpeedRnd, 137, 4, sX, psX
  999. CASE 1
  1000. FireCannon psX, 70, 2, 90, 4, sX, psX
  1001. END SELECT
  1002. END IF
  1003. LOCATE 19, 3: PRINT Hits; "of"; PGuns%; "shots hit us."
  1004. Pause 2
  1005. 'Combat menus.
  1006. 'Do the damage bar again, test for death.
  1007. IF Ship.damage <= 0 THEN
  1008. 'You've been sunk.
  1009. EndBattle% = 1: GOSUB EndBattleLoop
  1010. ELSEIF Ship.damage > 50 THEN
  1011. COLOR 32
  1012. ELSE
  1013. COLOR 40
  1014. END IF
  1015. BlockPrint 15, 2, 21, 40, " "
  1016. DamagePercent = (Ship.damage / 100) * 100
  1017. LOCATE 15, 2: PRINT STRING$((Ship.damage / 4), 219) + " -" + STR$(DamagePercent) + "%"
  1018. COLOR TextCol%
  1019. LOCATE 17, 2: PRINT "What do you want to do?"
  1020. 'If you've got cannons, show the menu option to fire them.
  1021. IF Ship.cannon > 0 THEN
  1022. LOCATE 19, 2: PRINT "(F)ire Cannon"
  1023. IF Ship.cannon > 1 THEN LOCATE 19, 15: PRINT "s"
  1024. END IF
  1025. 'Move away from the enemy ship. If you're far enough away, this attempts
  1026. 'to escape.
  1027. IF PDistance = 3 THEN
  1028. LOCATE 20, 2: PRINT "Run (A)way"
  1029. ELSE
  1030. LOCATE 20, 2: PRINT "Move (A)way"
  1031. END IF
  1032. 'Move towards the pirate ship.
  1033. IF PDistance > 1 THEN
  1034. LOCATE 21, 2: PRINT "Move (C)loser"
  1035. 'If you're close enough to the enemy ship, then you can ram them, or
  1036. 'attempt to board.
  1037. 'ELSEIF PDistance = 1 THEN
  1038. ' LOCATE 21, 2: PRINT "(R)am"
  1039. ' LOCATE 22, 2: PRINT "(B)oard"
  1040. END IF
  1041. SeaBattleInput:
  1042. SELECT CASE UCASE$(GetKey$)
  1043. CASE "F"
  1044. 'Fire your cannon
  1045. IF Ship.cannon > 0 THEN
  1046. 'Clear the menu.
  1047. BlockPrint 17, 2, 22, 32, " "
  1048. Hits = 0
  1049. FOR Shoot = 1 TO Ship.cannon
  1050. BlockPrint 17, 2, 19, 32, " "
  1051. LOCATE 17, 2: PRINT "We're firing..." + STRING$(10, " ")
  1052. 'The chance you'll actually have a hit.
  1053. RANDOMIZE TIMER: HitChance = (RND * 100)
  1054. IF PDistance = 1 THEN
  1055. IF HitChance >= 15 THEN
  1056. Hits = Hits + 1
  1057. EnemyHealth = EnemyHealth - 9
  1058. END IF
  1059. ELSEIF PDistance = 2 THEN
  1060. IF HitChance >= 35 THEN
  1061. Hits = Hits + 1
  1062. EnemyHealth = EnemyHealth - 7
  1063. END IF
  1064. ELSEIF PDistance = 3 THEN
  1065. IF HitChance >= 72 THEN
  1066. Hits = Hits + 1
  1067. EnemyHealth = EnemyHealth - 5
  1068. END IF
  1069. END IF
  1070. NEXT Shoot
  1071. IF Hits >= 1 THEN
  1072. OldEnemyHealth = EnemyHealth
  1073. SELECT CASE PDistance
  1074. CASE 3
  1075. FireCannon 80, 70, 40, 30, 1, sX, psX
  1076. CASE 2
  1077. FireCannon 100, 70, 40, 30, 1, sX, psX
  1078. CASE 1
  1079. FireCannon 135, 70, 15, 10, 1, sX, psX
  1080. END SELECT
  1081. ELSE
  1082. RANDOMIZE TIMER: shotSpeedRnd = (RND * 10)
  1083. SELECT CASE PDistance
  1084. CASE 3
  1085. FireCannon 80, 70, 20 + shotSpeedRnd, 35, 2, sX, psX
  1086. CASE 2
  1087. FireCannon 100, 70, 13 + shotSpeedRnd, 47, 2, sX, psX
  1088. CASE 1
  1089. FireCannon 135, 70, 2, 90, 2, sX, psX
  1090. END SELECT
  1091. END IF
  1092. LOCATE 19, 3: PRINT Hits; "of"; Ship.cannon; "hit them."
  1093. Pause 1
  1094. ELSE
  1095. GOSUB SeaBattleInput
  1096. END IF
  1097. CASE "C"
  1098. 'Move closer to the enemy ship
  1099. IF PDistance > 1 THEN
  1100. PDistance = PDistance - 1
  1101. ELSE
  1102. GOSUB SeaBattleInput
  1103. END IF
  1104. CASE "A"
  1105. 'Move away from the enemy ship, if you're far enough, attempt to escape
  1106. 'completely.
  1107. IF PDistance < 3 THEN
  1108. PDistance = PDistance + 1
  1109. ELSEIF PDistance = 3 THEN
  1110. 'The "run away" code goes here
  1111. RANDOMIZE TIMER: EscapeChance% = INT(RND * 100)
  1112. IF ShipFree% = Ship.capacity AND EscapeChance% >= 30 THEN
  1113. EndBattle% = 3
  1114. GOSUB EndBattleLoop
  1115. ELSEIF ShipFree% < (Ship.capacity / 2) AND EscapeChance% >= 50 THEN
  1116. EndBattle% = 3
  1117. GOSUB EndBattleLoop
  1118. ELSEIF ShipFree% < (Ship.capacity / 4) AND EscapeChance% >= 70 THEN
  1119. EndBattle% = 3
  1120. GOSUB EndBattleLoop
  1121. END IF
  1122. END IF
  1123. CASE ELSE
  1124. GOSUB SeaBattleInput
  1125. END SELECT
  1126. 'Decide whether or not to end the battle, and if so how much money you
  1127. 'make from it, etc.
  1128. IF Ship.damage <= 0 THEN
  1129. EndBattle% = 1
  1130. GOSUB EndBattleLoop
  1131. END IF
  1132. IF EnemyHealth <= 0 THEN
  1133. EndBattle% = 2
  1134. GOSUB EndBattleLoop
  1135. END IF
  1136. EndBattleLoop:
  1137. LOOP UNTIL EndBattle% > 0
  1138. SELECT CASE EndBattle%
  1139. CASE 1
  1140. 'You sink
  1141. GameOver 1
  1142. CASE 2
  1143. 'They sink
  1144. SELECT CASE PType%
  1145. CASE 1
  1146. RANDOMIZE TIMER: GainedCredits = INT(RND * 400)
  1147. RANDOMIZE TIMER: CargoToAdd = INT(RND * 3) + 1
  1148. RANDOMIZE TIMER: d% = INT(RND * ShipFree%)
  1149. SELECT CASE CargoToAdd
  1150. CASE 1
  1151. Item$ = "contraband"
  1152. CASE 2
  1153. Item$ = "luxuries"
  1154. CASE 3
  1155. Item$ = "ore"
  1156. END SELECT
  1157. BlockPrint 17, 2, 22, 32, " "
  1158. LOCATE 17, 2: PRINT "We sank them!"
  1159. LOCATE 19, 2: PRINT "We've captured"; GainedCredits; "in cash."
  1160. LOCATE 20, 2: PRINT "We've captured"; d%; "units of " + Item$
  1161. LOCATE 22, 2: PRINT "Do you want to keep it? (y/n)"
  1162. IF UCASE$(GetKey$) = "Y" THEN AddCargo d%, Item$, 1
  1163. CASE 2
  1164. END SELECT
  1165. CASE 3
  1166. 'You run
  1167. BlockPrint 17, 2, 22, 32, " "
  1168. LOCATE 17, 2: PRINT "We've escaped!"
  1169. END SELECT
  1170. END SUB
  1171. FUNCTION SellPrice% (Item$)
  1172. 'Returns a value for how much you can sell something for.
  1173. SELECT CASE Item$
  1174. CASE "cannon"
  1175. Price% = 100
  1176. CASE "wheat"
  1177. Price% = CurrentPrices.wheat
  1178. CASE "ore"
  1179. Price% = CurrentPrices.ore
  1180. CASE "luxuries"
  1181. Price% = CurrentPrices.luxuries
  1182. CASE "contraband"
  1183. Price% = CurrentPrices.contraband
  1184. CASE "equipment"
  1185. Price% = CurrentPrices.equipment
  1186. END SELECT
  1187. SellPrice% = Price%
  1188. END FUNCTION
  1189. SUB SetPrices (d%)
  1190. 'This sets the prices for all of the items at the marketplace.
  1191. 'For now it just takes into account the type of city and time of year,
  1192. 'but I plan on adding other economic factors.
  1193. Year = FIX((GameState.gameDate / 12)) + 1850
  1194. Month = GameState.gameDate - ((Year - 1850) * 12)
  1195. SELECT CASE Month
  1196. CASE 0 TO 5
  1197. WheatModifier = 3
  1198. CASE 6 TO 8
  1199. WheatModifier = 1
  1200. CASE 9 TO 11
  1201. WheatModifier = 2
  1202. END SELECT
  1203. SELECT CASE Ports(d%).CType
  1204. CASE "Agr"
  1205. RANDOMIZE TIMER: CurrentPrices.wheat = 1 + (INT(RND * 10) * WheatModifier)
  1206. RANDOMIZE TIMER: CurrentPrices.ore = 1 + INT(RND * 3)
  1207. RANDOMIZE TIMER: CurrentPrices.luxuries = 1 + INT(RND * 3)
  1208. RANDOMIZE TIMER: CurrentPrices.equipment = 500 + INT(RND * 2000)
  1209. CASE "Ind"
  1210. RANDOMIZE TIMER: CurrentPrices.wheat = 1 + INT(RND * 5)
  1211. RANDOMIZE TIMER: CurrentPrices.ore = 10 + INT(RND * 60)
  1212. RANDOMIZE TIMER: CurrentPrices.luxuries = 20 + INT(RND * 30)
  1213. RANDOMIZE TIMER: CurrentPrices.equipment = 500 + INT(RND * 800)
  1214. CASE "Min"
  1215. RANDOMIZE TIMER: CurrentPrices.wheat = 5 + (INT(RND * 20) * WheatModifier)
  1216. RANDOMIZE TIMER: CurrentPrices.ore = 2 + INT(RND * 25)
  1217. RANDOMIZE TIMER: CurrentPrices.luxuries = 1 + INT(RND * 16)
  1218. RANDOMIZE TIMER: CurrentPrices.equipment = 500 + INT(RND * 1000)
  1219. CASE "Fun"
  1220. RANDOMIZE TIMER: CurrentPrices.wheat = 1 + INT(RND * 6)
  1221. RANDOMIZE TIMER: CurrentPrices.ore = 1 + INT(RND * 3)
  1222. RANDOMIZE TIMER: CurrentPrices.luxuries = 5 + INT(RND * 50)
  1223. RANDOMIZE TIMER: CurrentPrices.equipment = 400
  1224. END SELECT
  1225. RANDOMIZE TIMER: CurrentPrices.contraband = 10 + INT(RND * 100)
  1226. END SUB
  1227. FUNCTION ShipFree%
  1228. 'Returns the amount of free space left in the ship.
  1229. Space = 0
  1230. Space% = Space% + Ship.cannon * 10
  1231. Space% = Space% + Ship.wheat + Ship.ore + Ship.luxuries + Ship.contraband + Ship.equipment
  1232. ShipFree% = Ship.capacity - Space%
  1233. END FUNCTION
  1234. SUB ShipMenu
  1235. MainShip:
  1236. CLS
  1237. LINE (5, 5)-(315, 195), 5, B
  1238. PUT (10, 10), ShipIcon%
  1239. 'Draw the cannons.
  1240. FOR PutIcon% = 1 TO Ship.cannon
  1241. PUT (30 + (16 * PutIcon%), 10), cannon%
  1242. NEXT PutIcon%
  1243. LOCATE 6, 3: PRINT "At ship in " + Ports(City%).CName
  1244. LOCATE 8, 3: PRINT "What do you want to do?"
  1245. LOCATE 10, 4: PRINT "1. Sail for Another Port"
  1246. LOCATE 11, 4: PRINT "2. Upgrade or Repair Ship"
  1247. LOCATE 12, 4: PRINT "3. Back to Main Menu"
  1248. SELECT CASE VAL(GetKey$)
  1249. CASE 1
  1250. GOSUB SailAway
  1251. CASE 2
  1252. GOSUB ShipYard
  1253. CASE 3
  1254. EXIT SUB
  1255. CASE ELSE
  1256. GOSUB MainShip
  1257. END SELECT
  1258. 'This menu lets you upgrade/repair your ship.
  1259. 'You can repair, buy cannons or a lifeboat, upgrade stuff, etc.
  1260. ShipYard:
  1261. CLS
  1262. LINE (5, 5)-(315, 195), 5, B
  1263. PUT (10, 10), ShipIcon%
  1264. 'Draw the cannons.
  1265. FOR PutIcon% = 1 TO Ship.cannon
  1266. PUT (30 + (16 * PutIcon%), 10), cannon%
  1267. NEXT PutIcon%
  1268. LOCATE 7, 3: PRINT "You have "; Ship.cannon; " Cannons."
  1269. LOCATE 8, 3: PRINT "Ship condition: " + STR$(Ship.damage) + "%"
  1270. LOCATE 9, 3: PRINT "You have "; Credits!; " Credits in cash."
  1271. LOCATE 11, 4: PRINT "1. Repair Damage - 30 Credits"
  1272. LOCATE 12, 4: PRINT "2. Buy a Cannon - 250 Credits"
  1273. LOCATE 14, 4: PRINT "3. Done"
  1274. SELECT CASE VAL(GetKey$)
  1275. CASE 1 'Repair the ship.
  1276. IF Ship.damage >= 100 THEN
  1277. LOCATE 16, 3: PRINT "Your ship is already repaired."
  1278. ELSEIF Ship.damage < 100 AND Credits! >= 30 THEN
  1279. Credits! = Credits! - 30
  1280. Ship.damage = Ship.damage + 10
  1281. IF Ship.damage > 100 THEN Ship.damage = 100
  1282. LOCATE 16, 3: PRINT "Repairs done."
  1283. END IF
  1284. WHILE INKEY$ = "": WEND
  1285. GOSUB ShipYard
  1286. CASE 2 'Buy a cannon
  1287. IF Credits! >= 250 AND ShipFree% >= 10 THEN
  1288. Credits! = Credits! - 250
  1289. AddCargo 1, "cannon", 1
  1290. LOCATE 16, 3: PRINT "Cannon Purchased"
  1291. ELSEIF (Credits! < 250) OR (ShipFree% < 10) THEN
  1292. LOCATE 16, 5: PRINT "You can't afford a new cannon."
  1293. END IF
  1294. WHILE INKEY$ = "": WEND
  1295. GOSUB ShipYard
  1296. CASE 3
  1297. GOSUB MainShip
  1298. CASE ELSE
  1299. GOSUB ShipYard
  1300. END SELECT
  1301. SailAway:
  1302. 'The menu of other ports to sail to. I'm sure there's a better way to do
  1303. 'this, but I have no idea what it is.
  1304. CLS
  1305. LINE (5, 5)-(315, 195), 5, B
  1306. PUT (10, 10), ShipIcon%
  1307. LOCATE 4, 6: PRINT "Where do you want to sail?"
  1308. IconPut 20, 44, Ports(1).CType
  1309. IconPut 20, 68, Ports(2).CType
  1310. IconPut 20, 92, Ports(3).CType
  1311. IconPut 20, 116, Ports(4).CType
  1312. IconPut 20, 140, Ports(5).CType
  1313. LOCATE 8, 7: PRINT "1. " + Ports(1).CName
  1314. LOCATE 11, 7: PRINT "2. " + Ports(2).CName
  1315. LOCATE 14, 7: PRINT "3. " + Ports(3).CName
  1316. LOCATE 17, 7: PRINT "4. " + Ports(4).CName
  1317. LOCATE 20, 7: PRINT "5. " + Ports(5).CName
  1318. IconPut 165, 44, Ports(6).CType
  1319. IconPut 165, 68, Ports(7).CType
  1320. IconPut 165, 92, Ports(8).CType
  1321. IconPut 165, 116, "cancel"
  1322. LOCATE 8, 25: PRINT "6. " + Ports(6).CName
  1323. LOCATE 11, 25: PRINT "7. " + Ports(7).CName
  1324. LOCATE 14, 25: PRINT "8. " + Ports(8).CName
  1325. LOCATE 17, 25: PRINT "9. Cancel"
  1326. d% = INT(VAL(GetKey$))
  1327. IF d% <= 9 AND d% >= 1 THEN
  1328. IF d% = City% THEN
  1329. LOCATE 23, 5: PRINT "You're already there!"
  1330. paws = TIMER: WHILE TIMER <= paws + 2: WEND
  1331. GOSUB SailAway
  1332. ELSEIF (d% <> City%) AND (ShipFree% < 0) THEN
  1333. LOCATE 22, 5: PRINT "Your ship is overloaded!"
  1334. LOCATE 23, 5: PRINT "Sell or move some cargo."
  1335. paws = TIMER: WHILE TIMER <= paws + 1: WEND
  1336. EXIT SUB
  1337. ELSEIF d% = 9 THEN
  1338. GOSUB MainShip
  1339. ELSE
  1340. GOSUB MovingShip
  1341. END IF
  1342. ELSE
  1343. GOSUB SailAway
  1344. END IF
  1345. 'Sail to whatever your port of choice is.
  1346. MovingShip:
  1347. CLS
  1348. LINE (5, 5)-(315, 195), 5, B
  1349. PUT (10, 10), ShipIcon%
  1350. 'Show the cannons.
  1351. FOR PutIcon% = 1 TO Ship.cannon
  1352. PUT (30 + (16 * PutIcon%), 10), cannon%
  1353. NEXT PutIcon%
  1354. LOCATE 5, 3: PRINT "Sailing to "; Ports(d%).CName
  1355. FOR MovingShip% = 5 TO 200 STEP 5
  1356. WAIT &H3DA, 8
  1357. PUT (25 + (MovingShip% - 5), 50), BigShipPic%
  1358. PUT (25 + MovingShip%, 50), BigShipPic%, PSET
  1359. Pause .3
  1360. IF MovingShip% = 85 THEN
  1361. SELECT CASE ShipFree%
  1362. CASE 0 TO (Ship.capacity / 4)
  1363. Chance = Chance + .4
  1364. CASE ((Ship.capacity / 4) + 1) TO (Ship.capacity / 2)
  1365. Chance = Chance + .3
  1366. CASE ((Ship.capacity / 2) + 1) TO ((Ship.capacity / 4) * 3)
  1367. Chance = Chance + .2
  1368. END SELECT
  1369. IF Ship.cannon >= 3 THEN Chance = Chance - (.1 * (INT(Ship.cannon / 3)))
  1370. RANDOMIZE TIMER: Attack = RND + Chance
  1371. IF GameState.paidPirates = 0 THEN
  1372. SELECT CASE Attack
  1373. CASE .85 TO .94
  1374. 'Start a battle
  1375. PAttacked% = 1
  1376. SeaBattle 1, 2
  1377. CASE .95
  1378. 'Start a battle
  1379. PAttacked% = 1
  1380. SeaBattle 1, 3
  1381. END SELECT
  1382. ELSEIF GameState.paidPirates = 1 THEN
  1383. IF Attack >= .99 THEN
  1384. 'Start a battle
  1385. PAttacked% = 1
  1386. SeaBattle 1, 2
  1387. END IF
  1388. END IF
  1389. IF PAttacked% = 1 THEN
  1390. CLS
  1391. LINE (5, 5)-(315, 195), 5, B
  1392. PUT (10, 10), ShipIcon%
  1393. 'Show the cannons.
  1394. FOR PutIcon% = 1 TO Ship.cannon
  1395. PUT (30 + (16 * PutIcon%), 10), cannon%
  1396. NEXT PutIcon%
  1397. LOCATE 5, 3: PRINT "Sailing to "; Ports(d%).CName
  1398. PUT (25 + MovingShip%, 50), BigShipPic%, PSET
  1399. END IF
  1400. END IF
  1401. NEXT MovingShip%
  1402. RANDOMIZE TIMER: Storm = RND
  1403. IF Storm >= .8 THEN
  1404. StormCity% = 0
  1405. StormRnd = 0
  1406. CLS
  1407. LINE (5, 5)-(315, 195), 5, B
  1408. PUT (130, 30), StormPic%
  1409. LOCATE 19, 3: PRINT "Storm!"
  1410. Pause 1
  1411. 'Calculate the effects of a storm.
  1412. RANDOMIZE TIMER: StormRnd = RND * 10
  1413. Ship.damage = Ship.damage - INT(StormRnd)
  1414. LOCATE 21, 3: PRINT "The ship has taken " + STR$(INT(StormRnd)) + " Damage."
  1415. IF Ship.damage <= 0 THEN
  1416. 'You're sunk.
  1417. GameOver 2
  1418. END IF
  1419. RANDOMIZE TIMER: StormRnd = RND
  1420. IF StormRnd >= .6 THEN
  1421. StormCity% = d% + 1
  1422. IF StormCity% > 8 THEN StormCity% = d% - 1
  1423. d% = StormCity%
  1424. LOCATE 23, 3: PRINT "We've been blown to " + Ports(d%).CName
  1425. END IF
  1426. WHILE INKEY$ = "": WEND
  1427. END IF
  1428. 'Finished sailing, arrived without being killed, etc...
  1429. 'This sub calculates interest at the bank, advances the date, triggers events,
  1430. 'etc.
  1431. Events d%
  1432. City% = d%: EXIT SUB
  1433. END SUB
  1434. FUNCTION WareFree%
  1435. 'Returns the amount of free space left in the warehouse.
  1436. Space = 0
  1437. Space% = Space% + WareHouse.cannon * 10
  1438. Space% = Space% + WareHouse.wheat + WareHouse.ore + WareHouse.luxuries + WareHouse.contraband + WareHouse.equipment
  1439. WareFree% = WareHouse.capacity - Space%
  1440. END FUNCTION
  1441. SUB WarehouseMenu
  1442. MainWarehouse:
  1443. CLS
  1444. LINE (5, 5)-(315, 195), 5, B
  1445. 'Draw the city icon thingy.
  1446. IconPut 10, 10, Ports(City%).CType
  1447. LOCATE 5, 3: PRINT "You are at your warehouse."
  1448. LOCATE 7, 3: PRINT " Cargo Free"
  1449. LOCATE 8, 3: PRINT USING "Ship: #### ####"; (Ship.capacity - ShipFree%); ShipFree%
  1450. LOCATE 9, 3: PRINT USING "Warehouse: ##### #####"; (WareHouse.capacity - WareFree%); WareFree%
  1451. LOCATE 11, 3: PRINT "What do you want to do?"
  1452. LOCATE 13, 4: PRINT "1. Transfer to ship"
  1453. LOCATE 14, 4: PRINT "2. Transfer from ship"
  1454. LOCATE 15, 4: PRINT "3. Back to Main Menu"
  1455. SELECT CASE VAL(GetKey$)
  1456. CASE 1
  1457. GOSUB MoveToShip
  1458. CASE 2
  1459. GOSUB MoveFromShip
  1460. CASE 3
  1461. EXIT SUB
  1462. CASE ELSE
  1463. END SELECT
  1464. MoveToShip:
  1465. CLS
  1466. LINE (5, 5)-(315, 195), 5, B
  1467. LOCATE 5, 3: PRINT "What do you want to transfer?"
  1468. LOCATE 7, 4: PRINT "Item No."
  1469. IF WareHouse.cannon > 0 THEN LOCATE 9, 4: PRINT USING "(C)annon ####"; WareHouse.cannon
  1470. IF WareHouse.wheat > 0 THEN LOCATE 10, 4: PRINT USING "(W)heat ####"; WareHouse.wheat
  1471. IF WareHouse.ore > 0 THEN LOCATE 11, 4: PRINT USING "(O)re ####"; WareHouse.ore
  1472. IF WareHouse.luxuries > 0 THEN LOCATE 12, 4: PRINT USING "(L)uxury Goods ####"; WareHouse.luxuries
  1473. IF WareHouse.contraband > 0 THEN LOCATE 13, 4: PRINT USING "Con(t)raband ####"; WareHouse.contraband
  1474. IF WareHouse.equipment > 0 THEN LOCATE 14, 4: PRINT USING "(E)quipment ####"; WareHouse.equipment
  1475. LOCATE 16, 4: PRINT "(D)one"
  1476. 'There has *got* to be a better way to do this...
  1477. SELECT CASE UCASE$(GetKey$)
  1478. CASE "C"
  1479. NumItems% = WareHouse.cannon: Item$ = "cannon"
  1480. CASE "W"
  1481. NumItems% = WareHouse.wheat: Item$ = "wheat"
  1482. CASE "O"
  1483. NumItems% = WareHouse.ore: Item$ = "ore"
  1484. CASE "L"
  1485. NumItems% = WareHouse.luxuries: Item$ = "luxuries"
  1486. CASE "T"
  1487. NumItems% = WareHouse.contraband: Item$ = "contraband"
  1488. CASE "E"
  1489. NumItems% = WareHouse.equipment: Item$ = "equipment"
  1490. CASE "D"
  1491. GOSUB MainWarehouse
  1492. CASE ELSE
  1493. GOSUB MoveToShip
  1494. END SELECT
  1495. LOCATE 18, 3: PRINT "You have "; NumItems%; " Units of " + Item$
  1496. LOCATE 19, 3: INPUT "Number to move aboard ship: ", d%
  1497. IF d% <= NumItems% AND d% <= ShipFree% THEN
  1498. AddCargo d%, Item$, 1
  1499. AddCargo -d%, Item$, 2
  1500. LOCATE 20, 3: PRINT TAB(6); "Items Moved: "; d%; Item$
  1501. ELSEIF d% > NumItems% THEN
  1502. LOCATE 20, 3: PRINT "You don't have that many " + Item$ + "."
  1503. END IF
  1504. WHILE INKEY$ = "": WEND
  1505. GOSUB MainWarehouse
  1506. 'Move stuff from the ship into the warehouse.
  1507. MoveFromShip:
  1508. CLS
  1509. LINE (5, 5)-(315, 195), 5, B
  1510. LOCATE 5, 3: PRINT "What do you want to transfer?"
  1511. LOCATE 7, 4: PRINT "Item No."
  1512. IF Ship.cannon > 0 THEN LOCATE 9, 4: PRINT USING "(C)annon ####"; Ship.cannon
  1513. IF Ship.wheat > 0 THEN LOCATE 10, 4: PRINT USING "(W)heat ####"; Ship.wheat
  1514. IF Ship.ore > 0 THEN LOCATE 11, 4: PRINT USING "(O)re ####"; Ship.ore
  1515. IF Ship.luxuries > 0 THEN LOCATE 12, 4: PRINT USING "(L)uxury Goods ####"; Ship.luxuries
  1516. IF Ship.contraband > 0 THEN LOCATE 13, 4: PRINT USING "Con(t)raband ####"; Ship.contraband
  1517. IF Ship.equipment > 0 THEN LOCATE 14, 4: PRINT USING "(E)quipment ####"; Ship.equipment
  1518. SELECT CASE UCASE$(GetKey$)
  1519. CASE "C"
  1520. NumItems% = Ship.cannon: Item$ = "cannon"
  1521. CASE "W"
  1522. NumItems% = Ship.wheat: Item$ = "wheat"
  1523. CASE "O"
  1524. NumItems% = Ship.ore: Item$ = "ore"
  1525. CASE "L"
  1526. NumItems% = Ship.luxuries: Item$ = "luxuries"
  1527. CASE "T"
  1528. NumItems% = Ship.contraband: Item$ = "contraband"
  1529. CASE "E"
  1530. NumItems% = Ship.equipment: Item$ = "equipment"
  1531. CASE "D"
  1532. CASE ELSE
  1533. END SELECT
  1534. LOCATE 18, 3: PRINT "You have "; NumItems%; " Units of " + Item$
  1535. LOCATE 19, 3: INPUT "Number to move to warehouse: ", d%
  1536. IF d% <= NumItems% AND d% <= WareFree% THEN
  1537. AddCargo -d%, Item$, 1
  1538. AddCargo d%, Item$, 2
  1539. LOCATE 20, 3: PRINT TAB(6); "Items Moved: "; d%; Item$
  1540. ELSEIF d% > NumItems% THEN
  1541. LOCATE 20, 3: PRINT "You don't have that many " + Item$ + "."
  1542. END IF
  1543. WHILE INKEY$ = "": WEND
  1544. GOSUB MainWarehouse
  1545. END SUB