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

' ***************
' * T R A D E R *
' * v1.0 *
' ***************
'
' Copyright 1997 Brennen Bearnes
' This is an attempted clone of an old Apple II game called Taipan, in which
' you sailed around, traded in stuff, and battled pirates. Copy and
' distribute as you like, provided you distribute the original unmodified
' archive (trader.zip).
' NOTES:
' I started this for the last Retro Compo on comp.lang.basic.misc (which got
' something like 3 entries), and it's been sitting there unfinished for
' months. There's quite a bit of stuff I'd like to add, but I figured I
' ought to release what I have. Below is a list of things I'd like to
' complete for version 2.0.
' Stuff that needs done:
' - A story (sort of have one worked out)
' - More enemies
' - Cannon and armor upgrades, etc.
' - More locations within cities
' - More/better graphics
' - End game animations
' The graphics (such as they are), were done with Lior Zur's excellent QBdraw.
' It can be found at:
' http://www.geocities.com/SiliconValley/Heights/9246/
' Comments/ideas/suggestions are, as always, welcome.
' --
' Brennen Bearnes | bbearnes@hardlink.com
' http://www.hardlink.com/~bbearnes/
' ********
' * SUBs *
' ********
DECLARE SUB AddCargo (d%, Item$, AddToPlace%)
DECLARE SUB BankMenu ()
DECLARE SUB BlockPrint (StartY%, StartX%, EndY%, EndX%, ReplaceChar$)
DECLARE SUB Events (d%)
DECLARE SUB FLoad (FileOffset&, DataLength&, Pic1%())
DECLARE SUB FireCannon (startShotX!, startShotY!, shotSpeed!, shotAngle!, FireType, sX, psX)
DECLARE SUB GameOver (OverType%)
DECLARE SUB IconLoad (LoadIcon%, LIType%)
DECLARE SUB IconPut (IconPutX%, IconPutY%, IconPut$)
DECLARE SUB MainMenu ()
DECLARE SUB MarketMenu ()
DECLARE SUB PalLoad (PalFile$)
DECLARE SUB Pause (delay!)
DECLARE SUB ReadIcon ()
DECLARE SUB SeaBattle (PType%, PGuns%)
DECLARE SUB SetPrices (d%)
DECLARE SUB ShipMenu ()
DECLARE SUB WarehouseMenu ()
' *************
' * FUNCTIONs *
' *************
DECLARE FUNCTION BuyPrice% (Item$)
DECLARE FUNCTION GetKey$ ()
DECLARE FUNCTION OpenMix1! (FileName$)
DECLARE FUNCTION SellPrice% (Item$)
DECLARE FUNCTION ShipFree% ()
DECLARE FUNCTION WareFree% ()
' *********
' * TYPEs *
' *********
TYPE World
paidPirates AS INTEGER
gameDate AS INTEGER
END TYPE
TYPE Storage
capacity AS INTEGER
cannon AS INTEGER
wheat AS INTEGER
ore AS INTEGER
luxuries AS INTEGER
contraband AS INTEGER
equipment AS INTEGER
damage AS INTEGER
END TYPE
TYPE CityType
CName AS STRING * 11
CType AS STRING * 3
Hidden AS INTEGER
END TYPE
TYPE PalType
r AS INTEGER
g AS INTEGER
B AS INTEGER
END TYPE
' *************
' * Variables *
' *************
'The default text color.
DIM SHARED TextCol%
TextCol% = 4
'World data. Basically, all the misc. stuff that's going on in the game.
DIM SHARED GameState AS World
'Holds data for the cities you can travel to.
DIM SHARED Ports(8) AS CityType
'Storage variables.
DIM SHARED WareHouse AS Storage
DIM SHARED Ship AS Storage
DIM SHARED CurrentPrices AS Storage
'Misc. stuff.
DIM SHARED Credits!, City%, Bank!
DIM SHARED PName$
'QBdraw MIX loader variables.
CONST MaxMIX = 30 'Max files in a MIX file.
DIM SHARED DimSize AS INTEGER
DIM SHARED pall(256) AS PalType
DIM SHARED pal(768)
DIM SHARED FileSizer AS INTEGER 'The file's number of bytes counter.
DIM SHARED FilesNumber AS INTEGER 'number of picture files in the MIX
DIM SHARED ArraySize(MaxMIX) AS INTEGER 'array size of each file
DIM SHARED StartRead(MaxMIX) AS INTEGER 'start reading place
'For the cannon ball drawing code.
CONST PI = 3.141592654#
SCREEN 13
PalLoad "draw" 'load palette
CLOSE
N = OpenMix1("icon") 'open the MIX file and get variables.
IF N = 0 THEN 'if no errors
DIM SHARED ShipIcon%(ArraySize(1))
DIM SHARED PirateIcon%(ArraySize(2))
DIM SHARED cannon%(ArraySize(3))
DIM SHARED IndIcon%(ArraySize(4))
DIM SHARED AgrIcon%(ArraySize(5))
DIM SHARED MinIcon%(ArraySize(6))
DIM SHARED FunIcon%(ArraySize(7))
DIM SHARED Splash%(ArraySize(8))
DIM SHARED Cancel%(ArraySize(9))
DIM SHARED TavernSign%(ArraySize(10))
DIM SHARED WareHouseIcon%(ArraySize(11))
DIM SHARED BankSign%(ArraySize(12))
FOR LoadIcon% = 1 TO 12
IconLoad LoadIcon%, 1
NEXT LoadIcon%
END IF
CLOSE
'Load larger graphics. (just 4, so far.)
N = OpenMix1("bigpics") 'open the MIX file and get variables.
IF N = 0 THEN 'if no errors
DIM SHARED BigShipPic%(ArraySize(1))
DIM SHARED PirateShipPic%(ArraySize(2))
DIM SHARED StormPic%(ArraySize(3))
DIM SHARED PatrolShipPic%(ArraySize(4))
FOR LoadIcon% = 1 TO 4
IconLoad LoadIcon%, 2
NEXT LoadIcon%
END IF
CLOSE
'The main game menu.
MainMenu
'Starting stuff. How much your warehouse/ship can hold, what stuff you start
'out with, what things cost at the beginning.
WareHouse.capacity = 1000
Ship.damage = 100
Ship.capacity = 100
Ship.cannon = 3
Ship.ore = 5
Credits! = 50
CurrentPrices.wheat = 4
CurrentPrices.ore = 45
CurrentPrices.luxuries = 30
CurrentPrices.contraband = 150
CurrentPrices.equipment = 1000
'Set the date to -1 so that you start out in January.
GameState.gameDate = -1
'Read the cities. First is always "home base".
FOR LoadCity% = 1 TO 8
READ Ports(LoadCity%).CName
READ Ports(LoadCity%).CType
NEXT LoadCity%
City% = 1
CLS
' *******************
' * Main game loop. *
' *******************
CityMenu:
CLS
'PUT the city icon
IconPut 10, 10, Ports(City%).CType
LINE (5, 5)-(315, 195), 5, B
LOCATE 4, 6: PRINT "You are in the city of "; Ports(City%).CName
LOCATE 7, 3: PRINT "Where do you want to go?"
IconPut 20, 68, Ports(City%).CType
LOCATE 11, 7: PRINT "1. The Marketplace"
IconPut 20, 92, "ship"
LOCATE 14, 7: PRINT "2. Your Ship"
IF City% = 1 THEN
IconPut 20, 116, "warehouse"
LOCATE 17, 7: PRINT "3. Your Warehouse"
IconPut 20, 140, "banksign"
LOCATE 20, 7: PRINT "4. The Bank"
END IF
SELECT CASE UCASE$(GetKey$)
CASE "1"
MarketMenu
CASE "2"
ShipMenu
CASE "3"
IF City% = 1 THEN
WarehouseMenu
ELSE
GOSUB CityMenu
END IF
CASE "4"
IF City% = 1 THEN
BankMenu
ELSE
GOSUB CityMenu
END IF
CASE CHR$(27)
LOCATE 22, 4: PRINT "Do you want to quit?"
SELECT CASE UCASE$(GetKey$)
CASE "Y"
LOCATE 22, 25: PRINT "Y"
Pause 1
END
CASE ELSE
GOSUB CityMenu
END SELECT
END SELECT
GOSUB CityMenu
' ********
' * DATA *
' ********
'city data
'Format: Name, type
'Agr is Agricultural
'Min is Mining
'Ind is industrial, or manufacturing.
'Fun is a pleasure city or resort.
DATA "Smogville", "Ind"
DATA "Cowstown", "Agr"
DATA "Millwater", "Ind"
DATA "Rockton", "Min"
DATA "Grainville", "Agr"
DATA "Silvercreek", "Min"
DATA "Coalburgh", "Ind"
DATA "Utopia", "Fun"
SUB AddCargo (d%, Item$, AddToPlace%)
SELECT CASE AddToPlace%
CASE 1
SELECT CASE Item$
CASE "cannon"
Ship.cannon = Ship.cannon + d%
CASE "wheat"
Ship.wheat = Ship.wheat + d%
CASE "ore"
Ship.ore = Ship.ore + d%
CASE "luxuries"
Ship.luxuries = Ship.luxuries + d%
CASE "contraband"
Ship.contraband = Ship.contraband + d%
CASE "equipment"
Ship.equipment = Ship.equipment + d%
END SELECT
CASE 2
SELECT CASE Item$
CASE "cannon"
WareHouse.cannon = WareHouse.cannon + d%
CASE "wheat"
WareHouse.wheat = WareHouse.wheat + d%
CASE "ore"
WareHouse.ore = WareHouse.ore + d%
CASE "luxuries"
WareHouse.luxuries = WareHouse.luxuries + d%
CASE "contraband"
WareHouse.contraband = WareHouse.contraband + d%
CASE "equipment"
WareHouse.equipment = WareHouse.equipment + d%
END SELECT
END SELECT
END SUB
SUB BankMenu
MainBank:
CLS
LINE (5, 5)-(315, 195), 5, B
IconPut 10, 10, "banksign"
LOCATE 4, 6: PRINT "The Bank in " + Ports(City%).CName
LOCATE 7, 3: PRINT "Your account contains"; FIX(Bank!); "Credits."
LOCATE 8, 3: PRINT "You have "; FIX(Credits!); " Credits in Cash."
LOCATE 10, 4: PRINT "1. Withdraw Cash"
LOCATE 11, 4: PRINT "2. Deposit Cash"
LOCATE 12, 4: PRINT "3. Back to Main Menu"
SELECT CASE VAL(GetKey$)
CASE 1
LOCATE 14, 5: INPUT "Enter amount to withdraw: ", Transaction!
IF Transaction! > Bank! THEN
LOCATE 16, 7: PRINT "Your account isn't that big."
WHILE INKEY$ = "": WEND
ELSEIF Transaction! <= Bank! THEN
Bank! = Bank! - Transaction!
Credits! = Credits! + Transaction!
LOCATE 16, 7: PRINT "Thanks for your business."
WHILE INKEY$ = "": WEND
END IF
GOSUB MainBank
CASE 2
LOCATE 14, 5: INPUT "Enter amount to deposit: ", Transaction!
IF Transaction! > Credits! THEN
LOCATE 16, 7: PRINT "You don't have that many credits."
WHILE INKEY$ = "": WEND
ELSEIF Transaction! <= Credits! THEN
Bank! = Bank! + Transaction!
Credits! = Credits! - Transaction!
LOCATE 16, 7: PRINT "Thanks for your business."
WHILE INKEY$ = "": WEND
END IF
GOSUB MainBank
CASE 3
EXIT SUB
CASE ELSE
GOSUB MainBank
END SELECT
END SUB
SUB BlockPrint (StartY%, StartX%, EndY%, EndX%, ReplaceChar$)
'This little sub just prints a block of the specified character at the
'given coordinates. I use it for clearing a section of the screen, such as
'a menu.
FOR PrintLine% = StartY% TO EndY%
LOCATE PrintLine%, StartX%: PRINT STRING$((EndX% - StartX%), ReplaceChar$)
NEXT PrintLine%
END SUB
FUNCTION BuyPrice% (Item$)
'Returns the cost to buy cargo.
SELECT CASE Ports(City%).CType
CASE "Agr"
SELECT CASE Item$
CASE "cannon"
Price% = 0
CASE "wheat"
Price% = CurrentPrices.wheat
CASE "ore"
Price% = 0
CASE "luxuries"
Price% = 0
CASE "contraband"
Price% = 0
CASE "equipment"
Price% = 0
END SELECT
CASE "Ind"
SELECT CASE Item$
CASE "cannon"
Price% = 0
CASE "wheat"
Price% = 0
CASE "ore"
Price% = 0
CASE "luxuries"
Price% = CurrentPrices.luxuries
CASE "contraband"
Price% = 0
CASE "equipment"
Price% = CurrentPrices.equipment
END SELECT
CASE "Min"
SELECT CASE Item$
CASE "cannon"
Price% = 0
CASE "wheat"
Price% = 0
CASE "ore"
Price% = CurrentPrices.ore
CASE "luxuries"
Price% = 0
CASE "contraband"
Price% = 0
CASE "equipment"
Price% = 0
END SELECT
CASE "Fun"
SELECT CASE Item$
CASE "cannon"
Price% = 0
CASE "wheat"
Price% = 0
CASE "ore"
Price% = 0
CASE "luxuries"
Price% = 0
CASE "contraband"
Price% = CurrentPrices.contraband
CASE "equipment"
Price% = 0
END SELECT
END SELECT
BuyPrice% = Price%
END FUNCTION
SUB Events (d%)
'This sub does all the stuff after you complete a voyage. Interest at the
'bank, the date, calls SetPrices, etc.
'Increase the date. Each voyage takes one month.
'Yeah, I know it's unrealistic.
GameState.gameDate = GameState.gameDate + 1
Year = FIX((GameState.gameDate / 12)) + 1850
Month = GameState.gameDate - ((Year - 1850) * 12)
SELECT CASE Month
CASE 0
Month$ = "January"
CASE 1
Month$ = "February"
CASE 2
Month$ = "March"
CASE 3
Month$ = "April"
CASE 4
Month$ = "May"
CASE 5
Month$ = "June"
CASE 6
Month$ = "July"
CASE 7
Month$ = "August"
CASE 8
Month$ = "September"
CASE 9
Month$ = "October"
CASE 10
Month$ = "November"
CASE 11
Month$ = "December"
END SELECT
'Calculate interest at the bank.
Bank! = FIX(Bank! + (Bank! * .05))
'This SUB sets the prices at the marketplace.
SetPrices d%
CLS
LINE (5, 5)-(315, 195), 5, B
IconPut 10, 10, Ports(d%).CType
LOCATE 4, 6: PRINT "Arriving at " + Ports(d%).CName
LOCATE 7, 3: PRINT Month$; Year
SELECT CASE Month$
CASE "January"
'Every January, the pirate's guild demands tribute. If you pay, you won't
'be attacked by pirates. Much.
GameState.paidPirates = 0
IF Credits! > 100 AND GameState.paidPirates = 1 THEN
Tribute% = INT(Credits! * .25)
ELSEIF Credits! > 100 AND GameState.paidPirates = 0 THEN
Tribute% = INT(Credits! * .5)
ELSEIF Credits! < 100 THEN
Tribute% = 50
END IF
LOCATE 9, 3: PRINT "The pirate's guild demands "; Tribute%; "in"
LOCATE 10, 3: PRINT "tribute. Will you pay?"
SELECT CASE UCASE$(GetKey$)
CASE "Y"
IF Credits! >= Tribute% THEN
LOCATE 10, 27: PRINT "Y"
Credits! = Credits! - Tribute%
GameState.paidPirates = 1
ELSE
LOCATE 11, 3: PRINT "You can't afford to pay."
END IF
CASE "N"
LOCATE 10, 27: PRINT "N"
END SELECT
CASE "July"
'The wheat harvest is in or around july, which means that wheat prices
'fall. They don't pick back up again for several months, which should
'be an easy way to turn a good profit. (Exercise left to reader.)
LOCATE 9, 3: PRINT "The wheat harvest has been completed."
LOCATE 10, 3: PRINT "Wheat prices are down."
CASE "October"
'Wheat prices rise again.
LOCATE 9, 3: PRINT "Wheat prices have risen somewhat."
END SELECT
WHILE INKEY$ = "": WEND
END SUB
SUB FireCannon (startShotX, startShotY, shotSpeed, shotAngle, FireType, sX, psX)
'FireType is what kind of shot it is.
'1 = Your ship, hit
'2 = Your ship, miss
'3 = Pirate ship, hit
'4 = Pirate ship, miss
shotAngle = shotAngle / 180 * PI
startShotXvel = COS(shotAngle) * shotSpeed
startShotYvel = SIN(shotAngle) * shotSpeed
t = 0
EndShot% = 0
DO
FOR paws = 1 TO 900: NEXT paws
CIRCLE (shotX, shotY), 1, 0
t = t + .1
shotX = startShotX + (startShotXvel * t)
shotY = startShotY + ((-1 * (startShotYvel * t)) + (4.9 * t ^ 2)) * (200 / 350)
CIRCLE (shotX, shotY), 1, 24
IF FireType = 1 AND shotX >= psX THEN
CIRCLE (shotX, shotY), 1, 0
EndShot% = 1
ELSEIF FireType = 2 AND shotY >= 94 THEN
CIRCLE (shotX, shotY), 1, 0
PUT (shotX, shotY), Splash%
EndShot% = 1
paws = TIMER: WHILE TIMER <= paws + .5: WEND
PUT (shotX, shotY), Splash%
ELSEIF FireType = 3 AND shotX <= sX + 50 THEN
CIRCLE (shotX, shotY), 1, 0
EndShot% = 1
ELSEIF FireType = 4 AND shotY >= 94 THEN
CIRCLE (shotX, shotY), 1, 0
PUT (shotX - 5, shotY), Splash%
EndShot% = 1
paws = TIMER: WHILE TIMER <= paws + .5: WEND
PUT (shotX - 5, shotY), Splash%
END IF
LOOP UNTIL EndShot% = 1
END SUB
SUB FLoad (FileOffset&, DataLength&, DestArray() AS INTEGER)
'
' FLoad -- Quickly loads a file's contents into specified integer array.
'
' --Parameters--
' FileName$ = The file name to load
' FileOffset& = The offset of the file to start loading
' DataLength& = The amount, in bytes, of data to load.
' DestArray() = The array to load all the data into.
IF FileOffset& = 0 THEN FileOffset& = 1
RemBytes& = DataLength&
BufferSize% = 32766 ' The buffer size to use. If you get out of string
' space errors, lower it. (result : it's slower)
BufStart% = LBOUND(DestArray) ' Lowest element number of buffer
DEF SEG = VARSEG(DestArray(BufStart%)) ' The segment of the song buffer
Ptr& = VARPTR(DestArray(BufStart%)) ' Pointer to the song buffer
LeftBytes& = RemBytes& MOD BufferSize% ' The amount of left over bytes
SEEK #1, FileOffset&
IF (LeftBytes& < RemBytes&) THEN
FOR QuickLoad% = 1 TO (DataLength& - LeftBytes&) / BufferSize%
Buffer$ = SPACE$(BufferSize%)
GET #1, , Buffer$
FOR x% = 1 TO BufferSize%
POKE Ptr&, ASC(MID$(Buffer$, x%, 1))
Ptr& = Ptr& + 1
NEXT
Buffer$ = ""
RemBytes& = RemBytes& - BufferSize%
NEXT
END IF
IF (LeftBytes& > 0) THEN
Buffer$ = SPACE$(LeftBytes&)
GET #1, , Buffer$
FOR x% = 1 TO LeftBytes&
POKE Ptr&, ASC(MID$(Buffer$, x%, 1))
Ptr& = Ptr& + 1
NEXT
Buffer$ = ""
END IF
DEF SEG
END SUB
SUB GameOver (OverType%)
' 1 - Sunk by a pirate
' 2 - Sunk in a storm
' more to come
SELECT CASE OverType%
CASE 1
CLS
LINE (5, 5)-(315, 195), 5, B
LOCATE 19, 3: PRINT "Your ship has been sunk in a"
LOCATE 20, 3: PRINT "fierce battle with pirates."
Pause 1
FOR MovingShip% = 50 TO 75
WAIT &H3DA, 8
PUT (120, (MovingShip% - 1)), BigShipPic%
PUT (120, MovingShip%), BigShipPic%, PSET
Pause .3
NEXT MovingShip%
LOCATE 22, 3: PRINT "Press a key to continue."
SLEEP
CASE 2
PRINT "Your ship has been sunk in a storm."
PRINT TAB(6); "Press a key to continue."
SLEEP
END SELECT
'This may be clumsy, but all this does is re-run the program, bringing you
'back to the main menu, which lets you start a new game, restore, etc.
RUN "trader"
END SUB
FUNCTION GetKey$
'This just returns a keypress value. Used for all those menus. I think it
'makes things a little more efficient, anyway.
k$ = ""
WHILE k$ = "": k$ = INKEY$: WEND
GetKey$ = k$
END FUNCTION
SUB IconLoad (LoadIcon%, LIType%)
DatLen& = ArraySize(LoadIcon%) * 2 'just temporary variables
StrRed& = StartRead(LoadIcon%) 'because of Fload.
IF LIType% = 1 THEN
SELECT CASE LoadIcon%
CASE 1
FLoad StrRed&, DatLen&, ShipIcon%()
CASE 2
FLoad StrRed&, DatLen&, PirateIcon%()
CASE 3
FLoad StrRed&, DatLen&, cannon%()
CASE 4
FLoad StrRed&, DatLen&, IndIcon%()
CASE 5
FLoad StrRed&, DatLen&, AgrIcon%()
CASE 6
FLoad StrRed&, DatLen&, MinIcon%()
CASE 7
FLoad StrRed&, DatLen&, FunIcon%()
CASE 8
FLoad StrRed&, DatLen&, Splash%()
CASE 9
FLoad StrRed&, DatLen&, Cancel%()
CASE 10
FLoad StrRed&, DatLen&, TavernSign%()
CASE 11
FLoad StrRed&, DatLen&, WareHouseIcon%()
CASE 12
FLoad StrRed&, DatLen&, BankSign%()
END SELECT
ELSEIF LIType% = 2 THEN
SELECT CASE LoadIcon%
CASE 1
FLoad StrRed&, DatLen&, BigShipPic%()
CASE 2
FLoad StrRed&, DatLen&, PirateShipPic%()
CASE 3
FLoad StrRed&, DatLen&, StormPic%()
END SELECT
END IF
END SUB
SUB IconPut (IconPutX%, IconPutY%, IconPutName$)
SELECT CASE IconPutName$
CASE "Ind"
PUT (IconPutX%, IconPutY%), IndIcon%
CASE "Min"
PUT (IconPutX%, IconPutY%), MinIcon%
CASE "Agr"
PUT (IconPutX%, IconPutY%), AgrIcon%
CASE "Fun"
PUT (IconPutX%, IconPutY%), FunIcon%
CASE "warehouse"
PUT (IconPutX%, IconPutY%), WareHouseIcon%
CASE "banksign"
PUT (IconPutX%, IconPutY%), BankSign%
CASE "tavernsign"
PUT (IconPutX%, IconPutY%), TavernSign%
CASE "ship"
PUT (IconPutX%, IconPutY%), ShipIcon%
CASE "cancel"
PUT (IconPutX%, IconPutY%), Cancel%
END SELECT
END SUB
SUB MainMenu
Start:
CLS
COLOR TextCol%
PRINT
PRINT TAB(13); "T R A D E R"
PRINT
IconPut 20, 44, "ship"
LOCATE 8, 7: PRINT "1. New Game"
IconPut 20, 68, "cancel"
LOCATE 11, 7: PRINT "2. Quit"
SELECT CASE VAL(GetKey$)
CASE 1
GOSUB StartGame
CASE 2
END
CASE ELSE
GOSUB Start
END SELECT
StartGame:
CLS
PRINT
PRINT TAB(6); "What is your name, Trader?"
LOCATE 4, 10: INPUT "]", PName$ 'Get the player's name.
CLS
END SUB
SUB MarketMenu
'Buy and sell stuff, etc.
MainMarket:
CLS
LINE (5, 5)-(315, 195), 5, B
'Draw the city icon thingy.
IconPut 10, 10, Ports(City%).CType
LOCATE 4, 6: PRINT "The market in " + Ports(City%).CName
LOCATE 7, 3: PRINT "Cargo Free"
IF ShipFree% >= 0 THEN
LOCATE 8, 3: PRINT USING "#### ####"; (Ship.capacity - ShipFree%); ShipFree%
ELSEIF ShipFree% < 0 THEN
LOCATE 8, 3: PRINT USING "#### Overloaded"; (Ship.capacity - ShipFree%)
END IF
LOCATE 10, 3: PRINT FIX(Credits!); "Credits"
LOCATE 12, 3: PRINT "What do you want to do?"
LOCATE 13, 4: PRINT "1. Sell Items"
LOCATE 14, 4: PRINT "2. Buy Items"
LOCATE 15, 4: PRINT "3. Back to Main Menu"
SELECT CASE VAL(GetKey$)
CASE 1
GOSUB SellMenu
CASE 2
GOSUB BuyMenu
CASE 3
EXIT SUB
CASE ELSE
GOSUB MainMarket
END SELECT
SellMenu:
CLS
LINE (5, 5)-(315, 195), 5, B
LOCATE 5, 3: PRINT "What do you want to sell?"
'Put the city icon thingy.
IconPut 10, 10, Ports(City%).CType
LOCATE 7, 4: PRINT "Item No."
IF Ship.cannon > 0 THEN LOCATE 9, 4: PRINT USING "(C)annon ####"; Ship.cannon
IF Ship.wheat > 0 THEN LOCATE 10, 4: PRINT USING "(W)heat ####"; Ship.wheat
IF Ship.ore > 0 THEN LOCATE 11, 4: PRINT USING "(O)re ####"; Ship.ore
IF Ship.luxuries > 0 THEN LOCATE 12, 4: PRINT USING "(L)uxury Goods ####"; Ship.luxuries
IF Ship.contraband > 0 THEN LOCATE 13, 4: PRINT USING "Con(t)raband ####"; Ship.contraband
IF Ship.equipment > 0 THEN LOCATE 14, 4: PRINT USING "(E)quipment ####"; Ship.equipment
LOCATE 16, 4: PRINT "(D)one"
'There has *got* to be a better way to do this...
SELECT CASE UCASE$(GetKey$)
CASE "C"
NumItems% = Ship.cannon: Item$ = "cannon"
CASE "W"
NumItems% = Ship.wheat: Item$ = "wheat"
CASE "O"
NumItems% = Ship.ore: Item$ = "ore"
CASE "L"
NumItems% = Ship.luxuries: Item$ = "luxuries"
CASE "T"
NumItems% = Ship.contraband: Item$ = "contraband"
CASE "E"
NumItems% = Ship.equipment: Item$ = "equipment"
CASE "D"
GOSUB MainMarket
CASE ELSE
GOSUB SellMenu
END SELECT
CalcSale:
SPrice% = SellPrice%(Item$)
LOCATE 18, 3: PRINT "You have "; NumItems%; " Units of " + Item$
LOCATE 19, 3: PRINT Item$ + " is/are selling for "; SPrice%
LOCATE 20, 3: INPUT "Number to Sell: ", d%
IF d% <= NumItems% THEN
AddCargo -d%, Item$, 1
Credits! = Credits! + (SPrice% * d%)
LOCATE 20, 3: PRINT TAB(6); "Items Sold: "; d%; Item$
ELSEIF d% > NumItems% THEN
LOCATE 20, 3: PRINT "You don't have that many " + Item$ + "."
END IF
WHILE INKEY$ = "": WEND
GOSUB SellMenu
'This is the menu where one buys stuff.
BuyMenu:
CLS
LINE (5, 5)-(315, 195), 5, B
LOCATE 5, 3: PRINT USING "Free space: ####"; ShipFree%
LOCATE 6, 3: PRINT USING "Credits: ##########"; FIX(Credits!)
LOCATE 7, 3: PRINT "What do you want to buy?"
'Icon thingy again.
IconPut 10, 10, Ports(City%).CType
SELECT CASE Ports(City%).CType
CASE "Agr"
LOCATE 9, 4: PRINT "(W)heat"
CASE "Ind"
LOCATE 9, 4: PRINT "(L)uxury Goods"
LOCATE 10, 4: PRINT "(E)quipment"
CASE "Min"
LOCATE 9, 4: PRINT "(O)re"
CASE "Fun"
LOCATE 9, 4: PRINT "Con(t)raband"
END SELECT
LOCATE 16, 4: PRINT "(D)one"
SELECT CASE UCASE$(GetKey$)
CASE "W"
Item$ = "wheat"
CASE "L"
Item$ = "luxuries"
CASE "E"
Item$ = "equipment"
CASE "O"
Item$ = "ore"
CASE "T"
Item$ = "contraband"
CASE "D"
GOSUB MainMarket
CASE ELSE
GOSUB BuyMenu
END SELECT
CalcPurchase:
BPrice% = BuyPrice%(Item$)
IF BPrice% > 0 THEN
LOCATE 18, 4: PRINT Item$ + " costs "; BPrice%; " per Unit."
LOCATE 19, 4: PRINT "You can afford " + STR$(FIX(Credits! / BPrice%))
LOCATE 20, 4: INPUT "Number to buy: ", d%
IF (d% * BPrice%) <= Credits! THEN
Credits! = Credits! - (d% * BPrice%)
AddCargo d%, Item$, 1
LOCATE 20, 4: PRINT "Number bought: "; d%
IF ShipFree% < 0 THEN
LOCATE 21, 4: PRINT "Your ship is overloaded."
END IF
ELSEIF (d% * BPrice%) > Credits! AND ShipFree% >= d% THEN
LOCATE 20, 4: PRINT "You can't afford that many."
END IF
ELSEIF BPrice% = 0 THEN
GOSUB BuyMenu
END IF
WHILE INKEY$ = "": WEND
GOSUB BuyMenu
END SUB
FUNCTION OpenMix1 (FileName$)
DIM lbyte AS STRING * 1
'(5) 5 char file id -+
' + |
'(4) 2 integer file version + num files |= calculate
'==== | file header
' 9 _|
FileSizer = 10 'this is the header size + 1 (1 = starting location)
DIM Dummy AS INTEGER 'just for info inside file that we don't need.
mk = FREEFILE
OPEN FileName$ + ".MIX" FOR BINARY AS mk
IF LOF(mk) <= 0 THEN 'file doesn't exist!
CLOSE
KILL FileName$ + "MIX" ' kill file! (opening file that doesn't
' exist creates an empty file)
OpenMix1 = -1
EXIT FUNCTION
END IF
id$ = "" 'get file id, to check if it's MIX
FOR I = 1 TO 5 'file...
GET #mk, , lbyte
id$ = id$ + lbyte
NEXT I
IF id$ <> "QBMIX" THEN 'if it's not, EXIT!!!!
OpenMix1 = -2
EXIT FUNCTION
END IF
DIM vers AS INTEGER
GET #mk, , vers 'get version
IF vers <> 1 THEN 'we know how to open only version 1
OpenMix1 = -3
EXIT FUNCTION
END IF
GET #mk, , FilesNumber 'number of pictures inside MIX
IF FilesNumber > MaxMIX OR FilesNumber <= 0 THEN
OpenMix1 = -4 'if it's too big or too small, exit!
EXIT FUNCTION
END IF 'until now file header
FOR I = 1 TO FilesNumber
'file name (8 bytes)
FOR d = 1 TO 8 'read file name. It's not useful here, so
GET #mk, , lbyte 'we just use a dummy.
FileSizer = FileSizer + 1 'we read one byte at a time.
NEXT d
GET #mk, , ArraySize(I) 'read array size
GET #mk, , Dummy 'read x size
GET #mk, , Dummy 'read y size (we use a dummy)
FileSizer = FileSizer + 6 'we read 3 integers that are 2 bytes
NEXT I 'each.
'now we have to calculate the place of each picture
'inside the file
FOR I = 1 TO FilesNumber
StartRead(I) = FileSizer 'array place in bytes
FileSizer = FileSizer + (ArraySize(I) * 2) 'because integer = 2
NEXT I 'bytes
END FUNCTION
SUB PalLoad (PalFile$)
CLOSE
OPEN PalFile$ + ".PAL" FOR BINARY AS #1
IF LOF(1) = 0 THEN
CLOSE #1
KILL PalFile$ + ".PAL"
EXIT SUB
END IF
CLOSE #1
OPEN PalFile$ + ".PAL" FOR INPUT AS #1
FOR I = 1 TO 768
INPUT #1, pal(I)
NEXT I
CLOSE #1
num = 1
an = 1
DO
pall(an).r = pal(num)
num = num + 1
pall(an).g = pal(num)
num = num + 1
pall(an).B = pal(num)
num = num + 1
an = an + 1
LOOP UNTIL num > 768
OUT &H3C7, 0: OUT &H3C8, 0
FOR a% = 1 TO 256 * 3:
OUT &H3C9, pal(a%)
NEXT a%
END SUB
SUB Pause (delay!)
'This sub just delays for the specified amount of time. Found it in an ABC
'packet. Seems like a good method.
t! = INT(TIMER)
IF delay! >= 1 THEN
DO
IF t! <> INT(TIMER) THEN
t! = INT(TIMER)
count = count + 1
END IF
LOOP UNTIL count = delay!
ELSEIF delay! < 1 THEN
DO
IF t! <> TIMER THEN
t! = TIMER
count = count + .1
END IF
LOOP UNTIL count = delay!
END IF
END SUB
SUB SeaBattle (PType%, PGuns%)
CLS
LINE (5, 5)-(315, 195), 5, B
SELECT CASE PType%
CASE 1
'Pirates
EnemyHealth = 40
PDistance = 3
END SELECT
DO
CLS
LINE (5, 5)-(315, 195), 5, B
LINE (5, 110)-(315, 110), 5
'PUT the cannons
FOR PutIcon% = 1 TO Ship.cannon
PUT (3 + (16 * PutIcon%), 3), cannon%
NEXT PutIcon%
'PUT the ships.
SELECT CASE PDistance
CASE 3
sX = 25: psX = 215
CASE 2
sX = 45: psX = 185
CASE 1
sX = 70: psX = 150
END SELECT
PUT (sX, 40), BigShipPic%
SELECT CASE PType%
CASE 1
PUT (psX, 40), PirateShipPic%
END SELECT
'Damage bar
IF Ship.damage > 50 THEN
COLOR 32
ELSE
COLOR 40
END IF
DamagePercent = (Ship.damage / 100) * 100
LOCATE 15, 2: PRINT STRING$((Ship.damage / 4), 219) + " -" + STR$(DamagePercent) + "%"
COLOR TextCol%
'Here's where the pirates fire at you.
Hits = 0
LOCATE 17, 2: PRINT "They're firing!" + STRING$(10, " ")
FOR Shoot = 1 TO PGuns%
'The chance they'll actually have a hit.
RANDOMIZE TIMER: HitChance = (RND * 100)
IF PDistance = 1 THEN
IF HitChance >= 15 THEN
'The most damage, and it's pretty hard to miss. Of course, at this
'range, it becomes a simple pounding match.
Ship.damage = Ship.damage - 9
Hits = Hits + 1
END IF
ELSEIF PDistance = 2 THEN
IF HitChance >= 35 THEN
Hits = Hits + 1
'Quite a bit better chance of a hit, and more damage.
Ship.damage = Ship.damage - 7
END IF
ELSEIF PDistance = 3 THEN
IF HitChance >= 72 THEN
Hits = Hits + 1
'Further away, they have less chance of a hit, and do less damage.
Ship.damage = Ship.damage - 5
END IF
END IF
NEXT Shoot
IF Hits >= 1 THEN
SELECT CASE PDistance
CASE 3
FireCannon psX, 70, 40, 120, 3, sX, psX
CASE 2
FireCannon psX, 70, 35, 140, 3, sX, psX
CASE 1
FireCannon psX, 70, 30, 120, 3, sX, psX
END SELECT
ELSE
RANDOMIZE TIMER: shotSpeedRnd = (RND * 10)
SELECT CASE PDistance
CASE 3
FireCannon psX, 70, 20 + shotSpeedRnd, 125, 4, sX, psX
CASE 2
FireCannon psX, 70, 13 + shotSpeedRnd, 137, 4, sX, psX
CASE 1
FireCannon psX, 70, 2, 90, 4, sX, psX
END SELECT
END IF
LOCATE 19, 3: PRINT Hits; "of"; PGuns%; "shots hit us."
Pause 2
'Combat menus.
'Do the damage bar again, test for death.
IF Ship.damage <= 0 THEN
'You've been sunk.
EndBattle% = 1: GOSUB EndBattleLoop
ELSEIF Ship.damage > 50 THEN
COLOR 32
ELSE
COLOR 40
END IF
BlockPrint 15, 2, 21, 40, " "
DamagePercent = (Ship.damage / 100) * 100
LOCATE 15, 2: PRINT STRING$((Ship.damage / 4), 219) + " -" + STR$(DamagePercent) + "%"
COLOR TextCol%
LOCATE 17, 2: PRINT "What do you want to do?"
'If you've got cannons, show the menu option to fire them.
IF Ship.cannon > 0 THEN
LOCATE 19, 2: PRINT "(F)ire Cannon"
IF Ship.cannon > 1 THEN LOCATE 19, 15: PRINT "s"
END IF
'Move away from the enemy ship. If you're far enough away, this attempts
'to escape.
IF PDistance = 3 THEN
LOCATE 20, 2: PRINT "Run (A)way"
ELSE
LOCATE 20, 2: PRINT "Move (A)way"
END IF
'Move towards the pirate ship.
IF PDistance > 1 THEN
LOCATE 21, 2: PRINT "Move (C)loser"
'If you're close enough to the enemy ship, then you can ram them, or
'attempt to board.
'ELSEIF PDistance = 1 THEN
' LOCATE 21, 2: PRINT "(R)am"
' LOCATE 22, 2: PRINT "(B)oard"
END IF
SeaBattleInput:
SELECT CASE UCASE$(GetKey$)
CASE "F"
'Fire your cannon
IF Ship.cannon > 0 THEN
'Clear the menu.
BlockPrint 17, 2, 22, 32, " "
Hits = 0
FOR Shoot = 1 TO Ship.cannon
BlockPrint 17, 2, 19, 32, " "
LOCATE 17, 2: PRINT "We're firing..." + STRING$(10, " ")
'The chance you'll actually have a hit.
RANDOMIZE TIMER: HitChance = (RND * 100)
IF PDistance = 1 THEN
IF HitChance >= 15 THEN
Hits = Hits + 1
EnemyHealth = EnemyHealth - 9
END IF
ELSEIF PDistance = 2 THEN
IF HitChance >= 35 THEN
Hits = Hits + 1
EnemyHealth = EnemyHealth - 7
END IF
ELSEIF PDistance = 3 THEN
IF HitChance >= 72 THEN
Hits = Hits + 1
EnemyHealth = EnemyHealth - 5
END IF
END IF
NEXT Shoot
IF Hits >= 1 THEN
OldEnemyHealth = EnemyHealth
SELECT CASE PDistance
CASE 3
FireCannon 80, 70, 40, 30, 1, sX, psX
CASE 2
FireCannon 100, 70, 40, 30, 1, sX, psX
CASE 1
FireCannon 135, 70, 15, 10, 1, sX, psX
END SELECT
ELSE
RANDOMIZE TIMER: shotSpeedRnd = (RND * 10)
SELECT CASE PDistance
CASE 3
FireCannon 80, 70, 20 + shotSpeedRnd, 35, 2, sX, psX
CASE 2
FireCannon 100, 70, 13 + shotSpeedRnd, 47, 2, sX, psX
CASE 1
FireCannon 135, 70, 2, 90, 2, sX, psX
END SELECT
END IF
LOCATE 19, 3: PRINT Hits; "of"; Ship.cannon; "hit them."
Pause 1
ELSE
GOSUB SeaBattleInput
END IF
CASE "C"
'Move closer to the enemy ship
IF PDistance > 1 THEN
PDistance = PDistance - 1
ELSE
GOSUB SeaBattleInput
END IF
CASE "A"
'Move away from the enemy ship, if you're far enough, attempt to escape
'completely.
IF PDistance < 3 THEN
PDistance = PDistance + 1
ELSEIF PDistance = 3 THEN
'The "run away" code goes here
RANDOMIZE TIMER: EscapeChance% = INT(RND * 100)
IF ShipFree% = Ship.capacity AND EscapeChance% >= 30 THEN
EndBattle% = 3
GOSUB EndBattleLoop
ELSEIF ShipFree% < (Ship.capacity / 2) AND EscapeChance% >= 50 THEN
EndBattle% = 3
GOSUB EndBattleLoop
ELSEIF ShipFree% < (Ship.capacity / 4) AND EscapeChance% >= 70 THEN
EndBattle% = 3
GOSUB EndBattleLoop
END IF
END IF
CASE ELSE
GOSUB SeaBattleInput
END SELECT
'Decide whether or not to end the battle, and if so how much money you
'make from it, etc.
IF Ship.damage <= 0 THEN
EndBattle% = 1
GOSUB EndBattleLoop
END IF
IF EnemyHealth <= 0 THEN
EndBattle% = 2
GOSUB EndBattleLoop
END IF
EndBattleLoop:
LOOP UNTIL EndBattle% > 0
SELECT CASE EndBattle%
CASE 1
'You sink
GameOver 1
CASE 2
'They sink
SELECT CASE PType%
CASE 1
RANDOMIZE TIMER: GainedCredits = INT(RND * 400)
RANDOMIZE TIMER: CargoToAdd = INT(RND * 3) + 1
RANDOMIZE TIMER: d% = INT(RND * ShipFree%)
SELECT CASE CargoToAdd
CASE 1
Item$ = "contraband"
CASE 2
Item$ = "luxuries"
CASE 3
Item$ = "ore"
END SELECT
BlockPrint 17, 2, 22, 32, " "
LOCATE 17, 2: PRINT "We sank them!"
LOCATE 19, 2: PRINT "We've captured"; GainedCredits; "in cash."
LOCATE 20, 2: PRINT "We've captured"; d%; "units of " + Item$
LOCATE 22, 2: PRINT "Do you want to keep it? (y/n)"
IF UCASE$(GetKey$) = "Y" THEN AddCargo d%, Item$, 1
CASE 2
END SELECT
CASE 3
'You run
BlockPrint 17, 2, 22, 32, " "
LOCATE 17, 2: PRINT "We've escaped!"
END SELECT
END SUB
FUNCTION SellPrice% (Item$)
'Returns a value for how much you can sell something for.
SELECT CASE Item$
CASE "cannon"
Price% = 100
CASE "wheat"
Price% = CurrentPrices.wheat
CASE "ore"
Price% = CurrentPrices.ore
CASE "luxuries"
Price% = CurrentPrices.luxuries
CASE "contraband"
Price% = CurrentPrices.contraband
CASE "equipment"
Price% = CurrentPrices.equipment
END SELECT
SellPrice% = Price%
END FUNCTION
SUB SetPrices (d%)
'This sets the prices for all of the items at the marketplace.
'For now it just takes into account the type of city and time of year,
'but I plan on adding other economic factors.
Year = FIX((GameState.gameDate / 12)) + 1850
Month = GameState.gameDate - ((Year - 1850) * 12)
SELECT CASE Month
CASE 0 TO 5
WheatModifier = 3
CASE 6 TO 8
WheatModifier = 1
CASE 9 TO 11
WheatModifier = 2
END SELECT
SELECT CASE Ports(d%).CType
CASE "Agr"
RANDOMIZE TIMER: CurrentPrices.wheat = 1 + (INT(RND * 10) * WheatModifier)
RANDOMIZE TIMER: CurrentPrices.ore = 1 + INT(RND * 3)
RANDOMIZE TIMER: CurrentPrices.luxuries = 1 + INT(RND * 3)
RANDOMIZE TIMER: CurrentPrices.equipment = 500 + INT(RND * 2000)
CASE "Ind"
RANDOMIZE TIMER: CurrentPrices.wheat = 1 + INT(RND * 5)
RANDOMIZE TIMER: CurrentPrices.ore = 10 + INT(RND * 60)
RANDOMIZE TIMER: CurrentPrices.luxuries = 20 + INT(RND * 30)
RANDOMIZE TIMER: CurrentPrices.equipment = 500 + INT(RND * 800)
CASE "Min"
RANDOMIZE TIMER: CurrentPrices.wheat = 5 + (INT(RND * 20) * WheatModifier)
RANDOMIZE TIMER: CurrentPrices.ore = 2 + INT(RND * 25)
RANDOMIZE TIMER: CurrentPrices.luxuries = 1 + INT(RND * 16)
RANDOMIZE TIMER: CurrentPrices.equipment = 500 + INT(RND * 1000)
CASE "Fun"
RANDOMIZE TIMER: CurrentPrices.wheat = 1 + INT(RND * 6)
RANDOMIZE TIMER: CurrentPrices.ore = 1 + INT(RND * 3)
RANDOMIZE TIMER: CurrentPrices.luxuries = 5 + INT(RND * 50)
RANDOMIZE TIMER: CurrentPrices.equipment = 400
END SELECT
RANDOMIZE TIMER: CurrentPrices.contraband = 10 + INT(RND * 100)
END SUB
FUNCTION ShipFree%
'Returns the amount of free space left in the ship.
Space = 0
Space% = Space% + Ship.cannon * 10
Space% = Space% + Ship.wheat + Ship.ore + Ship.luxuries + Ship.contraband + Ship.equipment
ShipFree% = Ship.capacity - Space%
END FUNCTION
SUB ShipMenu
MainShip:
CLS
LINE (5, 5)-(315, 195), 5, B
PUT (10, 10), ShipIcon%
'Draw the cannons.
FOR PutIcon% = 1 TO Ship.cannon
PUT (30 + (16 * PutIcon%), 10), cannon%
NEXT PutIcon%
LOCATE 6, 3: PRINT "At ship in " + Ports(City%).CName
LOCATE 8, 3: PRINT "What do you want to do?"
LOCATE 10, 4: PRINT "1. Sail for Another Port"
LOCATE 11, 4: PRINT "2. Upgrade or Repair Ship"
LOCATE 12, 4: PRINT "3. Back to Main Menu"
SELECT CASE VAL(GetKey$)
CASE 1
GOSUB SailAway
CASE 2
GOSUB ShipYard
CASE 3
EXIT SUB
CASE ELSE
GOSUB MainShip
END SELECT
'This menu lets you upgrade/repair your ship.
'You can repair, buy cannons or a lifeboat, upgrade stuff, etc.
ShipYard:
CLS
LINE (5, 5)-(315, 195), 5, B
PUT (10, 10), ShipIcon%
'Draw the cannons.
FOR PutIcon% = 1 TO Ship.cannon
PUT (30 + (16 * PutIcon%), 10), cannon%
NEXT PutIcon%
LOCATE 7, 3: PRINT "You have "; Ship.cannon; " Cannons."
LOCATE 8, 3: PRINT "Ship condition: " + STR$(Ship.damage) + "%"
LOCATE 9, 3: PRINT "You have "; Credits!; " Credits in cash."
LOCATE 11, 4: PRINT "1. Repair Damage - 30 Credits"
LOCATE 12, 4: PRINT "2. Buy a Cannon - 250 Credits"
LOCATE 14, 4: PRINT "3. Done"
SELECT CASE VAL(GetKey$)
CASE 1 'Repair the ship.
IF Ship.damage >= 100 THEN
LOCATE 16, 3: PRINT "Your ship is already repaired."
ELSEIF Ship.damage < 100 AND Credits! >= 30 THEN
Credits! = Credits! - 30
Ship.damage = Ship.damage + 10
IF Ship.damage > 100 THEN Ship.damage = 100
LOCATE 16, 3: PRINT "Repairs done."
END IF
WHILE INKEY$ = "": WEND
GOSUB ShipYard
CASE 2 'Buy a cannon
IF Credits! >= 250 AND ShipFree% >= 10 THEN
Credits! = Credits! - 250
AddCargo 1, "cannon", 1
LOCATE 16, 3: PRINT "Cannon Purchased"
ELSEIF (Credits! < 250) OR (ShipFree% < 10) THEN
LOCATE 16, 5: PRINT "You can't afford a new cannon."
END IF
WHILE INKEY$ = "": WEND
GOSUB ShipYard
CASE 3
GOSUB MainShip
CASE ELSE
GOSUB ShipYard
END SELECT
SailAway:
'The menu of other ports to sail to. I'm sure there's a better way to do
'this, but I have no idea what it is.
CLS
LINE (5, 5)-(315, 195), 5, B
PUT (10, 10), ShipIcon%
LOCATE 4, 6: PRINT "Where do you want to sail?"
IconPut 20, 44, Ports(1).CType
IconPut 20, 68, Ports(2).CType
IconPut 20, 92, Ports(3).CType
IconPut 20, 116, Ports(4).CType
IconPut 20, 140, Ports(5).CType
LOCATE 8, 7: PRINT "1. " + Ports(1).CName
LOCATE 11, 7: PRINT "2. " + Ports(2).CName
LOCATE 14, 7: PRINT "3. " + Ports(3).CName
LOCATE 17, 7: PRINT "4. " + Ports(4).CName
LOCATE 20, 7: PRINT "5. " + Ports(5).CName
IconPut 165, 44, Ports(6).CType
IconPut 165, 68, Ports(7).CType
IconPut 165, 92, Ports(8).CType
IconPut 165, 116, "cancel"
LOCATE 8, 25: PRINT "6. " + Ports(6).CName
LOCATE 11, 25: PRINT "7. " + Ports(7).CName
LOCATE 14, 25: PRINT "8. " + Ports(8).CName
LOCATE 17, 25: PRINT "9. Cancel"
d% = INT(VAL(GetKey$))
IF d% <= 9 AND d% >= 1 THEN
IF d% = City% THEN
LOCATE 23, 5: PRINT "You're already there!"
paws = TIMER: WHILE TIMER <= paws + 2: WEND
GOSUB SailAway
ELSEIF (d% <> City%) AND (ShipFree% < 0) THEN
LOCATE 22, 5: PRINT "Your ship is overloaded!"
LOCATE 23, 5: PRINT "Sell or move some cargo."
paws = TIMER: WHILE TIMER <= paws + 1: WEND
EXIT SUB
ELSEIF d% = 9 THEN
GOSUB MainShip
ELSE
GOSUB MovingShip
END IF
ELSE
GOSUB SailAway
END IF
'Sail to whatever your port of choice is.
MovingShip:
CLS
LINE (5, 5)-(315, 195), 5, B
PUT (10, 10), ShipIcon%
'Show the cannons.
FOR PutIcon% = 1 TO Ship.cannon
PUT (30 + (16 * PutIcon%), 10), cannon%
NEXT PutIcon%
LOCATE 5, 3: PRINT "Sailing to "; Ports(d%).CName
FOR MovingShip% = 5 TO 200 STEP 5
WAIT &H3DA, 8
PUT (25 + (MovingShip% - 5), 50), BigShipPic%
PUT (25 + MovingShip%, 50), BigShipPic%, PSET
Pause .3
IF MovingShip% = 85 THEN
SELECT CASE ShipFree%
CASE 0 TO (Ship.capacity / 4)
Chance = Chance + .4
CASE ((Ship.capacity / 4) + 1) TO (Ship.capacity / 2)
Chance = Chance + .3
CASE ((Ship.capacity / 2) + 1) TO ((Ship.capacity / 4) * 3)
Chance = Chance + .2
END SELECT
IF Ship.cannon >= 3 THEN Chance = Chance - (.1 * (INT(Ship.cannon / 3)))
RANDOMIZE TIMER: Attack = RND + Chance
IF GameState.paidPirates = 0 THEN
SELECT CASE Attack
CASE .85 TO .94
'Start a battle
PAttacked% = 1
SeaBattle 1, 2
CASE .95
'Start a battle
PAttacked% = 1
SeaBattle 1, 3
END SELECT
ELSEIF GameState.paidPirates = 1 THEN
IF Attack >= .99 THEN
'Start a battle
PAttacked% = 1
SeaBattle 1, 2
END IF
END IF
IF PAttacked% = 1 THEN
CLS
LINE (5, 5)-(315, 195), 5, B
PUT (10, 10), ShipIcon%
'Show the cannons.
FOR PutIcon% = 1 TO Ship.cannon
PUT (30 + (16 * PutIcon%), 10), cannon%
NEXT PutIcon%
LOCATE 5, 3: PRINT "Sailing to "; Ports(d%).CName
PUT (25 + MovingShip%, 50), BigShipPic%, PSET
END IF
END IF
NEXT MovingShip%
RANDOMIZE TIMER: Storm = RND
IF Storm >= .8 THEN
StormCity% = 0
StormRnd = 0
CLS
LINE (5, 5)-(315, 195), 5, B
PUT (130, 30), StormPic%
LOCATE 19, 3: PRINT "Storm!"
Pause 1
'Calculate the effects of a storm.
RANDOMIZE TIMER: StormRnd = RND * 10
Ship.damage = Ship.damage - INT(StormRnd)
LOCATE 21, 3: PRINT "The ship has taken " + STR$(INT(StormRnd)) + " Damage."
IF Ship.damage <= 0 THEN
'You're sunk.
GameOver 2
END IF
RANDOMIZE TIMER: StormRnd = RND
IF StormRnd >= .6 THEN
StormCity% = d% + 1
IF StormCity% > 8 THEN StormCity% = d% - 1
d% = StormCity%
LOCATE 23, 3: PRINT "We've been blown to " + Ports(d%).CName
END IF
WHILE INKEY$ = "": WEND
END IF
'Finished sailing, arrived without being killed, etc...
'This sub calculates interest at the bank, advances the date, triggers events,
'etc.
Events d%
City% = d%: EXIT SUB
END SUB
FUNCTION WareFree%
'Returns the amount of free space left in the warehouse.
Space = 0
Space% = Space% + WareHouse.cannon * 10
Space% = Space% + WareHouse.wheat + WareHouse.ore + WareHouse.luxuries + WareHouse.contraband + WareHouse.equipment
WareFree% = WareHouse.capacity - Space%
END FUNCTION
SUB WarehouseMenu
MainWarehouse:
CLS
LINE (5, 5)-(315, 195), 5, B
'Draw the city icon thingy.
IconPut 10, 10, Ports(City%).CType
LOCATE 5, 3: PRINT "You are at your warehouse."
LOCATE 7, 3: PRINT " Cargo Free"
LOCATE 8, 3: PRINT USING "Ship: #### ####"; (Ship.capacity - ShipFree%); ShipFree%
LOCATE 9, 3: PRINT USING "Warehouse: ##### #####"; (WareHouse.capacity - WareFree%); WareFree%
LOCATE 11, 3: PRINT "What do you want to do?"
LOCATE 13, 4: PRINT "1. Transfer to ship"
LOCATE 14, 4: PRINT "2. Transfer from ship"
LOCATE 15, 4: PRINT "3. Back to Main Menu"
SELECT CASE VAL(GetKey$)
CASE 1
GOSUB MoveToShip
CASE 2
GOSUB MoveFromShip
CASE 3
EXIT SUB
CASE ELSE
END SELECT
MoveToShip:
CLS
LINE (5, 5)-(315, 195), 5, B
LOCATE 5, 3: PRINT "What do you want to transfer?"
LOCATE 7, 4: PRINT "Item No."
IF WareHouse.cannon > 0 THEN LOCATE 9, 4: PRINT USING "(C)annon ####"; WareHouse.cannon
IF WareHouse.wheat > 0 THEN LOCATE 10, 4: PRINT USING "(W)heat ####"; WareHouse.wheat
IF WareHouse.ore > 0 THEN LOCATE 11, 4: PRINT USING "(O)re ####"; WareHouse.ore
IF WareHouse.luxuries > 0 THEN LOCATE 12, 4: PRINT USING "(L)uxury Goods ####"; WareHouse.luxuries
IF WareHouse.contraband > 0 THEN LOCATE 13, 4: PRINT USING "Con(t)raband ####"; WareHouse.contraband
IF WareHouse.equipment > 0 THEN LOCATE 14, 4: PRINT USING "(E)quipment ####"; WareHouse.equipment
LOCATE 16, 4: PRINT "(D)one"
'There has *got* to be a better way to do this...
SELECT CASE UCASE$(GetKey$)
CASE "C"
NumItems% = WareHouse.cannon: Item$ = "cannon"
CASE "W"
NumItems% = WareHouse.wheat: Item$ = "wheat"
CASE "O"
NumItems% = WareHouse.ore: Item$ = "ore"
CASE "L"
NumItems% = WareHouse.luxuries: Item$ = "luxuries"
CASE "T"
NumItems% = WareHouse.contraband: Item$ = "contraband"
CASE "E"
NumItems% = WareHouse.equipment: Item$ = "equipment"
CASE "D"
GOSUB MainWarehouse
CASE ELSE
GOSUB MoveToShip
END SELECT
LOCATE 18, 3: PRINT "You have "; NumItems%; " Units of " + Item$
LOCATE 19, 3: INPUT "Number to move aboard ship: ", d%
IF d% <= NumItems% AND d% <= ShipFree% THEN
AddCargo d%, Item$, 1
AddCargo -d%, Item$, 2
LOCATE 20, 3: PRINT TAB(6); "Items Moved: "; d%; Item$
ELSEIF d% > NumItems% THEN
LOCATE 20, 3: PRINT "You don't have that many " + Item$ + "."
END IF
WHILE INKEY$ = "": WEND
GOSUB MainWarehouse
'Move stuff from the ship into the warehouse.
MoveFromShip:
CLS
LINE (5, 5)-(315, 195), 5, B
LOCATE 5, 3: PRINT "What do you want to transfer?"
LOCATE 7, 4: PRINT "Item No."
IF Ship.cannon > 0 THEN LOCATE 9, 4: PRINT USING "(C)annon ####"; Ship.cannon
IF Ship.wheat > 0 THEN LOCATE 10, 4: PRINT USING "(W)heat ####"; Ship.wheat
IF Ship.ore > 0 THEN LOCATE 11, 4: PRINT USING "(O)re ####"; Ship.ore
IF Ship.luxuries > 0 THEN LOCATE 12, 4: PRINT USING "(L)uxury Goods ####"; Ship.luxuries
IF Ship.contraband > 0 THEN LOCATE 13, 4: PRINT USING "Con(t)raband ####"; Ship.contraband
IF Ship.equipment > 0 THEN LOCATE 14, 4: PRINT USING "(E)quipment ####"; Ship.equipment
SELECT CASE UCASE$(GetKey$)
CASE "C"
NumItems% = Ship.cannon: Item$ = "cannon"
CASE "W"
NumItems% = Ship.wheat: Item$ = "wheat"
CASE "O"
NumItems% = Ship.ore: Item$ = "ore"
CASE "L"
NumItems% = Ship.luxuries: Item$ = "luxuries"
CASE "T"
NumItems% = Ship.contraband: Item$ = "contraband"
CASE "E"
NumItems% = Ship.equipment: Item$ = "equipment"
CASE "D"
CASE ELSE
END SELECT
LOCATE 18, 3: PRINT "You have "; NumItems%; " Units of " + Item$
LOCATE 19, 3: INPUT "Number to move to warehouse: ", d%
IF d% <= NumItems% AND d% <= WareFree% THEN
AddCargo -d%, Item$, 1
AddCargo d%, Item$, 2
LOCATE 20, 3: PRINT TAB(6); "Items Moved: "; d%; Item$
ELSEIF d% > NumItems% THEN
LOCATE 20, 3: PRINT "You don't have that many " + Item$ + "."
END IF
WHILE INKEY$ = "": WEND
GOSUB MainWarehouse
END SUB