Game code updated with sounds:
remstart
Space RTS - by IBOL - 20th March 2010
Continued by OBese87 - Last Updated: 10/JAN/2013
------------
-=- Known Bugs -=-
* Not all planets are building ships.
* Instant ship building at start of game if order given while paused (useful for testing purposes however).
* Enemy ships continue defending a planet even after their colony has been destroyed.
------------
-=- Feature Ideas -=-
- Variable ai Difficulty -
The ai gives orders instantaneously!
- Stay Together -
Ships in a group should move at the speed of the slowest member.
- Advanced Movement Orders -
Guard or follow other ships.
Set up patrol routes.
Move in formation.
- Limited Resources -
Each planet has a finite mineral pool, minerals are harvested by the inhabitants and converted into currency for building ships.
Once a planet's resources are depleated the population will start to drop and consume currency.
A new class of ship, the trade vessel, can take resources from an abundant planet and deliver them where they are needed, but these ships cannot
defend themselves or attack the enemy.
(When the game is expanded to more than two races the merchant will also be able to trade with allies and send peace offerings.)
- Strategic RepAirs -
Ships only repAir when near a homeworld. Maybe some kind of carrier ship can be a mobile base for repAirs too.
- Ship Progression -
Ships receive stat boosts for combat experience and kills. Already half implemented.
------------
remend
set display mode 1024,768,32
sync on
sync rate 0
randomize timer()
set text font "lucida console",1
set text size 16
ink -2,0
gosub arraysAndGlobals
gosub makeBackdrop
gosub makeSounds
gosub raceSelect
gosub initialize
rem === MAiN ===
do
rem >> INPUT >>
if key=0 then key=scancode() else key=0-scancode() :`World's most efficient trip-switch?
if mc=0 then mc=mouseclick() else mc=0-mouseclick()
`{
rem Adjust game speed (+/- keys) Pause "P".
if key>0
if key=57 then omniscience = 1 - omniscience :`spacekey
rem Pause game else adjust speed.
if key=25 :`P for qwerty; L for dvorak.
gamespeed#=0 : play sound sndWarpFail
else
if key=78
if gamespeed#=0 then gamespeed#=1 else inc gamespeed#,gamespeed#
if gamespeed#>32 then gamespeed#=32 else play sound sndFlip
endif
if key=74
gamespeed# = gamespeed#/2
if gamespeed#<1 then gamespeed#=1 else play sound sndDrop
endif
endif
endif
`}
gosub commandSelectObjects
gosub validateSelection
gosub commandMoveShips
`{
rem Planetary Command Centre
if planetSelected and planet#(planetSelected,3)=1
rem Calculate ship building permits for this planet.
for u = 1 to 4
rem What ship classes can we afford here?
enoughPeople = Planet#(planetSelected,4)>=(ShipClass(u,6)*2) :rem I don't like how this *2 is hidden away in here.
enoughMoney = Planet#(planetSelected,5)>=ShipClass(u,5)
buildPermit(u) = enoughPeople * enoughMoney :`AND logic
next u
if key
rem We want to build a ship.
if key>=2 and key<=5
class = key-1 :`convert scancode to ship class.
rem Can we afford to build this class of ship?
if buildPermit(class)
rem Subtract build cost from planetary resources.
Planet#(planetSelected,4) = Planet#(planetSelected,4)-ShipClass(class,6)
Planet#(planetSelected,5) = Planet#(planetSelected,5)-ShipClass(class,5)
rem Begin construction.
buildError = BuildShip(1,pr(1),Planet#(planetSelected,1),Planet#(planetSelected,2),class,Rnd(359))
play sound sndBuy
endif
endif
endif
endif
`}
rem >> PROCESS >>
if gamespeed#>0
rem Control game timer
gameticks# = (timer()-t1) * gamespeed# * 0.00004
t1=timer()
gosub updatePlanetData
gosub updateShipData
gosub updateAi
gosub checkEndGame
endif
rem >> OUTPUT >>
gosub display
sync:cls
loop
END
rem ======================================
rem === DATA ===
rem ======================================
rem Propaganda Descriptions
data "Glorious", "Righteous", "Noble", "Mighty", "Brave", "Valiant"
data "Vile", "Evil", "Wretched", "Foul", "Savage", "Cowardly"
data 18,15,128,222 :`ascii codes for ship graphics
data "Viper","Falcon","Titan","Colonizer"
data "DEFEND","PREPARE","ATTACK","COLONIZE"
` RACE
` atk,def,pgr,eco, R, G, B,#col, engage dist
data 33, 14, 17, 11, 255, 0, 0, 4, 300
data 17, 26, 11, 14, 180, 0,180, 5, 150
data 14, 11, 20, 17, 0,180, 0, 8, 225
data 11, 17, 14, 20, 255,180, 0, 6, 100
` SHIPS:
` atk,def,spd,rng,cost,POP-cost
data 3, 2, 20, 20, 500, 50
data 6, 5, 15, 27, 1000, 100
data 12,14,10, 34, 2000, 150
data 0, 1, 7, 0, 1500, 500
`//
rem ======================================
rem === SUBROUTINES ===
rem ======================================
arraysAndGlobals:
remstart
(ship classes always ordered: Destroyer, Cruiser, Battleship, Colonizer)
NAME DESCRIPTION DATA
ai ai 0=number of colonies, 1-4=number of ships in each class, 5=number of enemy colonies,
6=colony under attack,7=sync countdown of coming out of defence, 9=Ai state decided on.
buildPermit Ship build 1-4=ship classes by size(1=can build,0=cannot build).
string$ Game text 1-4=race names, 5-8=ship ascii images, 9-12=ship names, 13-16=Ai state strings.
planet$ Planet name 0=planet name.
planet# Planets 1=x, 2=y, 3=owner(0=none,1=human,2=Ai), 4=population, 5=wealth,
6=race(1-4:equal to player or enemy race at time of colonising), 7=K1?, 8=K2?
race Races 1=attack, 2=defence, 3=pgr?, 4=economy, 5=colour, 6=desired colonies, 7=engage distance.
shipClass Ship class 1=attack, 2=defence, 3=speed, 4=range, 5=wealth cost, 6=population cost.
shipx(1) Ship Position 0: current x, 1: destination x.
shipy(1) Ship Position 0: current y, 1: destination y.
shipOwner Ship Data [0=none|1=player|2=Ai]
shipClass Ship Data
shipAttack Ship Attribute
shipDefence Ship Attribute
shipSpeed Ship Attribute
shipRange Ship Attribute
shipHealth Ship Data
shipBuild
shipFightDuration?
shipTimeSinceAttacked
shipAiThing?
1=x 2=y 3=owner 4=class 5=attack 6=defence 7=speed 8=range 9=health 10=destination x, 11=destination y,
12=fight duration, 13=build status(11=complete),
[14]= time since attacked, [15]= some ai thing??
shipsel Ship select [0]= number of ships selected, [1]+ is a list where each entity stores the ID# of a selected ship.
remend
rem Propaganda Descriptions
dim propaganda$(11)
for i = 0 to 11 : read propaganda$(i) : next i
rem DBC "globals"
rem Ship limit
dim shipLim(0)
shipLim = 50 :`yes we need this too because DB doesn't like arrays being used to declare other arrays!
shipLim(0) = shipLim
rem Player and Enemy race
dim PR(2)
rem Colours (colours 1 and 2 are the player colours.)
dim colour(3)
colour(0) = rgb(255,255,255)
colour(3) = rgb(108,108,108)
rem Game Speed Modifier
gamespeed# = 0
rem Define arrays.
dim string$(16)
dim race(4,7)
dim ShipClass(4,6)
dim Ship#(shipLim,15)
dim ShipSel(shipLim)
dim Planet#(31,8)
dim planet$(31)
dim buildPermit(4)
dim ai(9)
rem read-in ship graphics
for t=5 to 8
read a
string$(t)=chr$(a)
next t
rem read-in game text (race names generated in INITIALIZE:)
for t=9 to 16
read a$
string$(t)=a$
next t
rem read race data
race(0,5)=colour(0) :`neutral colour is colour(0).
for t=1 to 4
for u=1 to 7
read a
if u = 5
read b
read c
race(t,u) = rgb(a,b,c)
else
race(t,u)=a
endif
next u
next t
rem read ship class data
for t=1 to 4
for u=1 to 6
read a
ShipClass(t,u)=a
next u
next t
return
`//arraysAndGlobals
makeBackdrop:
create bitmap 1,1024,768
rem HUD border
box 9,9,1013,740
ink 0,0
box 10,10,739,739
box 741,10,1012,739
rem create starry backdrop
maxstars=1024
for t=1 to maxstars
x=rnd(720)+15
y=rnd(720)+15
rem star intensity
i=230
if (t/(maxstars+.0)) >= 0.10 then i=128
if (t/(maxstars+.0)) >= 0.40 then i=64
ink rgb(i,i,i),0
dot x,y
next t
ink colour(0),0
set current bitmap 0
return
`//make backdrop
makeSounds:
meloTheme = newSound(8,"4C{8}E{4}G{4}a{9}-GGFFCCF{9}-eecc3aa4C{8}-{7}C{8}E{4}G{4}5C{9}-4bbaa5CCc{8}--CC4bbaab{8}-{8}")
bassTheme = newSound(8,"3C{16}2F{16}3c{16}a{14}-C{16}F{16}2b{16}3e{16}")
sndFlip = newSound(16,"5DA")
sndDrop = newSound(16,"4AD")
sndBuy = newSound(16,"5D4D5A6D")
sndLaser = newSound(128,"0BAGFEDC1BAGFEDC2BAGFEDC3BAGFEDC4BAGFEDC5BAGFEDC6BAGFEDC7BAGFEDC")
sndClaxon = newSound(128,"1CcDeEFfGaAbB2CcDeEFfGaAbB3CcDeEFfGaAbB4CcDeEFfGaAbB5C{32}3BbAaGfFEeDcC2BbAaGfFEeDcC{32}-{64}")
sndWarp = newSound(64,"0CcDeEFfGaAbB1C0cDeEFfGaAbB1Cc0eEFfGaAbB1CcDe0FfGaAbB1CcDeF0GaAbB1CcDeEFfGaAbB2CcDeEFfGaAbB3CDEFGAB4CDEFGAB5CDEFGAB6CEG7CG8C9C")
sndWarpFail = newSound(64,"0CcDeEFfGaAbB1C0cDeEFfGaAbB1Cc0eEFfGaAbB1CcDe0FfGaAbB1CcDeF0GaAbB1CcDeEFfGaAbB2CcDeEFfGaAbB3CDEFGAB4CDEFGAB5CDE4CDEFGAB3CDEFGAB2CDEFGAB1CDEFGAB0CDEFGAB0BAGFEDC")
return
`//
checkEndGame:
rem check both sides have at least one planet each.
p1=0 : p2=0
for t=1 to 30
if Planet#(t,3)=1 then p1 = 1
if Planet#(t,3)=2 then p2 = 1
if p1=1 and p2=1 then exit
next t
if p1=0 or p2=0
loop sound meloTheme : loop sound bassTheme
if p2=0
a$ = "VICTORY IS OURS!"
b$ = "Congratulations General! You have vanquished The "
else
a$ = "ALL IS LOST!"
b$ = "Your colony has been overrun by The "
endif
cls
center text 512,200,a$
center text 512,250,b$+propaganda$(6+rnd(5))+" "+string$(pr(2))+"s"
wAit 700
sync
wAit key
END
endif
return
`//check end game
commandMoveShips:
rem Is a ship selected?
if ShipSel(0)>0
rem can only issue commands to our own ships!
if ( ShipSel(0)=1 and Ship#(shipsel(1),3)=1 ) or shipsel(0)>1
if mc=2
play sound sndDrop
if mousex()>10 and mousey()>10 and mousex()<740 and mousey()<740
ships = shipsel(0) :`can't use arrays as parameters in loops.
xoffset=0 : yoffset=0
rem Give the ships their movement commands.
for t=1 to ships
if Ship#(shipsel(t),1)>0
`spread out ships
if ships>1
n=(t+4)*1.5
xoff=rnd(n+n)-n
yoff=rnd(n+n)-n
else
xoff=0 : yoff=0
endif
Ship#(shipsel(t),10)=mousex()+xoff
Ship#(shipsel(t),11)=mousey()+yoff
rem keep ships within map
if ship#(shipsel(t),10)<25 then ship#(shipsel(t),10)=25
if ship#(shipsel(t),10)>725 then ship#(shipsel(t),10)=725
if ship#(shipsel(t),11)<25 then ship#(shipsel(t),11)=25
if ship#(shipsel(t),11)>725 then ship#(shipsel(t),11)=725
endif
next t
endif
endif
endif
endif
return
`//command move ships
commandSelectObjects:
rem Begin selection.
if selecting=0 and mc=1 and mousex()<740 and mousey()<740
selecting = 1
planetSelected = 0
ShipSel(0) = 0 :`reset number of ships selected.
rem store mouse position when clicked
mXStart = mousex()
mYStart = mousey()
slogan = rnd(5) :rem randomize propaganda slogans
endif
rem End selection: process selection.
if selecting=1 and mc=0
selecting = 0
rem store mouse position at release
mXEnd = mousex()
mYEnd = mousey()
rem Box selection else pick selection.
if abs(mXEnd + mYEnd - mXStart - mYStart) > 8
rem sort box coordinates
if mXStart > mXEnd then inc mXStart, mXEnd : mXEnd = mXStart-mXEnd : dec mXStart, mXEnd
if mYStart > mYEnd then inc mYStart, mYEnd : mYEnd = mYStart-mYEnd : dec mYStart, mYEnd
rem Mark ships within selection box as selected.
for t=1 to shipLim(0)
ShipSel(t)=0 :`wipe the old selection data just to be tidy.
rem only box-select player owned, constructed ships.
if Ship#(t,3)=1 and Ship#(t,13)>11
if Ship#(t,1)>mXStart and Ship#(t,1)<mXEnd and Ship#(t,2)>mYStart and Ship#(t,2)<mYEnd
ShipSel(0)=ShipSel(0)+1 :`increase the number of ships that have been selected.
ShipSel(ShipSel(0))=t :`place the selected ship in the new list place.
endif
endif
next t
else
chosen = pick(mXEnd,mYEnd)
if chosen>0 and chosen<31 then planetSelected = chosen :rem planet selected (1 to 30)
if chosen>1000 then ShipSel(0)=1 : ShipSel(ShipSel(0))=chosen-1000 :rem ship selected (1000+)
endif
if shipSel(0)+planetSelected >0 then play sound sndFlip
endif
return
`//command select objects
display:
rem refresh backdrop
copy bitmap 1,0
rem Show selection box during selection.
if selecting=1
rem store new mouse position
mX = mousex()
mY = mousey()
rem draw selection box (fiddly but boxes are so much faster than lines)
ax = mxStart : bx = mx
ay = myStart : by = my
if ax > bx then ax = bx+ax : bx = ax-bx : ax = ax-bx
if ay > by then ay = by+ay : by = ay-by : ay = ay-by
box ax,ay,bx,ay
box bx,ay,bx,by
box ax,by,bx,by
box ax,ay,ax,by
endif
` draw PLANETS
set text size 18
for t=1 to 30
a$=""
if Planet#(t,7)>1 then a$="?"
if VIS(Planet#(t,1),Planet#(t,2),1) or omniscience then a$ = "@" : ink colour(planet#(t,3)),0
text Planet#(t,1)-5,Planet#(t,2)-7,a$
ink colour(0),0
next t
set text size 14
`DRAW SHIPS
for t=1 to shipLim(0)
if Ship#(t,3)>0 and Ship#(t,1)>0
if Ship#(t,3)=1 or VIS(Ship#(t,1),Ship#(t,2),1) or omniscience
if Ship#(t,13)<11
ink colour(3),0
else
ink colour(Ship#(t,3)),0
endif
center text Ship#(t,1),Ship#(t,2)-6,string$(int(Ship#(t,4)+4))
endif
endif
next t
ink colour(0),0
rem display selected planet data
if planetSelected
circle Planet#(planetSelected,1),Planet#(planetSelected,2),9
a$="Uninhabited"
s$=""
if Planet#(planetSelected,3)=2
a$="The "+propaganda$(6+slogan)+" "
s$="s"
endif
if Planet#(planetSelected,3)=1
a$="The "+propaganda$(slogan)+" "
s$="s"
rem Display ships for construction, with unaffordable ships in colour(3).
for u=1 to 4
c = 80+buildPermit(u)*175
ink rgb(c,c,c),0
set text size 14
text 760,300+u*20,str$(u)+". BUILD "+string$(u+8)
next u
endif
ink -2,0
text 760,20,str$(planetSelected)
center text 876,40,"-=- "+planet$(planetSelected)+" -=-"
text 760,80,"GOV: "+a$+string$(int(Planet#(planetSelected,6)))+s$
text 760,100,"POP: "+str$(int(Planet#(planetSelected,4)))
text 760,120,"CUR: "+str$(int(Planet#(planetSelected,5)))
endif
rem If single ship selected , display ship data
if ShipSel(0)=1
rem who owns the ship?
if Ship#(ShipSel(1),3)=1
ownerRace$=string$(pr(1))
else
ownerRace$=string$(pr(2))
endif
rem ship weapons status
if Ship#(ShipSel(1),12)>0.1 then weapons$="Weapons Charging" else weapons$="Ready To Fire"
rem ship damage status
if Ship#(ShipSel(1),9)<Ship#(ShipSel(1),6)
damage$="Damaged"
if Ship#(ShipSel(1),14)>5 then damage$ = damage$+", REPAiRING NOW"
else
damage$="All Systems Operational"
endif
rem Under Construction
if ship#(shipsel(1),13)<11
ink 65535,0
text 760,60,"UNDER CONSTRUCTION: "+str$(int(ship#(shipsel(1),13)*9))+"%"
ink colour(0),0
endif
center text 876,40,"-=- "+ownerRace$+" "+string$(int(Ship#(ShipSel(1),4))+8)+" -=-"
text 760,80,"ATK: "+str$(int(Ship#(ShipSel(1),5)))
text 760,100,"DEF: "+str$(int(Ship#(ShipSel(1),9)))+" / "+str$(int(Ship#(ShipSel(1),6)))
text 760,140,weapons$
text 760,160,damage$
rem Ship "cam"
x = ship#(shipsel(1),1) : y = ship#(shipsel(1),2)
set current bitmap 0
get image 1,x-20,y-20,x+20,y+20
box 949,79,991,121
paste image 1,950,80
endif
rem Show selected ship map graphics.
if ShipSel(0)>0
fleetposx#=0:fleetposy#=0:fleetdestx#=0:fleetdesty#=0:fleetmoving=0
for t = 1 to ShipSel(0)
rem circle the selected ship
circle Ship#(ShipSel(t),1),Ship#(ShipSel(t),2),9
rem show friendly ship path
destx# = Ship#(ShipSel(t),10)
desty# = Ship#(ShipSel(t),11)
if destx#>0 AND Ship#(ShipSel(t),3)=1
if ShipSel(0)=1
rem show path if a single ship selected
line Ship#(ShipSel(t),1),Ship#(ShipSel(t),2),destx#,desty#
else
inc fleetmoving
rem store average data for a group selection
fleetposx# = fleetposx# + Ship#(ShipSel(t),1)
fleetposy# = fleetposy# + Ship#(ShipSel(t),2)
fleetdestx# = fleetdestx# + destx#
fleetdesty# = fleetdesty# + desty#
endif
endif
next t
rem show one path for a group selection
if ShipSel(0)>1 and fleetmoving>0
ax = fleetposx#/fleetmoving
ay = fleetposy#/fleetmoving
bx = fleetdestx#/fleetmoving
by = fleetdesty#/fleetmoving
line ax,ay,bx,by
endif
endif
rem display game data
select gamespeed#
case 0 : a$="PAUSED" : endcase
case default : a$=str$(gamespeed#) : endcase
endselect
text 760,700,"GAME SPEED : "+a$
text 760,720,"FPS : "+str$(screen fps())
return
`//display
generateRaces:
rem generate race names
for t=1 to 4
a$=GenerateRace$()
string$(t)=a$
next t
return
`//
initialize:
rem create planets
repeat
fAil=0
sxs=1
for t=1 to 30
yes=1
repeat
inc fAil
x=rnd(690)+30
y=rnd(690)+30
for u=1 to t-1
dist#=d2d(x+.0,y+.0,Planet#(u,1),Planet#(u,2))
if dist#<30
yes=0
endif
next u
until yes=1 or fAil>1500
if fAil<=1500
Planet#(t,1)=x
Planet#(t,2)=y
Planet#(t,3)=0
planet$(t)=generatePlanet$() :`generate planet name.
else
sxs=0
EXIT
endif
next t
until sxs=1
` NEW DESIGNATE HOMEWORLDS
rem Human
X=20
for t=1 to 3
sxs=0
repeat
inc X
for u=1 to 30
if Planet#(u,3)<1
if Planet#(u,1)<x
Planet#(u,3)=1
Planet#(u,4)=1500
Planet#(u,5)=1000
Planet#(u,6)=pr(1)
SXS=1
EXIT
endif
endif
next u
until sxs=1
next t
rem ai
X=720
for t=4 to 6
sxs=0
repeat
dec X
for u=1 to 30
if Planet#(u,3)<1
if Planet#(u,1)>x
Planet#(u,3)=2
Planet#(u,4)=1500
Planet#(u,5)=1000
Planet#(u,6)=pr(2)
SXS=1
EXIT
endif
endif
next u
until sxs=1
next t
return
`//initialize
raceSelect:
loop sound meloTheme : loop sound bassTheme
repeat
gosub generateRaces
rem list races
cls
center text 512,200,"Welcome. Use The Keyboard To Select Your Race"
text 300,300,"1. "+string$(1) : text 600,300," (Warriors)"
text 300,330,"2. "+string$(2) : text 600,330,"(Scientists)"
text 300,360,"3. "+string$(3) : text 600,360," (Breeders)"
text 300,390,"4. "+string$(4) : text 600,390," (Traders)"
center text 512,450,"Press 5 to randomize the race names."
rem wAit for valid key press
repeat
sync
if key=0 then key=scancode() else key=0-scancode()
until key>1 and key<=6
if key = 6 then play sound sndBuy
until key<=5
play sound sndDrop
pr(1)=key-1
rem select enemy race.
enemy = pr(1) + rnd(2)+1
if enemy > 4 then dec enemy,4
pr(2) = enemy
rem store active colours
colour(1) = race(pr(1),5)
colour(2) = race(pr(2),5)
rem display enemy race
center text 512,500,"You Face The "+propaganda$(6+rnd(5))+" "+string$(pr(2))+"s!"
sync:wait 2000:cls
stop sound meloTheme : stop sound bassTheme
return
`//raceSelect
`*** UNEDITED ***
updateAi:
`0 numcol, 1 num DD, 2 num CA, 3 num BB, 4 # colships, 5 num ENEMY colonies,
`6 - colony being attacked. 7. sync countdown of coming out of defense. 9 ai STATE DECIDED ON
`===================Ai====================
` ai STATE determines WHICH SHIP IS BUILT.
` 1. DEFEND. build destroyers. send all ships within DOUBLE engagement range to the attacked planet.
` 2. PREPARE. build cruisers. CA & BB don't move. destroyers PATROL HOME.
` 3. ATTACK. build BB's. send all ships to their nearest seen enemy planet. if no enemy planet is seen, DDs PATROL AWAY.
` 4. COLONIZE. build COL ships. one at a time. (while any colony ships exist). if no empty planets are seen, DDs PATROL AWAY. as long as numcol<numColWant
` clear ai statistics-keeping.
for t=0 to 5
ai(t)=0
next t
NumEnColSeen=0
` ai, count your ships and planets.
for t=1 to 30
if Planet#(t,3)=1 and Planet#(t,8)>0
ai(5)= ai(5)+1
if VIS(Planet#(t,1),Planet#(t,2),2)
inc NumEnColSeen
endif
endif
if Planet#(t,3)=2 then ai(0) = ai(0)+1
next t
for t=1 to shipLim(0)
if Ship#(t,3)=2
ai(int(Ship#(t,4))) = ai(int(Ship#(t,4)))+1
endif
next t
` THIS decides on the ai state.
` if you are NOT under attack, AND you have enough DESTROYERS
if ai(6)=0 and ai(1)>=Ai(0)
` if you don't have enough colonies, AND you don't have any colony ships, then COLONIZE.
if ai(0)<race(pr(2),6) and ai(4)<1
ai(9)=4
else
pow=Ai(1)+Ai(2)*2+Ai(3)*3
snd=Ai(0)*4+Ai(5)
if pow>snd
ai(9)=3 : ` if you have enough ships to attack, then do so.
else
ai(9)=2 : ` otherwise wAit, and keep building.
endif
IF pow>(3*snd) AND ai(0)<25
` ifyou have LOTS of ships and not totally colonized all of space, then colonize.
ai(9)=4
ENDIF
endif
else
ai(9)=1 : ` if you're under attack, or you don't have enough destroyers, then state=1.
endif
if ai(6)>0
ai(7) = ai(7)-1
ai(9)=1
if ai(7)<1
ai(6)=0
endif
endif
` this builds ships based on ai STATE:
if ai(9)>0
for t=1 to 30
if Planet#(t,3)=2
if Planet#(t,4)>ShipClass(Ai(9),6)*2
if Planet#(t,5)>ShipClass(Ai(9),5)
Planet#(t,4) = Planet#(t,4)-ShipClass(Ai(9),6)
Planet#(t,5) = Planet#(t,5)-ShipClass(Ai(9),5)
BuildShip(2,pr(2),Planet#(t,1),Planet#(t,2),Ai(9),Rnd(359))
EXIT : ` ONLY ONE ships is built per cycle, so we don't build too many of something.
endif
endif
endif
next t
endif
` this will build COLONY SHIPS at any owned planet with a POP >2499 , as long as you have <10 colonies
if ai(0)<13
for t=1 to 30
if Planet#(t,3)=2
if Planet#(t,4)>2499
if Planet#(t,5)>ShipClass(4,5)
Planet#(t,4) = Planet#(t,4)-ShipClass(4,6)
Planet#(t,5) = Planet#(t,5)-ShipClass(4,5)
BuildShip(2,pr(2),Planet#(t,1),Planet#(t,2),4,Rnd(359))
endif
endif
endif
next t
endif
` if we are really under attack, defend the colony:
if ai(9)=1
if ai(6)>0
DefendPlanet(Ai(6))
endif
endif
if ai(9)=3
` if ATTACK
for t=1 to shipLim(0)
Ship#(t,15)=0
IF Ship#(t,4)<4
if Ship#(t,3)=2
if Ship#(t,13)>11
if Ship#(t,1)>0
if Ship#(t,10)<10
Ship#(t,15)=99
Ship#(t,10)=rnd(710)+20
Ship#(t,11)=rnd(710)+20
endif
endif
endif
endif
ENDIF
next t
attack()
endif
`these should be called regardless of ai STATE.
`if you have built colony ships, then use them! if you see enemy, attack!
AiEngageShip()
SendColonyShips()
`===================END=Ai====================
return
`//update ai
updatePlanetData:
for t=1 to 30
`grow the pop & economy. make wealth first, then grow pop.
if Planet#(t,3)>0
Planet#(t,5)=Planet#(t,5)+ ( (race(int(Planet#(t,6)),4)*Planet#(t,4))*gameticks#)/250.1
Planet#(t,4)=Planet#(t,4)+ ( (race(int(Planet#(t,6)),3))*gameticks#)
if Planet#(t,4)>2500 then Planet#(t,4)=2500
endif
rem planets visible by human
if VIS(Planet#(t,1),Planet#(t,2),1) or omniscience
Planet#(t,7)=99
endif
rem planets visible by ai
if VIS(Planet#(t,1),Planet#(t,2),2)
Planet#(t,8)=99
endif
next t
return
`//
updateShipData:
`Ship live data: 1=x,2=y,3=own,4=size,5=atk,6=def,7=spd,8=range,9=defLeft,10=targetx,11=targety
` 12=FightTime,13=built,14=Time Since been hit
for t=1 to shipLim(0)
rem Check the ship exists (has an owner).
if Ship#(t,3)>0
rem BUILD SHIPS - once ship#[t,13] reaches 11 the ship is completed.
if Ship#(t,13) <= 11
rem big ships take longer to build.
Ship#(t,13) = Ship#(t,13)+(gameticks#*7)/Ship#(t,4)
endif
` REPAiR SHIPS - any ship that has not been shot in the last 20 gameticks# will start to slowly repAir itself.
Ship#(t,14) = Ship#(t,14)+gameticks#
if Ship#(t,14)>5
if Ship#(t,9)<Ship#(t,6)
Ship#(t,9) = Ship#(t,9)+gameticks#*21
endif
endif
` MOVE SHIPS - move any ship that has a target co-ordinate.
if Ship#(t,10)>0
rem check ship is built
if Ship#(t,13)>11
dx#=(Ship#(t,1)-Ship#(t,10))
dy#=(Ship#(t,2)-Ship#(t,11))
rem destination reached.
if abs(dx#)<3 and abs(dy#)<3
Ship#(t,10)=0
Ship#(t,11)=0
endif
rem move ship towards target
a#=wrapvalue((ATANFULL(dx#,dy#)))
Ship#(t,1)=Ship#(t,1)-( sin(a#)*gameticks#*Ship#(t,7)*3 )
Ship#(t,2)=Ship#(t,2)-( cos(a#)*gameticks#*Ship#(t,7)*3 )
endif
endif
` COLONIZE/ATTACK PLANETS (colonizers don't attack)
Ship#(t,12) = Ship#(t,12)-gameticks#*5
for u=1 to 30
if Ship#(t,4)=4
` Colonize Empty Planets - this works for everybody, automatically.
if Planet#(u,3)=0
if d2d(Ship#(t,1),Ship#(t,2),Planet#(u,1),Planet#(u,2))<7.0
Planet#(u,3)=Ship#(t,3)
Planet#(u,4)=500
Planet#(u,5)=350
Planet#(u,6)=pr(Ship#(t,3))
killShip(t)
play sound sndWarp
endif
endif
else
` Attack Planet
if Ship#(t,12)<0.1
` if you still haven't fired, try to attack planets.
if Planet#(u,3)>0 and Planet#(u,3)<>Ship#(t,3)
if d2d(Ship#(t,1),Ship#(t,2),Planet#(u,1),Planet#(u,2))<20
play sound sndLaser
line Ship#(t,1),Ship#(t,2),Planet#(u,1),Planet#(u,2)
Planet#(u,4) = Planet#(u,4)-Ship#(t,5)
` tell ai one of its planets is under attack.
if Planet#(u,3)=2 AND ai(6)=0
ai(6)=u
ai(7)=500
endif
rem wipe out population.
if Planet#(u,4)<1
Planet#(u,3)=0
Planet#(u,4)=0
Planet#(u,5)=0
Planet#(u,6)=0
endif
Ship#(t,12)=2.5+( rnd(99)/9.9 ):`increase attack time.
EXIT:`only one attack per turn
endif
endif
endif
endif
next u
` SHIPS FIGHT
if Ship#(t,4)<4 : ` colony ships DON'T ATTACK.
if Ship#(t,12)<0.1
`attack an enemy ship
for u=1 to shipLim(0)
if Ship#(u,3)>0 and Ship#(u,3)<>Ship#(t,3)
if d2d(Ship#(t,1),Ship#(t,2),Ship#(u,1),Ship#(u,2))<Ship#(t,8)
play sound sndLaser
line Ship#(t,1),Ship#(t,1),Ship#(u,1),Ship#(u,2)
Ship#(t,12)=2.5+( rnd(99)/9.9 ):`increase attack time.
` enemy ship hit.
Ship#(u,9) = Ship#(u,9)-Ship#(t,5)
Ship#(u,14)=0
` kill dead ships:
if Ship#(u,9)<1
killShip(u)
` since ship T killed ship U, give ship T some EXPERIENCE.
Ship#(T,5) = Ship#(T,5)+(Ship#(t,4)) : ` +1 atk/size
Ship#(T,6) = Ship#(T,6)+5*(Ship#(t,4)) : ` +5 DEF per size
Ship#(T,7) = Ship#(T,7)+1 : ` +1 SPD regardless of size
Ship#(T,8) = Ship#(T,8)+1 : ` +1 RNG regardless of size
endif
EXIT:`only one attack per turn
endif
endif
next u
endif
endif
endif
next t
return
`//update ship data
validateSelection:
if omniscience=0
rem Non-human planet still visible.
if planetSelected and planet#(planetSelected,3)!1
if VIS(planet#(planetSelected,1),planet#(planetSelected,2),1)=0 then planetSelected=0
endif
rem Enemy Ship still visible.
if ShipSel(0)=1
if ship#(ShipSel(1),3)=2
if VIS(ship#(ShipSel(1),1),ship#(ShipSel(1),2),1)=0 then ShipSel(0)=0
endif
endif
endif
return
`//
rem ======================================
rem === FUNCTIONS ===
rem ======================================
function killShip(n)
ship#(n,1)=0
ship#(n,2)=0
ship#(n,3)=0
ship#(n,4)=0
ship#(n,5)=0
ship#(n,6)=0
ship#(n,7)=0
ship#(n,8)=0
ship#(n,9)=0
ship#(n,10)=0
ship#(n,11)=0
ship#(n,12)=0
ship#(n,13)=0
ship#(n,14)=0
ship#(n,15)=0
deselectShip(n)
endfunction
`//
function deselectShip(n)
rem Find and remove the ship from the selection list.
for t = 1 to ShipSel(0)
if ShipSel(t)=n
`Move higher entries down to fill the gap.
for bump = t to ShipSel(0)-1
ShipSel(bump) = ShipSel(bump+1)
next bump
ShipSel(ShipSel(0))=0 :`Delete last entry which is no longer needed.
ShipSel(0) = ShipSel(0)-1 :`reduce number of ships in the list.
EXIT
endif
next t
endfunction
`//
function d2d(ax#,ay#,bx#,by#)
rem distance between A and B.
dist#=sqrt( (ax#-bx#)*(ax#-bx#) + (ay#-by#)*(ay#-by#) )
endfunction dist#
`//
Function VIS(x#,y#,p)
rem This function determines whether player P can see coord x,y. 0=no, 1=yes
V=0
for t=1 to shipLim(0)
if Ship#(t,3)=p
if Ship#(t,13)>11
dist#=d2d(Ship#(t,1),Ship#(t,2),x#,y#)
if dist#<50 then V=1 : EXIT
endif
endif
next t
for t=1 to 30
if int(Planet#(t,3))=p
dist#=d2d(Planet#(t,1),Planet#(t,2),x#,y#)
if dist#<100 then V=1 : EXIT
endif
next t
Endfunction V
`//
Function PICK(x,y)
`Only the HUMAN player uses this function. Returns 0 for nothing picked, 1-30 for a planet, 1001-2000 for a ship.
for t=1 to 30
if VIS(Planet#(t,1),Planet#(t,2),1)
if d2d(Planet#(t,1),Planet#(t,2),x+.0,y+.0)<7 then exitfunction t
endif
next t
rem Only check for ships if no planet is found.
for t=1 to shipLim(0)
if VIS(Ship#(t,1),Ship#(t,2),1)
if d2d(Ship#(t,1),Ship#(t,2),x+.0,y+.0)<7 then exitfunction t+1000
endif
next t
Endfunction 0
`//
Function BuildShip(owner,race,x#,y#,class,ang)
for s = 1 to shipLim(0)
if Ship#(s,3)=0.0 then exit
next s
if s>shipLim(0) then exitfunction -1 :`break if no id avAilable
killShip(s) :`wipe old data
Ship#(s,1)=x#+(sin(ang)*16)
Ship#(s,2)=y#+(cos(ang)*16)
Ship#(s,3)=owner
Ship#(s,4)=class
Ship#(s,5)=race(race,1)*ShipClass(class,1)
Ship#(s,6)=race(race,2)*ShipClass(class,2)*15
Ship#(s,7)=ShipClass(class,3)
Ship#(s,8)=ShipClass(class,4)
Ship#(s,9)=race(race,2)*ShipClass(class,2)*15
Endfunction
`//
Function aiEngageShip()
rem if an ai ship SEES another ship (and it's not already in combat) ,
rem it might just attack that other ship. but there is a range limit.
rem this should NOT happen if ai STATE is DEFEND.
for t=1 to shipLim(0)
if Ship#(t,3)=2
if Ship#(t,13)>11
if Ship#(t,1)>0
if Ship#(t,4)<4
if Ship#(t,14)>8
for u=1 to shipLim(0)
if Ship#(u,3)=1
if Ship#(u,13)>11
if Ship#(u,1)>0
if VIS(Ship#(u,1),Ship#(u,2),2) : ` if we see this enemy ship.
if d2d(Ship#(t,1),Ship#(t,2),Ship#(u,1),Ship#(u,2))<race(pr(2),7) : ` if its within our ENGAGEMENT RANGE
Ship#(t,10)=Ship#(u,1)+rnd(15)-8
Ship#(t,11)=Ship#(u,2)+rnd(15)-8
EXIT
endif
endif
endif
endif
endif
next u
endif
endif
endif
endif
endif
next t
Endfunction
`//
Function DefendPlanet(p)
for t=1 to shipLim(0)
if Ship#(t,3)=2
if Ship#(t,13)>11
if Ship#(t,1)>0
if Ship#(t,4)<4
if d2d(Ship#(t,1),Ship#(t,2),Planet#(p,1),Planet#(p,2))<450 : ` make defense much more of a Priority. : ` (race(er,7)*2)
Ship#(t,10)=Planet#(p,1)+rnd(15)-8
Ship#(t,11)=Planet#(p,2)+rnd(15)-8
endif
endif
endif
endif
endif
next t
Endfunction
`//
Function SendColonyShips()
for t=1 to shipLim(0)
IF Ship#(t,4)=4
if Ship#(t,3)=2
if Ship#(t,13)>11
if Ship#(t,1)>0
dis=999
plan=0
for u=1 to 30
if Planet#(u,3)=0
if VIS(Planet#(u,1),Planet#(u,2),2)
dist#=d2d(Planet#(u,1),Planet#(u,2),Ship#(t,1),Ship#(t,2))
if dist#<dis
dis=dist#
plan=u
endif
endif
endif
next u
if plan>0
Ship#(t,10)=Planet#(plan,1)
Ship#(t,11)=Planet#(plan,2)
endif
endif
endif
endif
ENDIF
next t
Endfunction
`//
Function ATTACK()
for t=1 to shipLim(0)
if Ship#(t,3)=2
if Ship#(t,13)>11
if Ship#(t,1)>0
if Ship#(t,4)<4
dis=999
plan=0
for u=1 to 30
if Planet#(u,3)=1
if VIS(Planet#(u,1),Planet#(u,2),2)
dist#=d2d(Planet#(u,1),Planet#(u,2),Ship#(t,1),Ship#(t,2))
if dist#<dis
dis=dist#
plan=u
endif
endif
endif
next u
if plan>0
Ship#(t,10)=Planet#(plan,1)
Ship#(t,11)=Planet#(plan,2)
endif
endif
endif
endif
endif
next t
Endfunction
`//
rem *** OBESE87'S RANDOM NAME GENERATOR FUNCTIONS ***
function GenerateRace$()
race$ = ""
race$ = GeneratePlanet$()
rem Select a suffix depending on the last letter.
last$ = right$(race$,1)
select last$
case "a" "e" "o" "i" "u" : k=rnd(5) : endcase
case default : k=rnd(4)+4 : endcase
endselect
select k
case 0 : race$ = race$+"n" : endcase
case 1 : endcase
case 2 : race$ = race$+"can" : endcase
case 3 : race$ = race$+"ni" : endcase
case 4 : race$ = race$+"an" : endcase
case 5 : race$ = race$+"on" : endcase
case 6 : race$ = race$+"i" : endcase
case 7 : race$ = race$+"ese" : endcase
case 8 : race$ = race$+"ite" : endcase
endselect
endfunction race$
`//
function GeneratePlanet$()
planet$=""
rem Define number of character pAirs to generate.
nameLen = rnd(1)+2
for i = 1 to nameLen
rem After first letter switch to lower case.
if i>1 then capoff=32 else capoff=0
rem Get a random parent character.
Parent = rnd(25)+65
rem Make sure name doesn't end in "QU".
if i=nameLen
if Parent=81 then Parent=Parent-1-rnd(15)
endif
rem Add parent to planet name.
planet$ = planet$+chr$(Parent+capoff)
rem Generate child from parent.
Select Parent
rem Q.
Case 81 : planet$=planet$+"u" : Endcase
rem Vowel.
Case 65 or 69 or 73 or 79 or 85
child = rnd(5)
if child=0 then planet$=planet$+"d"
if child=1 then planet$=planet$+"l"
if child=2 then planet$=planet$+"n"
if child=3 then planet$=planet$+"r"
if child=4 then planet$=planet$+"s"
if child=5 then planet$=planet$+"t"
Endcase
rem Consonant.
Case Default
child = rnd(4)
if child=0 then planet$=planet$+"a"
if child=1 then planet$=planet$+"e"
if child=2 then planet$=planet$+"i"
if child=3 then planet$=planet$+"o"
if child=4 then planet$=planet$+"u"
Endcase
next i
endfunction planet$
`//
function newSound(bps,music$)
rem Find avAilable sound
for snd = 1 to 255
if sound exist(snd)=0 then exit
next snd
if snd > 255 then end
rem Find avAilable memblock.
for mem = 1 to 255
if memblock exist(mem)=0 then exit
next mem
if mem > 255 then end
rem Define constants and variables.
strLen = len(music$)
memPtr = 12
samplerate# = 40000
` samplerate# = 26624 :`Why this number?
soundsize = samplerate# / bps
rem Find number of actual notes in music$.
i=0 :`forgot variables inside function are persistent: eugh DB is not a good example for new coders. No other language I know does this. :'(
for x = 1 to strLen
n$ = mid$(music$,x)
if val(n$)=0
rem Number inside curly brackets denotes note length.
if n$="{"
for bracket = x+1 to strLen
if mid$(music$,bracket) = "}"
numinbracket = val(snippet$(music$,x+1,bracket-1))-1 :`we minus one from the length because note will have been counted by itself.
inc i,numinbracket :`add number in brackets to note count.
x = bracket : `this just moves the x pointer past the brackets.
exit
endif
next bracket
else
inc i :`single note
endif
endif
next x
rem Make the soundblock
size=(soundsize*i)+12
make memblock mem,size
rem write header
write memblock dword mem,0,8
write memblock dword mem,4,samplerate#
write memblock dword mem,8,size
rem write notes
for x=1 to strLen
n$=mid$(music$,x)
if asc(n$) >= 48 and asc(n$) <=57 :`n$ is a number.
octave = val(n$)
else
rem Numbers inside curly brackets denotes note length.
if n$="{"
for bracket = x+1 to strLen
if mid$(music$,bracket) = "}"
numinbracket = val(snippet$(music$,x+1,bracket-1))-1 :`we minus one from the length because note will have been counted by itself.
n$ = mid$(music$,x-1) :`take the note before the brackets.
x = bracket : `this just moves the pointer past the brackets.
bracket = strLen
endif
next bracket
else
numinbracket = 1
endif
for noteLen = 1 to numinbracket
rem -- Store Note --
remstart
WTF IS THE PROBLEM HERE? WHY WONT THE SELECT COMMAND WORK NOW!?!? >:(
select n$
case "C" : nt#=2093.00 : endcase
case "c" : nt#=2217.46 : endcase :`C#/Db
case "D" : nt#=2349.32 : endcase
case "e" : nt#=2489.02 : endcase :`Eb/D#
case "E" : nt#=2637.02 : endcase
case "F" : nt#=2793.83 : endcase
case "f" : nt#=2959.96 : endcase :`F#/Gb
case "G" : nt#=3135.96 : endcase
case "a" : nt#=3322.44 : endcase :`Ab/G#
case "A" : nt#=3520.00 : endcase
case "b" : nt#=3729.31 : endcase :`Bb/A#
case "B" : nt#=3951.07 : endcase
case default : nt#=-1 : endcase :`no note (pause)
endselect
remend
nt#=-1
if n$ = "C" then nt#=2093.00
if n$ = "c" then nt#=2217.46
if n$ = "D" then nt#=2349.32
if n$ = "e" then nt#=2489.02
if n$ = "E" then nt#=2637.02
if n$ = "F" then nt#=2793.83
if n$ = "f" then nt#=2959.96
if n$ = "G" then nt#=3135.96
if n$ = "a" then nt#=3322.44
if n$ = "A" then nt#=3520.00
if n$ = "b" then nt#=3729.31
if n$ = "B" then nt#=3951.07
if nt#>-1
hz# = nt# / 2^(7.0-octave)
anginc# = 360.0 * hz# / samplerate#
for xx = memPtr to memPtr+soundsize-1
ang#=wrapvalue(ang#+anginc#)
b = 128 + sin(ang#) :`since integers are truncated b will always be 127 or 128. (Except when ang#= 90|270 then b= 126|129.)
write memblock byte mem,xx,b
next xx
endif
inc memPtr, soundsize
next noteLen
endif
next x
make sound from memblock snd,mem
set sound volume snd,5 :rem Default volume is bloody loud!
delete memblock mem
endfunction snd
`//
function snippet$(a$,head,tAil)
return$ = right$(left$(a$,tAil),tAil+1-head)
endfunction return$
`//
"I am a big dumb babby!

" - TheComet