Thanks, I hadn't coded for a while so I really got into it.
My computer is really slow so now I'm trying to find ways to keep the FPS respectable when lots of ships are built.
A problem I noticed about the AI is when you destroy one of their planets they continue to try to defend it. I don't if that's because of something I changed or not.
Updates:
* New subroutine checks if the current selection is still valid (i.e. if you can still see enemy ships you've selected etc)
* Stars are drawn to an off-screen bitmap before the main loop and copied to screen each cycle. Allows for more a complex background while actually gaining a few FPS.
rem Space RTS - by IBOL - 20th March 2010
rem Edited by OBese87 v2.04
rem ------------
set display mode 1024,768,32
sync on
sync rate 0
randomize timer()
set text font "lucida console",1
set text size 16
gosub arrays_and_globals
gosub race_select
gosub initialize
rem === MAIN ===
DO
rem >> INPUT >>
gosub game_speed_control
if spacekey() then Show_Visible()
gosub command_select_objects
rem Don't update or allow commands while paused.
if gsm>0
gosub validate_selection
gosub command_move_ships
gosub command_build_ships
rem >> PROCESS >>
gosub update_planet_data
gosub update_ship_data
` gosub update_ai
gosub check_end_game
endif
rem >> OUTPUT >>
gosub display
sync:cls
loop
END
rem ======================================
rem === DATA ===
rem ======================================
data "-",">","#","@","Destroyer","Cruiser","Battleship","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 ======================================
arrays_and_globals:
remstart
(ship classes always ordered: Destroyer, Cruiser, Battleship, Colonizer)
NAME INFORMATION 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.
cb Ship build 1-4=ship classes by size(1=can build,0=cannot build).
n$ 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.
panet# 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.
ship_class Ship class 1=attack, 2=defence, 3=speed, 4=range, 5=wealth cost, 6=population cost.
ship# Ship data 1=x, 2=y, 3=owner, 4=size, 5=attack, 6=defence, 7=speed, 8=range, 9=defence remaining,
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+=list where each entity stores the ID# of a selected ship.
star Stars 1=x, 2=y, 3=intensity(colour).
remend
rem Array limit variables.
maxstars = 2096
maxships = 1000
rem Define arrays.
dim n$(16)
dim race(4,7)
dim Ship_Class(4,6)
dim Ship#(maxships,15)
dim ShipSel(maxships)
dim star(maxstars,3)
dim Planet#(31,8)
dim planet$(31)
dim CB(4)
dim AI(9)
rem DBC "globals"
dim PR(0) : ` player race (1-4)
dim ER(0) : ` enemy race (1-4), cannot equal PR.
rem Colours used inside main loop (don't need to be arrays)
white = rgb(255,255,255)
grey = rgb(108,108,108)
rem Game Speed Modifier. 0(PAUSED)-20%-40%-60%-80%-100%-200%-300%-400%
GSM = 0
rem read game graphics and text (race names generated in INITIALIZE:)
for t=5 to 16
read a$
n$(t)=a$
next t
rem read race data
race(0,5)=white :`neutral colour is white.
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
Ship_Class(t,u)=a
next u
next t
return
`//arrays_and_globals
check_end_game:
c1=0 : c2=0
for t=1 to 30
if Planet#(t,3)=1 then inc c1
if Planet#(t,3)=2 then inc c2
next t
if c1<1 or c2<1
if c2<1
a$ = "CONGRATULATIONS! YOU WIN!"
b$ = "You have defeated The Evil "
else
a$ = "YOU LOSE!"
b$ = "You have been defeated by The Evil "
endif
cls
center text 512,200,a$
center text 512,250,b$+n$(ER(0))+"s"
wait 700
sync
wait key
END
endif
return
`//check end game
command_build_ships:
rem Accept input?
if SC<=0 then inputOK=1
SC=scancode()-1
if inputOK
inputOK=0 :`don't repeat the same input twice.
if planet_selected>0 and sc>=1 and sc<=4
if Planet#(planet_selected,3)=1
rem Can we build this ship?
if CB(SC)=1
` you CAN build this ship, and you just Pressed the key to do it!
Planet#(planet_selected,4) = Planet#(planet_selected,4)-Ship_Class(sc,6)
Planet#(planet_selected,5) = Planet#(planet_selected,5)-Ship_Class(sc,5)
Build_Ship(1,PR(0),Planet#(planet_selected,1),Planet#(planet_selected,2),SC,Rnd(359))
rem ?? stop us from building more ships ??
for u=1 to 4
CB(u)=0
next u
endif
endif
endif
endif
return
`//command_build_ships
command_move_ships:
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 mouseclick()=2
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
command_select_objects:
old_LMB = new_LMB
new_LMB = (mouseclick()=1)
rem Begin selection.
if selecting=0 and new_LMB>old_LMB and mousex()<740 and mousey()<740
selecting = 1
planet_selected = 0
ShipSel(0) = 0 :`set list cursor to 0.
rem store mouse position when clicked
mX_start = mousex()
mY_start = mousey()
endif
rem End selection: process selection.
if selecting=1 and new_LMB<old_LMB
selecting = 0
rem store mouse position at release
mX_end = mousex()
mY_end = mousey()
rem sort box coordinates
if mX_start > mX_end then inc mX_start, mX_end : mX_end = mX_start-mX_end : dec mX_start, mX_end
if mY_start > mY_end then inc mY_start, mY_end : mY_end = mY_start-mY_end : dec mY_start, mY_end
rem Box selection else pick selection.
if (mX_end-mX_start)>5 or (mY_end-mY_start)>5
rem Mark ships within selection box as selected.
for t=1 to 250
ShipSel(t)=0 :`wipe the old selection data just to be tidy.
if Ship#(t,3)=1 and Ship#(t,13)>11
if Ship#(t,1)>mX_start and Ship#(t,1)<mX_end
if Ship#(t,2)>mY_start and Ship#(t,2)<mY_end
rem Only human ships can be box selected.
if Ship#(t,3)=1
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
endif
endif
next t
else
chosen = pick(mX_end,mY_end)
rem DUPLICATED CODE (would possibly slow down box selection if I moved it outside though)
rem I don't really need this now that only the list items that the list cursor points to are used
rem but I'll keep it for now because it tidies things up. :D
for t=0 to 250
ShipSel(t)=0
next t
rem planet selected
if chosen>0 and chosen<31 then planet_selected = chosen
rem ship selected
if chosen>1000 then ShipSel(0)=1 : ShipSel(ShipSel(0))=chosen-1000
endif
endif
return
`//command select objects
display:
rem Refresh Star Backdrop
copy bitmap 1,0,0,729,729, 0,10,10,739,739
rem HUD border.
line 10,10,740,10
line 10,10,10,740
line 740,10,740,740
line 10,740,740,740
line 10,10,1013,10
line 1013,10,1013,740
line 10,740,1013,740
rem Show selection box during selection.
if selecting=1
rem store new mouse position
mX = mousex()
mY = mousey()
rem draw selection box (clockwise)
line mX_start,mY_start,mx,mY_start
line mX,mY_start,mX,mY
line mX_start,mY,mX,mY
line mX_start,mY_start,mX_start,mY
endif
` draw PLANETS
set text size 18
for t=1 to 30
a$=""
if Planet#(t,7)>1
a$="*"
endif
if VIS(Planet#(t,1),Planet#(t,2),1)
a$ = str$(Planet#(t,3))
if a$="0" then a$ ="O"
endif
text Planet#(t,1)-5,Planet#(t,2)-7,a$
next t
set text size 14
`DRAW SHIPS
for t=1 to 250
if Ship#(t,3)>0 and Ship#(t,1)>0
if Ship#(t,3)=1 or VIS(Ship#(t,1),Ship#(t,2),1)
if Ship#(t,13)<11
ink grey,0
else
if Ship#(t,3)=1
ink race(PR(0),5),0
else
ink race(ER(0),5),0
endif
endif
center text Ship#(t,1),Ship#(t,2)-6,n$(int(Ship#(t,4)+4))
endif
endif
next t
ink white,0
rem display selected planet data
if planet_selected>0
circle Planet#(planet_selected,1),Planet#(planet_selected,2),9
a$="Empty"
s$=""
if Planet#(planet_selected,3)=2
a$="The Evil "
s$="s"
endif
if Planet#(planet_selected,3)=1
a$="The Glorious "
s$="s"
`Display which ships can currently be built at this planet.
for u=1 to 4
CB(u)=0
if Planet#(planet_selected,5)>=Ship_Class(u,5)
if Planet#(planet_selected,4)>=(Ship_Class(u,6)*2)
CB(u)=1
text 760,300+u*20,str$(u)+". BUILD "+n$(u+8)
endif
endif
next u
endif
text 760,40,"- "+planet$(planet_selected)+" -"
text 760,60,a$+n$(int(Planet#(planet_selected,6)))+s$
text 760,80,"POP : "+str$(int(Planet#(planet_selected,4)))
text 760,100,"WEALTH : "+str$(int(Planet#(planet_selected,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
owner$="Human"
owner_race$=n$(PR(0))
else
owner$="A.I."
owner_race$=n$(ER(0))
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
text 760,40,owner$+" Ship # "+str$(ShipSel(1))
text 760,60,owner_race$+" "+n$(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$
endif
rem Show selected ship map graphics.
if ShipSel(0)>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 paths
if Ship#(ShipSel(t),10)>0 AND Ship#(ShipSel(t),3)=1
line Ship#(ShipSel(t),1),Ship#(ShipSel(t),2),Ship#(ShipSel(t),10),Ship#(ShipSel(t),11)
endif
next t
endif
rem display game data
select gsm
case 0 : a$="PAUSED" : endcase
case default : a$=str$(gsm/20) : endcase
` case default : a$="" : box 864,700,864+gsm/3,712 : endcase
endselect
text 760,700,"GAME SPEED : "+a$
text 760,720,"FPS : "+str$(screen fps())
return
`//display
game_speed_control:
rem Control game timer
gs#=((timer()-t1) * 0.0000033)*GSM
t1=timer()
rem Adjust game speed (+/- keys) Pause "P".
oldsc = newsc
newsc = scancode()
rem key pressed
if newsc<>oldsc and newsc>0
select newsc
case 12
if gsm<=100 then gsm = gsm-20 else gsm = gsm-100
if gsm<20 then gsm=20
endcase
case 13
if gsm<100 then gsm = gsm+20 else gsm = gsm+100
if gsm>400 then gsm=400
endcase
case 25 : gsm=0 : endcase
endselect
endif
remstart
oldminus=newminus
newminus=keystate(12)
if newminus>oldminus
if gsm<=100 then gsm = gsm-20 else gsm = gsm-100
if gsm<20 then gsm=20
endif
oldplus=newplus
newplus=keystate(13)
if newplus>oldplus
if gsm<100 then gsm = gsm+20 else gsm = gsm+100
if gsm>400 then gsm=400
endif
remend
return
`//
generate_races:
rem generate race names
for t=1 to 4
a$=Generate_Race$()
n$(t)=a$
next t
return
`//
initialize:
rem position stars
for t=1 to maxstars
x=rnd(720)+5
y=rnd(720)+5
rem star intensity
i=255
if (t/(maxstars+.0)) >= 0.10 then i=128
if (t/(maxstars+.0)) >= 0.40 then i=64
star(t,1)=x
star(t,2)=y
star(t,3)=rgb(i,i,i)
next t
rem create starry backdrop
create bitmap 1,730,730
for t=1 to maxstars
ink star(t,3),0
dot star(t,1),star(t,2)
next t
ink white,0
set current bitmap 0
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)=generate_planet$() :`generate planet name.
else
sxs=0
EXIT
endif
next t
until sxs=1
rem Set ships' initial data
for s=1 to 250
for u=1 to 14
Ship#(s,u)=-99
next u
next s
` 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(0)
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)=ER(0)
SXS=1
EXIT
endif
endif
next u
until sxs=1
next t
return
`//initialize
race_select:
repeat
gosub generate_races
rem list races
cls
center text 512,200,"Welcome. Use The Keyboard To Select Your Race"
text 300,300,"1. "+n$(1) : text 600,300," (Warriors)"
text 300,330,"2. "+n$(2) : text 600,330,"(Scientists)"
text 300,360,"3. "+n$(3) : text 600,360," (Breeders)"
text 300,390,"4. "+n$(4) : text 600,390," (Traders)"
center text 512,450,"Press 5 to randomize the race names."
rem wait for valid key press
repeat
sc=scancode()-1
sync
until sc>0 and sc<=5
rem wait for key release
repeat : until scancode()=0
until sc<=4
PR(0)=SC
rem select enemy race.
enemy = PR(0) + rnd(2)+1
if enemy > 4 then dec enemy,4
ER(0) = enemy
rem display enemy race
center text 512,500,"You Face The Evil "+n$(ER(0))+"s!"
sync:wait 2000:cls
return
`//race_select
`*** UNEDITED ***
update_ai:
`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<num_col_want
` 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 250
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(ER(0),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)>Ship_Class(ai(9),6)*2
if Planet#(t,5)>Ship_Class(ai(9),5)
Planet#(t,4) = Planet#(t,4)-Ship_Class(ai(9),6)
Planet#(t,5) = Planet#(t,5)-Ship_Class(ai(9),5)
Build_Ship(2,ER(0),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)>Ship_Class(4,5)
Planet#(t,4) = Planet#(t,4)-Ship_Class(4,6)
Planet#(t,5) = Planet#(t,5)-Ship_Class(4,5)
Build_Ship(2,ER(0),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
Defend_Planet(ai(6))
endif
endif
if ai(9)=3
` if ATTACK
for t=1 to 250
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!
AI_Engage_Ship()
Send_Colony_Ships()
`===================END=AI====================
return
`//update ai
update_planet_data:
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))*gs#)/250.1
Planet#(t,4)=Planet#(t,4)+ ( (race(int(Planet#(t,6)),3))*gs#)
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)
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 planet
return
`//
update_ship_data:
`Ship live data: 1=x,2=y,3=own,4=size,5=atk,6=def,7=spd,8=range,9=def_left,10=targetx,11=targety
` 12=FightTime,13=built,14=Time Since been hit
for t=1 to 250
rem Check the ship exists (has an owner).
if Ship#(t,3)>0
` BUILD SHIPS - once (,13) reaches 11 the ship is completed.
if Ship#(t,13)<12
rem big ships take longer to build.
Ship#(t,13) = Ship#(t,13)+(gs#*7)/Ship#(t,4)
endif
` REPAIR SHIPS - any ship that has not been shot in the last 20 gs# will start to slowly repair itself.
Ship#(t,14) = Ship#(t,14)+gs#
if Ship#(t,14)>5
if Ship#(t,9)<Ship#(t,6)
Ship#(t,9) = Ship#(t,9)+gs#*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#)*gs#*Ship#(t,7)*3 )
Ship#(t,2)=Ship#(t,2)-( cos(a#)*gs#*Ship#(t,7)*3 )
endif
endif
` COLONIZE/ATTACK PLANETS - colonizers don't attack.
Ship#(t,12) = Ship#(t,12)-gs#*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
if Ship#(t,3)=1 then Planet#(u,6)=PR(0) else Planet#(u,6)=ER(0)
Ship#(t,3)=0
Ship#(t,1)=0
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
line Ship#(t,1),Ship#(t,2),Planet#(u,1),Planet#(u,2)
for a=int(Ship#(t,1))-2 to int(Ship#(t,1))+2
for b=int(Ship#(t,2))-2 to int(Ship#(t,2))+2
line a,b,Planet#(u,1),Planet#(u,2)
next b
next a
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 250
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)
for a=int(Ship#(t,1))-2 to int(Ship#(t,1))+2
for b=int(Ship#(t,2))-2 to int(Ship#(t,2))+2
line a,b,Ship#(u,1),Ship#(u,2)
next b
next a
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
Ship#(u,3)=0
Ship#(u,10)=0
Ship#(u,1)=-99
` 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
validate_selection:
rem Non-human planet still visible.
if planet_selected and planet#(planet_selected,3)<>1
if VIS(planet#(planet_selected,1),planet#(planet_selected,2),1)=0 then planet_selected=0
endif
rem Ships
if ShipSel(0)>0
rem Enemy ship still visible.
if ship#(ShipSel(1),3)=2
if VIS(ship#(ShipSel(1),1),ship#(ShipSel(1),2),1)=0 then deselect_ship(ShipSel(1))
else
rem Check for dead ships.
for t = 1 to ShipSel(0)
if Ship#(ShipSel(t),3)=0 then deselect_ship(ShipSel(t))
next t
endif
endif
return
`//
rem ======================================
rem === FUNCTIONS ===
rem ======================================
function deselect_ship(deselect)
rem Find and remove the ship from the selection list.
for t = 1 to ShipSel(0)
if ShipSel(t)=deselect
for writeship = t to ShipSel(0)-1
ShipSel(writeship) = ShipSel(writeship+1) :`Move higher entries down to fill the gap.
next writeship
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#
` if all data was stored at the end of this function, it may work for a 20 line game.
Function VIS(x#,y#,p)
` this function determines whether player P can see coord x,y. 0=no, 1=yes
V=0
for t=1 to 250
if Ship#(t,3)=p
if Ship#(t,13)>11
dist#=d2d(Ship#(t,1),Ship#(t,2),x#,y#)
if dist#<50
V=1
EXIT
endif
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
V=1
EXIT
endif
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.
V=0
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
V=t
EXIT
endif
endif
next t
rem Only check for ships if no planet is found.
if V=0
for t=1 to 250
if VIS(Ship#(t,1),Ship#(t,2),1)
if Ship#(t,13)>11
if d2d(Ship#(t,1),Ship#(t,2),x+.0,y+.0)<7
V=1000+t
EXIT
endif
endif
endif
next t
endif
Endfunction V
Function Build_Ship(Own,Race,x#,y#,Size,ang)
S=0
repeat
inc S
until Ship#(s,3)<1 or s>250
if s<250
for u=1 to 14
Ship#(s,u)=0
next u
Ship#(s,1)=x#+(sin(ang)*13)
Ship#(s,2)=y#+(cos(ang)*13)
Ship#(s,3)=own
Ship#(s,4)=size
Ship#(s,5)=race(race,1)*Ship_Class(size,1)
Ship#(s,6)=race(race,2)*Ship_Class(size,2)*15
Ship#(s,7)=Ship_Class(size,3)
Ship#(s,8)=Ship_Class(size,4)
Ship#(s,9)=race(race,2)*Ship_Class(size,2)*15
endif
Endfunction
Function Show_Visible()
for t=1 to 250
if Ship#(t,3)=1
if Ship#(t,13)>11
circle Ship#(t,1),Ship#(t,2),50
endif
endif
next t
for t=1 to 30
if Planet#(t,3)=1
if Planet#(t,4)>0
circle Planet#(t,1),Planet#(t,2),100
endif
endif
next t
Endfunction
Function AI_Engage_Ship()
` if an AI ship SEES another ship (and it's not already in combat) ,
` it might just attack that other ship. but there is a range limit.
` this should NOT happen if AI STATE is DEFEND.
for t=1 to 250
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 250
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(ER(0),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 Defend_Planet(p)
for t=1 to 250
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 Send_Colony_Ships()
for t=1 to 250
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 250
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 Generate_Race$()
race$ = ""
race$ = Generate_Planet$()
rem Select a suffix depending on the last letter.
last$ = right$(race$,1)
select last$
case "a" : race$ = race$+"n" : endcase
case "e" : race$ = race$+"sian" : endcase
case "i" : endcase
case "o" : race$ = race$+"tian" : endcase
case "u" : race$ = race$+"can" : endcase
case default : race$ = race$+"ian" : endcase
endselect
endfunction race$
`//
function Generate_Planet$()
planet$=""
rem Define number of character pairs to generate.
name_len = rnd(1)+2
for i = 1 to name_len
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=name_len
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$
`//
Ideas:
* Multiple enemies: maybe have all four races competing against each other? I haven't gotten the gist of the AI yet so if you are still working on it that would be a cool thing to add.
* Display game time.
* Store and display number of kills by each ship. Taking it further ships could have a rank (private, lieutenant) associated with the ship's kills.
* Option to build planetary defences.
* Low-res generated graphics. I've made some that I might use but it's not a priority. I mainly want to do this so I could write the images to a memblock which would increase FPS for my old machine lol.
set display mode 1024,768,32
sync on
dim colour(4)
colour(1) = rgb(255,0,0)
colour(2) = rgb(180,0,180)
colour(3) = rgb(0,180,0)
colour(4) = rgb(255,180,0)
for ship = 1 to 4
read width
read height
shipx = ship*150
for iy = 0 to height-1
for ix = 0 to width-1
read pt
if pt=1
for race = 1 to 4
ink colour(race),0
`horizontal image
dot shipx+ix,iy+(race*50)
`reverse horizontal image
dot shipx+width*2.5-ix,iy+(race*50)
`vertical image
dot shipx+iy+width*2.5+height*2,ix+(race*50)-width/2
`reverse vertical image
dot shipx+iy+width*2.5+height*4,(race*50)+width/2-ix
next race
endif
next ix
next iy
next ship
sync
end
rem Destroyer (7x5)
data 7,5
data 0,1,1,0,0,0,0
data 0,0,1,1,0,0,0
data 0,1,1,1,1,1,1
data 0,0,1,1,0,0,0
data 0,1,1,0,0,0,0
rem Cruiser (9x7)
data 9,7
data 0,0,1,1,1,0,0,0,0
data 0,1,1,1,0,0,0,0,0
data 1,1,1,1,1,1,0,0,0
data 0,1,1,1,1,1,1,1,1
data 1,1,1,1,1,1,0,0,0
data 0,1,1,1,0,0,0,0,0
data 0,0,1,1,1,0,0,0,0
rem Battleship (23x7)
data 23,7
data 0,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0
data 0,1,1,0,1,1,1,1,1,1,0,0,1,1,0,1,0,0,1,1,1,0,0
data 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0
data 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
data 0,1,1,0,1,1,1,1,1,1,0,0,1,1,0,1,0,0,1,1,1,0,0
data 0,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0
rem Colonizer (22x9)
data 22,11
data 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
data 0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0
data 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0
data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
data 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
data 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0
data 0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0
data 0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
I quite like the battleship but it is a strange style, I wanted to make it look like it had guns coming out of everywhere.