I am making a turn based strategy game at the moment and i think its not too bad so far. However im completely stuck when it comes to AI. I don't really know where to start. If someone could help me write some simple AI that could handle things like building units, moving attacking etc. it would be a real help. I have attached any models that you might need to run the game and the code is here:
rem setup global collision
set global collision on
rem load models
load object "cursor.x",81
scale object 81,25,25,25
set object collision to boxes 81
color object 81,rgb(0,255,0)
load object "arrow.x",83
hide object 83
load object "movering.x",82
hide object 82
set object collision to spheres 82
rem create plains to use as health bars
make object box 84,15,3,1
color object 84,rgb(0,255,255)
hide object 84
make object box 85,15,3,1
color object 85,rgb(0,255,255)
hide object 85
rem make matrix
load image "mossy03.bmp",1
make matrix 1,1000,1000,25,25
prepare matrix texture 1,1,1,1
rem make arrays to handle units
dim unitx#(40)
dim unitz#(40)
dim unittype(40)
dim unithealth#(40)
dim unitangle#(40)
dim maxhealth#(5)
rem make arrays to handle enemy units
dim eunitx#(40)
dim eunitz#(40)
dim eunittype(40)
dim eunithealth#(40)
dim eunitangle#(40)
rem create starting variables
cx#=50
cz#=50
ps#=25
pxmovemax#=180
pxmovemin#=-100
pzmovemax#=170
pzmovemin#=-80
speed#=5
funds=100000
moves=10
attacks=5
opt1$="build"
opt2$="move options"
opt3$="game options"
maxhealth#(1)=100
maxhealth#(2)=150
maxhealth#(3)=100
maxhealth#(4)=200
maxhealth#(5)=300
rem create all units and collision boxes for units
for unit=1 to 80
make object cube unit,10
hide object unit
if unit > 40
color object unit,rgb(255,0,0)
else
color object unit,rgb(0,0,255)
endif
set object collision to polygons unit
next unit
rem show single unit
unittype(1)=1
unithealth#(1)=maxhealth#(unittype(1))
unitx#(1)=50
unitz#(1)=50
inc unitsactive
show object 1
unittype(2)=1
unithealth#(2)=maxhealth#(unittype(2))
unitx#(2)=150
unitz#(2)=150
inc unitsactive
show object 2
rem show enemy unit
eunittype(1)=1
eunithealth#(1)=100
eunitx#(1)=500
eunitz#(1)=500
position object 41,eunitx#(1),0,eunitz#(1)
inc eunitsactive
show object 41
rem find save game names
if file exist("mainsave.sav")=1
open to read 1,"mainsave.sav"
read string 1,save1$
read string 1,save2$
read string 1,save3$
read string 1,save4$
read string 1,save5$
close file 1
endif
rem ================================================
rem make main game loop
sync on
hide mouse
do
mainloop:
rem go to unit update subroutine
gosub updateunits
rem go to position camera subroutine
gosub updatecamera
rem go to pointer update subroutine
gosub updatepointer
rem go to selection subroutine
gosub select
rem go to movement subroutine
gosub move
rem go to unit creation subroutine
gosub build
rem go to move options menu subroutine
gosub moveopt
rem game options subroutine
gosub gameopt
rem go to HUD subroutine
gosub HUD
rem debug mode
gosub debug
rem end main loop
sync
loop
rem ================================================
rem ------------------------------------------------
rem unit update subroutine
updateunits:
rem update position of units
for unit=1 to 40
if unithealth#(unit)>0
position object unit,unitx#(unit),0,unitz#(unit)
else
hide object unit
endif
next unit
for eunit=1 to 40
if eunithealth#(eunit)>0
position object eunit+40,eunitx#(eunit),0,eunitz#(eunit)
else
hide object eunit+40
endif
next unit
rem update position of health bars
if unitselected > 0
position object 84,unitx#(unitselected),5,unitz#(unitselected)+10
scale object 84,(unithealth#(unitselected)/maxhealth#(unittype(unitselected)))*100,100,100
endif
if enemyattacked>0
position object 85,eunitx#(enemyattacked),5,eunitz#(enemyattacked)+10
scale object 85,(eunithealth#(enemyattacked)/maxhealth#(eunittype(enemyattacked)))*100,100,100
show object 85
else
hide object 85
endif
rem return to main loop
return
rem ------------------------------------------------
rem camera update subroutine
updatecamera:
rem move camera
if px#>pxmovemax#
inc cx#,10
inc pxmovemin#,10
inc pxmovemax#,10
inc px#,10
endif
if px#<pxmovemin#
dec cx#,10
dec pxmovemin#,10
dec pxmovemax#,10
dec px#,10
endif
if pz#>pzmovemax#
inc cz#,10
inc pzmovemin#,10
inc pzmovemax#,10
inc pz#,10
endif
if pz#<pzmovemin#
dec cz#,10
dec pzmovemin#,10
dec pzmovemax#,10
dec pz#,10
endif
rem update camera position
position camera cx#,250,cz#
point camera cx#,0,cz#
rem return to main loop
return
rem -------------------------------------------------
rem pointer update subroutine
updatepointer:
rem inc pointer position by mouse movement
px#=px#+mousemovex()
pz#=pz#-mousemovey()
rem position pointer at centre of movement area
if spacekey()=1 and unitselected>0 and move=0
unitmove=unitselected
movex#=unitx#(unitmove)
movez#=unitz#(unitmove)
move=1
endif
rem stop pointer going off screen
if px#>(pxmovemax#+60)
dec px#,mousemovex()
endif
if px#<(pxmovemin#-40)
dec px#,mousemovex()
endif
if pz#>(pzmovemax#+20)
inc pz#,mousemovey()
endif
if pz#<(pzmovemin#-10)
inc pz#,mousemovey()
endif
rem rotate and scale object
pa#=wrapvalue(pa#+2)
if scalestage=0
dec ps#,2
if ps#<15
scalestage=1
endif
else
inc ps#,2
if ps#>30
scalestage=0
endif
endif
rem position pointer at mouse coordinates
position object 81,px#,5,pz#
yrotate object 81,pa#
scale object 81,ps#,25,ps#
rem update colour
if move=1 and (sqrt((px#-movex#)^2+(pz#-movez#)^2))<150
if object collision(81,0)>40 and object collision(81,0)<=80
color object 81,rgb(255,0,0)
attackopt=1
else
color object 81,rgb(0,255,0)
attackopt=0
endif
else
if attackopt=1
color object 81,rgb(0,255,0)
attackopt=0
endif
endif
rem return to main loop
return
rem -----------------------------------------------------
rem selection subroutine
select:
rem unselection
if unitselected>0 and mouseclick()=1 and object collision(81,0)<>unitselected and travel=0
color object unitselected,rgb(0,0,255)
hide object 84
unitselected=0
endif
rem detect selection
if object collision(81,0)>0 and object collision(81,0)<=40 and mouseclick()=1
if unithealth#(object collision(81,0))>0
color object object collision(81,0),rgb(255,255,255)
unitselected=object collision(81,0)
position object 84,unitx#(unitselected),5,unitz#(unitselected)+10
show object 84
endif
endif
rem return to main loop
return
rem ------------------------------------------------------
rem movement subroutine
move:
rem detect transition into and out of movement mode
if unitmove<>unitselected and move=1
unitmove=unitselected
movex#=unitx#(unitmove)
movez#=unitz#(unitmove)
endif
if controlkey()=1 or unitselected=0
if moving=0
hide object 82
move=0
endif
endif
rem show area for movement
if move=1 and moves > 0
position object 82,movex#,10,movez#
scale object 82,300,30,300
show object 82
endif
rem movement
if travel=0 and move=1 and mouseclick()=2 and (sqrt((px#-movex#)^2+(pz#-movez#)^2))<150
if object collision(81,0)>40 and object collision(81,0)<=80
if timer()-timeb>=200 and attacks>0
goto attack
else
goto movefail
endif
endif
moving=1
destx#=px#
destz#=pz#
dist#=(sqrt((unitx#(unitmove)-px#)^2+(unitz#(unitmove)-pz#)^2))
scale object 83,100,100,dist#
position object 83,(destx#+unitx#(unitmove))/2,5,(destz#+unitz#(unitmove))/2
point object 83,unitx#(unitmove),5,unitz#(unitmove)
show object 83
endif
if moving=1 and returnkey()=1 and travel = 0
moves = moves - 1
oldx#=unitx#(unitmove)
oldz#=unitz#(unitmove)
oldunit=unitmove
undo=1
travel=1
point object unitmove,destx#,0,destz#
unitangle#(unitmove)=object angle y(unitmove)
endif
if travel=1
unitx#(unitmove)=newxvalue(unitx#(unitmove),unitangle#(unitmove),speed#)
unitz#(unitmove)=newzvalue(unitz#(unitmove),unitangle#(unitmove),speed#)
inc disttrav,speed#
if disttrav>=dist#
dist#=0
disttrav=0
speed#=5
point object unitmove,destx#,0,destz#
unitangle#(unitmove)=object angle y(unitmove)
travel=0
moving=0
movex#=unitx#(unitmove)
movez#=unitz#(unitmove)
endif
endif
movefail:
rem return to main loop
return
rem --------------------------------------------------------------
rem unit creation subroutine
build:
rem check for key press
key=scancode()
rem check for unit creation
if key>1 and key<7 and menu=1 and unitsactive<40 and timer()-timea>500
if key=2 and funds>=2000
goto buildsuccess
endif
if key=3 and funds>=3000
goto buildsuccess
endif
if key=4 and funds>=5000
goto buildsuccess
endif
if key=5 and funds>=7000
goto buildsuccess
endif
if key=6 and funds>=10000
goto buildsuccess
else
goto buildfail
endif
buildsuccess:
timea=timer()
gosub findinactive
if unitcreate>0
unittype(unitcreate)=key-1
unithealth#(unitcreate)=maxhealth#(unittype(unitcreate))
retryposition:
unitx#(unitcreate)=rnd(250)
unitz#(unitcreate)=rnd(250)
unitangle#(unitcreate)=rnd(360)
if key=2
dec funds,2000
endif
if key=3
dec funds,3000
endif
if key=4
dec funds,5000
endif
if key=5
scale object unitcreate,150,100,200
dec funds,7000
endif
if key=6
scale object unitcreate,200,100,300
dec funds,10000
endif
position object unitcreate,unitx#(unitcreate),0,unitz#(unitcreate)
rotate object unitcreate,0,unitangle#(unitcreate),0
if object collision(unitcreate,0)>0 and object collision(unitcreate,0)<41
goto retryposition
endif
show object unitcreate
endif
endif
buildfail:
rem return to main loop
return
rem find an inactive unit
findinactive:
for unit=1 to 40
if unithealth#(unit)=0
unitcreate=unit
goto endofsub
endif
next unit
unitcreate=0
endofsub:
return
rem ------------------------------------------------------
rem move options menu subroutine
moveopt:
if menu = 2
if keystate(2) = 1 and timer() - timea >= 200
moves = 10
attacks = 5
enemyattacked=0
hide object 83
if unitselected>0
color object unitselected,rgb(255,255,255)
unitselected = 0
endif
timea = timer()
endif
if keystate(3) = 1 and timer() - timea >= 200 and moves > 0
moves = moves - 1
attacks = attacks + 1
dec funds,5000
timea = timer()
endif
if keystate(4) = 1 and timer() - timea >= 200 and attacks > 0
moves = moves + 1
attacks = attacks - 1
dec funds,5000
timea = timer()
endif
if keystate(5)=1 and timer()-timea>=200 and undo=1
undo=0
dec funds,10000
position object oldunit,oldx#,0,oldz#
unitx#(oldunit)=oldx#
unitz#(oldunit)=oldz#
movex#=unitx#(oldunit)
movez#=unitz#(oldunit)
inc moves
hide object 83
endif
endif
return
rem ------------------------------------------------------
rem game options menu
gameopt:
if menu=3 and timer()-timea>=200
if keystate(2)=1
gosub save
endif
if keystate(4)=1
end
endif
endif
return
rem ------------------------------------------------------
rem HUD subroutine
HUD:
rem output funds total onto screen
set cursor 10,0
print "funds > £",funds
rem output total moves left
set cursor 10,15
print "moves > ",moves
rem output total attacks left
set cursor 10,30
print "attacks > ",attacks
rem options menu
if shiftkey()=1
textx=0
opt1$="build"
opt2$="move options"
opt3$="game options"
opt4$=""
opt5$=""
menu=0
timea=timer()
endif
rem build menu
if keystate(2)=1 and menu=0
textx=0
opt1$="infantry - £2000"
opt2$="heavy infantry - £3000"
opt3$="sniper - £5000"
opt4$="light tank - £7000"
opt5$="heavy tank - £10000"
menu=1
timea=timer()
endif
rem move options menu
if keystate(3)=1 and menu=0
textx=0
opt1$="end turn"
opt2$="move --> attack - £5000"
opt3$="attack --> move - £5000"
opt4$="undo last - £10000"
opt5$=""
menu=2
timea=timer()
endif
rem game options menu
if keystate(4)=1 and menu=0
textx=0
opt1$="save"
opt2$="load"
opt3$="quit"
opt4$=""
opt5$=""
menu=3
timea=timer()
endif
rem allow user to scroll text if it goes off the screen
if text width(opt5$)+text width(opt4$)+text width(opt3$)+text width(opt2$)+text width(opt1$)+200+textx>screen width()
if rightkey()=1
dec textx,5
endif
endif
If textx<0 and leftkey()=1
inc textx,5
endif
rem show options on screen
set cursor textx,460
print "(1) ",opt1$
set cursor text width(opt1$)+40+textx,460
print "(2) ",opt2$
set cursor text width(opt2$)+text width(opt1$)+80+textx,460
print "(3) ",opt3$
set cursor text width(opt3$)+text width(opt2$)+text width(opt1$)+120+textx,460
print "(4) ",opt4$
set cursor text width(opt4$)+text width(opt3$)+text width(opt2$)+text width(opt1$)+160+textx,460
print "(5) ",opt5$
rem return to main loop
return
rem ------------------------------------------------------
rem debug mode
debug:
rem replenish funds (F.U.N.D.)
if keystate(22)=1 and keystate(32)=1 and keystate(33)=1 and keystate(49)=1
funds=99999999
endif
return
rem ------------------------------------------------------
rem attacking
attack:
attackopt=1
rem only attack if the player clicks on the enemy
if mouseclick()=2
rem calculate damage to do depending on unit type
rem infantry
if unittype(unitselected)=1
if eunittype(object collision(81,0)-40)<=3
damage=50
endif
if eunittype(object collision(81,0)-40)=4
damage=15
endif
if eunittype(object collision(81,0)-40)=5
damage=10
endif
endif
rem heavy infantry
if unittype(unitselected)=2
if eunittype(object collision(81,0)-40)<=3
damage=75
endif
if eunittype(object collision(81,0)-40)=4
damage=35
endif
if eunittype(object collision(81,0)-40)=5
damage=25
endif
endif
rem sniper
if unittype(unitselected)=3
if eunittype(object collision(81,0)-40)<=3
damage=150
endif
if eunittype(object collision(81,0)-40)=4
damage=10
endif
if eunittype(object collision(81,0)-40)=5
damage=5
endif
endif
rem light tank
if unittype(unitselected)=4
if eunittype(object collision(81,0)-40)<=3
damage=100
endif
if eunittype(object collision(81,0)-40)=4
damage=50
endif
if eunittype(object collision(81,0)-40)=5
damage=50
endif
endif
rem heavy tank
if unittype(unitselected)=1
if eunittype(object collision(81,0)-40)<=3
damage=50
endif
if eunittype(object collision(81,0)-40)=4
damage=100
endif
if eunittype(object collision(81,0)-40)=5
damage=150
endif
endif
rem do damage to enemy
eunithealth#(object collision(81,0)-40)=eunithealth#(object collision(81,0)-40)-damage
dec attacks
enemyattacked=object collision(81,0)-40
timeb=timer()
endif
goto mainloop:
rem ------------------------------------------------------
rem saving subroutine
save:
rem ask which slot player wants to save in
if menu=3 and keystate(2)=1
opt1$=save1$
opt2$=save2$
opt3$=save3$
opt4$=save4$
opt5$=save5$
menu=4
timea=timer()
endif
if menu=4
if keystate(2)=1
if asc(save1$)>0
if file exist(save1$+"real.sav")=1
delete file save1$+"real.sav"
endif
dim real#(3,40)
for value=1 to 40
real#(1,value)=unitx#(value)
next value
for value=1 to 40
real#(2,value)=unitz#(value)
next value
for value=1 to 40
real#(3,value)=unitangle#(value)
next value
save array save1$+"real.sav",real#(3,40)
if file exist(save1$+"integer.sav")
delete file save1$+"integer.sav"
endif
dim integer(3,40)
for value=1 to 40
integer(1,value)=unithealth#(value)
next value
for value=1 to 40
integer(2,value)=unittype(value)
next value
integer(3,1)=funds
integer(3,2)=moves
integer(3,3)=attacks
save array save1$+"integer.sav",integer(3,40)
else
input "what would you like to call the save game?",save1$
open to write 1,"mainsave"
write string 1,save1$
close file 1
dim real#(3,40)
for value=1 to 40
real#(1,value)=unitx#(value)
next value
for value=1 to 40
real#(2,value)=unitz#(value)
next value
for value=1 to 40
real#(3,value)=unitangle#(value)
next value
save array save1$+"real.sav",real#(3,40)
if file exist(save1$+"integer.sav")
delete file save1$+"integer.sav"
endif
dim integer(3,40)
for value=1 to 40
integer(1,value)=unithealth#(value)
next value
for value=1 to 40
integer(2,value)=unittype(value)
next value
integer(3,1)=funds
integer(3,2)=moves
integer(3,3)=attacks
save array save1$+"integer.sav",integer(3,40)
endif
endif
endif
rem return to main loop
return
rem ------------------------------------------------------
I know its kind of long, sorry.
Also if when you help me you could explain why your doing stuff so i learn and i can do it myself in the future.
(ps. i have DB classic 1.13)
Thankyou in advance