File :: http://www.coreillusions.co.uk/games/antbot/antbot.rar
The file has all the media needed.
This is a wee thing I did months ago and just found it again, While playing with it today and adding a few things to it I found it doing strange things, and I am sure its my dodgy maths, maths isn't my strong point and being dyslexic I find it hard to track down maths problems.
So, here is the full source, and media.
What should be happening, is that each queen spawns some workers, they then go and gather some food, once the queen has enough food she either spawns another worker or a soldier antbot.
Its something with the angles cos if a target moves to the left of the ant targetting it, it gets all confused, or sometimes the ants just go in circles for no clear reason. lol very strange.
Anyway, the soldier ants, pick a target, and hunt it down, when in range they damage it then return to their queen.
Have a look, and thanks in advance for any help, I hope its something really simple, but given the age of this code and how messy it is, I fear it may need a full rewrite.
The file has all the media needed.
This is a wee thing I did months ago and just found it again, While playing with it today and adding a few things to it I found it doing strange things, and I am sure its my dodgy maths, maths isn't my strong point and being dyslexic I find it hard to track down maths problems.
So, here is the full source, and media.
What should be happening, is that each queen spawns some workers, they then go and gather some food, once the queen has enough food she either spawns another worker or a soldier antbot.
Its something with the angles cos if a target moves to the left of the ant targetting it, it gets all confused, or sometimes the ants just go in circles for no clear reason. lol very strange.
Anyway, the soldier ants, pick a target, and hunt it down, when in range they damage it then return to their queen.
Have a look, and thanks in advance for any help, I hope its something really simple, but given the age of this code and how messy it is, I fear it may need a full rewrite.
Rem Ant bot . End Rem Strict; Rem ****************************************************************************************************** ****************************************************************************************************** Initial Graphics and Code Setup ****************************************************************************************************** ****************************************************************************************************** End Rem 'SetGraphicsDriver GLMax2DDriver() SetGraphicsDriver D3D7Max2DDriver() Const ScrWidth : Int = 1024; Const ScrHeight: Int = 768; Graphics ScrWidth,ScrHeight,0,75; 'Global Variable used for controling the AI timer. Global AIInt : Int; AIInt = 100 Global rows : Int = 11; Global colums : Int = 11; Global rowWidth : Int = scrheight / rows; Global columHeight : Int = scrwidth / colums; Global Lfoodlist : TList [rows,colums]; Global tempr : Int; Global tempg : Int; Global tempb : Int; tempr = 200 tempg = 20 tempb = 20 Global gx,gy : Int 'this is a temp var to change the colors of the grid squares that were checking 'this should only be showing on 1 bot, and it will be set.. 'HideMouse; AutoImageFlags MASKEDIMAGE|FILTEREDIMAGE|MIPMAPPEDIMAGE; SetMaskColor 255,0,255; AutoMidHandle True; SetBlend alphablend; SeedRnd Rand(MilliSecs()); Rem ****************************************************************************************************** ****************************************************************************************************** Loading Media Files. ****************************************************************************************************** ****************************************************************************************************** End Rem 'preload some images. Global red_Worker_img :Timage=LoadImage("img/red_worker.bmp",MASKEDIMAGE) Global red_queen_img :Timage=LoadImage("img/red_queen.bmp",MASKEDIMAGE) Global red_soldier_img :Timage=LoadImage("img/red_soldier.bmp",MASKEDIMAGE) Global yellow_Worker_img :Timage=LoadImage("img/yellow_worker.bmp",MASKEDIMAGE) Global yellow_queen_img :Timage=LoadImage("img/yellow_queen.bmp",MASKEDIMAGE) Global yellow_soldier_img :Timage=LoadImage("img/yellow_soldier.bmp",MASKEDIMAGE) Global green_Worker_img :Timage=LoadImage("img/green_worker.bmp",MASKEDIMAGE) Global green_queen_img :Timage=LoadImage("img/green_queen.bmp",MASKEDIMAGE) Global green_soldier_img :Timage=LoadImage("img/green_soldier.bmp",MASKEDIMAGE) Global blue_Worker_img :Timage=LoadImage("img/blue_worker.bmp",MASKEDIMAGE) Global blue_queen_img :Timage=LoadImage("img/blue_queen.bmp",MASKEDIMAGE) Global blue_soldier_img :Timage=LoadImage("img/blue_soldier.bmp",MASKEDIMAGE) Global food_img :Timage=LoadImage("img/leaf.bmp",MASKEDIMAGE) Global viewrange_img :Timage=LoadImage("img/viewrange.bmp",MASKEDIMAGE) Global viewrange_seen_img :Timage=LoadImage("img/viewrange_seen.bmp",MASKEDIMAGE) Rem ****************************************************************************************************** ****************************************************************************************************** Initialize variables and set default values. ****************************************************************************************************** ****************************************************************************************************** End Rem Const Explore : Int = 1; Const ReturntoQueen : Int = 2; Const Flee : Int = 3; Const Dead : Int = 4; Const Sleep : Int = 5; Const Fighting : Int = 6; Const Gathering : Int = 7; Const held : Int = 8; Const mission : Int = 9; Const food : Int =10; Const drop : Int =11; Const still : Int =12; Const lay : Int =13; Const Hunting : Int =14; 'Ant Types Const Worker : Int =14; Const Soldier : Int =15; Const Queen : Int =16; 'Ant Colonies Const red : Int =17; Const blue : Int =18; Const green : Int =19; Const yellow : Int =20; 'AntQueens Global redQueen : Tant; Global greenQueen : Tant; Global blueQueen : Tant; Global yellowQueen : Tant; Global queenant : Tant; Global FoodCounter : Int; Global RedWorkerCounter : Int; Global greenWorkerCounter : Int; Global blueWorkerCounter : Int; Global yellowWorkerCounter : Int ; Global EggCounter : Int = 3; Global old_ms : Int = MilliSecs(); Global FPS : Int; Global renders : Int; Rem ****************************************************************************************************** ****************************************************************************************************** Object Lists and Objects Structures.. ****************************************************************************************************** ****************************************************************************************************** End Rem 'Item Lists. Global Tantlist :TList = CreateList(); Global Tfoodlist :TList = CreateList(); Global Ants : Tant; Global Foods : Tfood; Rem ****************************************************************************************************** ****************************************************************************************************** The Ant Object.. ****************************************************************************************************** ****************************************************************************************************** End Rem Type Tant Field workers : Int ; Field soldiers : Int ; Field seen : Int; Field x : Float; Field y : Float; Field xVel : Float; Field yVel : Float; Field cAngle : Float; Field tAngle : Float; Field nSpeed : Float; Field fSpeed : Float; Field eating : Int; Field health : Int; Field aiTime : Int; Field aiInterval : Int; Field image : Timage; Field turnrate : Float; Field State : Int; Field foodTarget : Tfood; Field antTarget : Tant; Field antType : Int; Field antColor : Int; Field reportInTime : Int; Field reportInInterval : Int; 'temp var's Field marked : Int; Field gridx,gridy : Int; Rem ******************************* ******************************* Draw Method ******************************* ******************************* End Rem Method Draw() SetRotation 180+cAngle; 'DrawImage viewrange_img,x,y DrawImage image,x,y; SetRotation 0; If self.foodtarget <> Null Then DrawLine self.x , self.y , self.foodtarget.x , foodtarget.y If self.anttarget<>Null Then DrawLine self.x,self.y,self.anttarget.x,anttarget.y If Self.antType = Queen 'DrawText "eaten:"+self.eating,self.x,self.y-20 DrawText "State:"+self.state,self.x,self.y+5 Else DrawText "State:"+self.state,self.x,self.y+5 'DrawText "range:"+self.reportInInterval,self.x,self.y+5 'DrawText "RTQ:"+(MilliSecs()-self.reportInTime),self.x,self.y+20 End If DrawText "Life :"+self.health,self.x,self.y-20 'DrawText "cA:"+Abs(cAngle),x,y-20 'DrawText "tA:"+Abs(tAngle),x,y+20 End Method Rem ******************************* ******************************* Update Method ******************************* ******************************* End Rem Method Update() 'DebugStop 'Check Queens Food Stats. Local oldx : Float Local oldy : Float oldx=self.x oldy=self.y gridx=Abs(x/columHeight) gridy=Abs(y/rowWidth) If marked=1 gx=gridx gy=gridy End If If self.antType=queen Select self.antcolor Case red If redQueen.eating=>EggCounter redQueen.state=lay; End If Case blue If blueQueen.eating=>EggCounter blueQueen.state=lay; End If Case green If greenQueen.eating=>EggCounter greenQueen.state=lay; End If Case yellow If yellowQueen.eating=>EggCounter yellowQueen.state=lay; End If End Select End If Select Self.state Case Explore '***** ' All code in here handles the ant when its in gathering mode. ' Explorers will hunt for food piles, and then head to the queen dropping ' cent markers. '***** self.x=self.x+self.xVel*self.nSpeed; self.y=self.y+self.yVel*self.nSpeed; Local leftRange : Float; Local rightRange : Float; leftRange=cAngle-40; rightRange=cAngle+40; If MilliSecs()-self.aiTime>self.aiInterval tAngle=Rand(leftRange,rightRange) self.aiTime=MilliSecs() End If Case Gathering '***** ' All code in here handles the ant when its in gathering mode. '***** self.x=self.x+self.xVel*self.nSpeed; self.y=self.y+self.yVel*self.nSpeed; If self.foodTarget=Null 'Oh no I cant see any food. 'lets move about to find some. Local leftRange : Float; Local rightRange : Float; leftRange=cAngle-40; rightRange=cAngle+40; If MilliSecs()-self.aiTime>self.aiInterval tAngle=Rand(leftRange,rightRange) self.aiTime=MilliSecs() End If 'so now lets look for some food. 'Look for food. For foods=EachIn Tfoodlist Local range:Int = distanceTo(foods.x,foods.y,x,y) Select self.anttype Case worker If range<100 And foods.state<>held And self.foodTarget=Null And foods.seen=0 'Woohooo We can see some food an I am now targeting it foods.seen=1 self.reportInTime=MilliSecs() self.foodTarget=foods Local mx : Float; Local my : Float ; mx=self.x-self.foodTarget.x; my=self.y-self.foodTarget.y; self.tAngle=360-ATan2(mx,my) self.tAngle = Abs(self.tAngle) End If Case queen If range<200 And foods.state<>held And self.foodTarget=Null And foods.seen=0 'Woohooo We can see some food an I am now targeting it foods.seen=1 self.reportInTime=MilliSecs() self.foodTarget=foods Local mx : Float; Local my : Float ; mx=self.x-self.foodTarget.x; my=self.y-self.foodTarget.y; self.tAngle=360-ATan2(mx,my) self.tAngle = Abs(self.tAngle) End If End Select Next Else 'OK so I have a target, now what Local rangep:Int = distanceTo(self.foodTarget.x,self.foodTarget.y,x,y) 'lets chack if were close enough to pick it up. If rangep>100 Then self.foodtarget.seen=0 self.foodtarget=Null End If If rangep<15 'if I am in range, the food isnt being held, I am gathering, and im targeting it. self.foodTarget.holder=Self self.foodTarget.state=held self.state=returntoqueen Select self.antcolor Case red Local mx : Float; Local my : Float; mx=self.x-redqueen.x; my=self.y-redqueen.y; Case blue Local mx : Float; Local my : Float; mx=self.x-bluequeen.x; my=self.y-bluequeen.y; Case yellow Local mx : Float; Local my : Float; mx=self.x-yellowqueen.x; my=self.y-yellowqueen.y; Case green Local mx : Float; Local my : Float; mx=self.x-greenqueen.x; my=self.y-greenqueen.y; End Select 'If MilliSecs()-self.aiTime>self.aiInterval Local mx : Float; Local my : Float; self.tAngle=360-ATan2(mx,my) self.tAngle = Abs(self.tAngle) self.aiTime=MilliSecs() 'End If End If End If Case Hunting '***** ' All code in here handles the ant when its in gathering mode. '***** self.x=self.x+self.xVel*self.nSpeed; self.y=self.y+self.yVel*self.nSpeed; If self.antTarget=Null 'Oh no I cant see any food. 'lets move about to find some. Local leftRange : Float; Local rightRange : Float; leftRange=cAngle-40; rightRange=cAngle+40; If MilliSecs()-self.aiTime>self.aiInterval tAngle=Rand(leftRange,rightRange) self.aiTime=MilliSecs() End If 'so now lets look for some ant. 'Look for food. For ants=EachIn Tantlist Local range:Int = distanceTo(ants.x,ants.y,x,y) If range<200 And self.antTarget=Null And self.antcolor<>ants.antcolor 'And ants.seen=0 'Woohooo We can see some ant an I am now targeting it ants.seen=1 self.reportInTime=MilliSecs() self.antTarget=ants Local mx : Float; Local my : Float ; mx=self.x-self.antTarget.x; my=self.y-self.antTarget.y; self.tAngle=360-ATan2(mx,my) self.tAngle = Abs(self.tAngle) End If Next Else 'get to it and kill it dead. Local mx : Float; Local my : Float ; Local cx : Float ; Local cy : Float ; mx=self.x-self.antTarget.x; my=self.y-self.antTarget.y; cx = self.x cy = self.y self.tAngle=360-ATan2(mx,my) self.tAngle = Abs(self.tAngle) Local range:Int = distanceTo(self.anttarget.x , self.anttarget.y , self.x , self.y) 'DebugLog range If range < 10 self.anttarget.health:- 20 self.state=returntoqueen End If End If Case returntoqueen 'drop any ant targets if your rtq self.anttarget=Null '***** ' All code in here handles the ant when its in gathering mode. '***** self.x=self.x+self.xVel*self.nSpeed; self.y=self.y+self.yVel*self.nSpeed; 'find queen and target her. 'For ants=EachIn Tantlist 'If ants.species=queen Select self.antcolor Case red queenant=RedQueen; Case blue queenant=BlueQueen; Case green queenant=greenQueen; Case yellow queenant=yellowQueen; End Select Local mx : Float; Local my : Float; mx=self.x-Queenant.x; my=self.y-Queenant.y; If MilliSecs()-self.aiTime>self.aiInterval self.tAngle=360-ATan2(mx,my) self.tAngle = Abs(self.tAngle) self.aiTime=MilliSecs() End If 'Drop of food. if holding any If self.foodTarget<>Null Local range:Float = distanceTo(Queenant.x,Queenant.y,x,y) If range<20 And self.state<>gathering self.foodTarget.state=food If self.foodtarget.yield=>1 Then QueenAnt.eating=queenAnt.eating+1 Self.foodTarget.yield=Self.foodTarget.yield-1 Select self.anttype Case worker self.state = gathering Case soldier self.state = hunting End Select self.reportInInterval=self.reportInInterval+500 self.reportInTime=MilliSecs() If self.reportInInterval>30000 Then self.reportInInterval=30000 self.foodTarget=Null End If Else Local range:Float = distanceTo(Queenant.x,Queenant.y,x,y) If range<20 And self.state<>gathering self.reportInInterval=self.reportInInterval+500 self.reportInTime=MilliSecs() If self.reportInInterval>30000 Then self.reportInInterval=30000 Select self.anttype Case worker self.state = gathering Case soldier self.state = hunting End Select End If End If 'End If 'Next Case lay 'DebugStop '***** ' Its a boy, time to hatch out a new ant. '***** self.x=self.x+self.xVel*self.nSpeed; self.y=self.y+self.yVel*self.nSpeed; ' why is this set out by colour ? what was I planning to do with this when It could be done in 2 or 3 lines. Select self.antcolor Case red If self.workers<4 createAnts(self.x , self.y , Worker , self.antColor , gathering , 1) ; self.workers:+1 Else If self.soldiers<3 createAnts(self.x , self.y , Soldier , self.antColor , Hunting , 1) ; self.soldiers:+1 End If End If Case blue If self.workers<4 createAnts(self.x , self.y , Worker , self.antColor , gathering , 1) ; self.workers:+1 Else If self.soldiers<3 createAnts(self.x , self.y , Soldier , self.antColor , Hunting , 1) ; self.soldiers:+1 End If End If Case green If self.workers<4 createAnts(self.x , self.y , Worker , self.antColor , gathering , 1) ; self.workers:+1 Else If self.soldiers<3 createAnts(self.x , self.y , Soldier , self.antColor , Hunting , 1) ; self.soldiers:+1 End If End If Case yellow If self.workers<4 createAnts(self.x , self.y , Worker , self.antColor , gathering , 1) ; self.workers:+1 Else If self.soldiers<3 createAnts(self.x , self.y , Soldier , self.antColor , Hunting , 1) ; self.soldiers:+1 End If End If End Select self.state = gathering Default End Select If self.x<=10 Or self.x=>ScrWidth-10 Or self.y=<10 Or self.y=>ScrHeight-10 'And self.foodtarget=Null self.x=oldx; self.y=oldy; self.state=returntoqueen End If TurnAnt(); updateVel(); wrapAngles(); End Method Rem ******************************* ******************************* Misc Methods ******************************* ******************************* End Rem Method WrapAngles(); If self.tAngle>360 Then self.tAngle=self.tAngle-360 If self.tAngle<1 Then self.tAngle=self.tAngle+360 End Method Method updateVel() xVel=Sin(180-cAngle); yVel=Cos(180+cAngle); Select self.antType Case red If Self=redQueen Select redQueen.state Case still self.xVel=0 self.yVel=0 Case lay xVel=Sin(180-cAngle); yVel=Cos(180+cAngle); Default End Select End If Case green Case blue Case yellow End Select End Method; Method turnAnt() If cAngle < 1 cAngle = 180+(180 - Abs(cAngle)) End If If tAngle < 1 tAngle = 180+(180 - Abs(tAngle)) EndIf If tAngle > cAngle And tAngle > 0 Then cAngle = cAngle + turnrate If tAngle > cAngle And tAngle < 1 Then cAngle = cAngle - turnrate If tAngle < cAngle And tAngle > 0 Then cAngle = cAngle - turnrate If tAngle < cAngle And tAngle < 1 Then cAngle = cAngle + turnrate If cAngle> 360 Then cAngle = 1 If cAngle< 1 Then cAngle = 360 End Method Rem ******************************* ******************************* Initialize function for ants. ******************************* ******************************* End Rem Function SetupAnt:Tant(xx:Float ,yy :Float,this:Tant ,antType :Int,cState :Int,color : Int) this.seen=0; this.x=xx; this.y=yy; this.cAngle=Rand(1,259); this.health=100; this.aiTime=MilliSecs(); this.aiInterval=AIInt; this.reportInTime=MilliSecs(); this.reportInInterval=30000; this.state=cState; this.antType=antType this.xVel=Sin(180-this.cAngle); this.yVel=Cos(180+this.cAngle); this.eating=0; this.foodTarget=Null; this.antTarget=Null; this.antColor=color If antType=Worker Select color Case red this.image=red_Worker_img; Case green this.image=green_Worker_img; Case yellow this.image=yellow_Worker_img; Case blue this.image=blue_Worker_img; End Select this.nspeed=1; this.fspeed=2; this.Turnrate=5'2.5; End If If antType=Queen Select color Case red this.image=red_Queen_img; Case green this.image=green_Queen_img; Case yellow this.image=yellow_Queen_img; Case blue this.image=blue_Queen_img; End Select this.nspeed=0; this.fspeed=1; this.Turnrate=4; End If If antType=Soldier Select color Case red this.image=red_Soldier_img; Case green this.image=green_Soldier_img; Case yellow this.image=yellow_Soldier_img; Case blue this.image=blue_Soldier_img; End Select this.nspeed=2; this.fspeed=3; this.Turnrate=4; End If End Function Method New(); ListAddLast Tantlist,Self; End Method End Type Rem ****************************************************************************************************** ****************************************************************************************************** The Food Object ****************************************************************************************************** ****************************************************************************************************** End Rem Type Tfood Field x : Float; Field y : Float; Field image : Timage; Field Yield : Int; Field state : Int; Field holder : Tant; Field seen : Int; Rem ******************************* ******************************* Draw Method ******************************* ******************************* End Rem Method Draw() DrawImage image,x,y End Method Rem ******************************* ******************************* Update Method ******************************* ******************************* End Rem Method Update() Select State Case held x=holder.x y=holder.y Default End Select If yield=<0 ListRemove Tfoodlist,Self; foodCounter:-1; If foodCounter<50 CreateFoods(still,1) End If End If End Method Rem ******************************* ******************************* New Method ******************************* ******************************* End Rem Method New() yield=1; image=food_img; state=0; seen=0; holder=Null; ListAddLast Tfoodlist,Self; End Method End Type Rem ****************************************************************************************************** ****************************************************************************************************** Initialize some objects. ****************************************************************************************************** ****************************************************************************************************** End Rem Global pos_offset : Int = 150 CreateAnts(pos_offset,pos_offset,queen,red,gathering,1); CreateAnts(pos_offset,scrheight-pos_offset,queen,blue,gathering,1); CreateAnts(scrWidth-pos_offset,pos_offset,queen,green,gathering,1); CreateAnts(scrWidth-pos_offset,scrheight-pos_offset,queen,yellow,gathering,1); CreateFoods(still,30) Rem ****************************************************************************************************** ****************************************************************************************************** Main Game Loop. ****************************************************************************************************** ****************************************************************************************************** End Rem While Not KeyHit(KEY_ESCAPE) Cls Update() Render() Flip; Wend EndGraphics End Rem ****************************************************************************************************** ****************************************************************************************************** Game Funtions outwith any object. ****************************************************************************************************** ****************************************************************************************************** End Rem Function Update() ' calculate fps renders=renders+1 If MilliSecs()-old_ms>=1000 old_ms=MilliSecs() fps=renders renders=0 EndIf For ants=EachIn Tantlist ants.Update() Next For foods=EachIn Tfoodlist foods.update() Next End Function Function Render() Local r : Int; Local c : Int; Rem For r=0 To rows For c=0 To colums SetColor 255,255,255 DrawRect c*columHeight,r*rowWidth,columHeight,rowWidth SetColor 0,50,0 DrawRect c*columHeight+1,r*rowWidth+1,columHeight-1,rowWidth-1 SetColor 255,255,255 DrawText "["+r+":"+c+"]",c*columHeight,r*rowWidth Next Next End Rem For ants=EachIn Tantlist ants.Draw() Next For foods=EachIn Tfoodlist foods.draw() Next SetColor 0,0,0 DrawRect 0,0,50,20 SetColor 255,255,255 DrawText fps,1,1 End Function Function CreateFoods(state : Int ,count: Int) For Local x:Int = 1 To count Local xx : Int; Local yy : Int; xx=Rand(200,scrWidth-200) yy=Rand(10,scrHeight-10) Foods = New Tfood foods.state = state foods.x=xx foods.y=yy FoodCounter:+1 Next End Function Function CreateAnts(xx : Float , yy : Float, antType : Int,color : Int,state : Int,count: Int,temp:Int =0) Ants:Tant = New Tant Ants.setupAnt(xx,yy,ants,antType,state,color); If temp>0 ants.marked = 1; End If If anttype = Queen Select color Case red redQueen:Tant = Ants redQueen.eating=EggCounter*3; Case blue blueQueen:Tant = Ants blueQueen.eating=EggCounter*3; Case green greenQueen:Tant = Ants greenQueen.eating=EggCounter*3; Case yellow yellowQueen:Tant = Ants yellowQueen.eating=EggCounter*3; End Select Else Select color Case red redQueen.eating=redQueen.eating-EggCounter; Case blue blueQueen.eating=blueQueen.eating-EggCounter; Case green greenQueen.eating=greenQueen.eating-EggCounter; Case yellow yellowQueen.eating=yellowQueen.eating-EggCounter; End Select End If End Function Function distanceTo(x1 : Float,y1 : Float,x2 : Float,y2:Float) Local l1:Float = Abs(x1-x2) Local l2:Float = Abs(y1-y2) Local rtf : Int; rtf=Sqr((l1*l1)+(l2*l2)); Return rtf; End Function Function AngleTo(x1 : Float,y1 : Float,x2 : Float,y2:Float) Local mx : Float; Local my : Float; Local ang : Float; mx=x1-x2; my=y1-y2; ang = 360-ATan2(mx,my) ang = Abs(Ang) Return ang End Function