AI

Blitz3D Forums/Blitz3D Programming/AI

Hi, i'm pretty new at Ai programming so i was wondering if anyone could give me some nice tutorials or instructions on some basics

thnx

It depends on what the object thats is "AI-ed" is supposed to do. if its a baddie it needs to move in such a way as the type of baddie would move and so and so forth
without knowing what the object is its hard to help

for starters get to know entitydistance real well and linepick.

I've written a very competent AI for my game without ever seeking any information or reading a tutorial about creating one. It took a few days to come up with the idea and a lot days more to make it work, but it's not impossible.

The basic good idea is thinking in states. 'Finite state machine' as the academics call it. First think of values the AI should be gathering about it's surroundings and itself.
- My health is low
- Enemy present
- Multiple enemies present
- Enemy outnumbered
- I am outnumbered
- Route to enemy is blocked

Then according to these values, your AI should decide a state it is in.
- Agressive attack
- Defensive attack
- Flee
- Move to X
- Wait

Then according to the state, AI should prioritize whether to shoot or move or anything it could be doing.

Please keep in mind that although it makes AI coding easier to do 'AI cheating', it drives people crazy. So if possible, make your AI so that it doesn't have capabilities the human player doesn't have.

Also, you may want to look into path finding, to help your cpu characters find their way round the enviroment.

Yes, path finding is basically a chapter of its own. There are also lots of other issues, like AI teamwork. There are always ways to improve your AI, but there's rarely a need for best of the best solution. Just think what you need for your game.

There's also another approach to AI. An action score system. Define all the possibilities AI can do and give points to those actions with some predefined system. The action with most score is chosen. It requires some heavy testing in balancing the scoring system, but when it works, AI can be suprisingly human-like.

A couple of good posts there.

The best I can offer is, if you tell us what kind of game you're looking to make an AI for - it would be easier, to more correctly, guide you to the best solution, if we know what kind of game it's needed for.

wow, i go to bed and when i get up there are six posts!

anyway, Thnx for all the advice.the game i am trying to write is a FPS paintball game. The AI will be for the other members of the player's team and the members of the opposite team. The members of the player's team will need to be able to locate each of the other team members and then start shooting at them. The opposite team will have to do pretty much the same thing, only, against the player's team. all the AI controlled characters will need to find their way from bunker to bunker.

thnx in advance

Abstract overview:
Make a function called ProcessAI() or something and have it loop through each of the AI characters. For each character, evaluate what things are like currently (eg. use LinePick to "see" what is ahead of the character) and then have the character choose a reaction to the situation (eg. if they don't see anything, continue walking; if they see the player, shoot.)

i'm working on the ai in my game also.
here it is use it if yu want. its based on the "AIscore" idea.
Function getenemystate()
For e.enemy=Each enemy
 For c.char=Each char
  EntityPick (e\e,150)
  ;check disance
  e\score=100
  If EntityDistance(e\e,c\e)>50 
   e\score=e\score-50
  Else If EntityDistance(e\e,c\e)>30 
   e\score=e\score-30
  Else If EntityDistance(e\e,c\e)>20 
   e\score=e\score-20
  Else If EntityDistance(e\e,c\e)>10 
   e\score=e\score-10
  End If
  ;check health
  If e\hp<80 
   e\score=e\score-10
  Else If e\hp<60 
   e\score=e\score-20
  Else If e\hp<40 
   e\score=e\score-30
  Else If e\hp<20 
   e\score=e\score-40
  Else If e\hp<10 
   e\score=e\score-60
  End If
  ;check whats infront of it
  If PickedEntity=c\e 
   e\score=e\score+20
  Else If Not PickedEntity=c\e 
   e\score=e\score-10
  End If
  DebugLog "hp "+e\hp
  DebugLog "AIscore "+e\score
  ;"normalize" the score
  If e\score>100 
   e\score=100
  Else If e\score<0 
   e\score=0
 
  End If
 Next
Next
End Function



What is the point of the score?

to determin an action later on. in the updateenemy command i check the score and if it is <> a cetain value it will do something. the posted code was a example of sorts for a method posted ealier by jasu.

For a major speed boost, should this ..

For e.enemy=Each enemy
For c.char=Each char
EntityPick (e\e,150)

Not be this?

For e.enemy=Each enemy
EntityPick (e\e,150)
For c.char=Each char

Otherwise you are repeating the same pick for every instance of char unecessarily.

Stevie

yeah probably. :)

I don't know much of anything about AI programming, but I know the basic logic of it...I just need pathfinding GAH!!!

The purpose of using a score system is so you can evaluate the best possible decision, so you loop through all surrounding conditions, and score each condition. For example, If playerhealth > (npcHealth * 2) then choicescore = choicescore-50. This way, you can evaluate your choicescore at the end of processing the conditions, so you can say: if choicescore < 20 then runaway(). Using a system like this, you can make an AI usually choose the best action for the current decisions, and you could even make "personalities" using the score system, for example, for a cowardly npc this would be more realistic: if choicescore < 40 then runaway. Basically, higher choicescore would mean the conditions are leaning further toward the npc, and it stands a better chance if it were to fight than if it ran away. A choicescore system would work best when integrated with a finite logic system, so you can further enhance the personalities of different npc's, so as to extend the logic from numbers to numbers and if statements, for example:

if choicescore < 20 and surroundingallies < 1 then
runaway()
elseif choicescore < 20 and surroundingallies > 1 then
standandfight()
endif
;this would do something to the effect of, if conditions are bad and there are no allies around, run away, 
;if conditions are bad and there are allies around, stand and fight

hope that helped.

hi,

i've been trying some basics with AI but i ran into a problem which i am guessing is very simple, i just can't figure it out

here is my code:

Graphics3D 800,600,0,2
SetBuffer BackBuffer()
SeedRnd MilliSecs()

Global cam = CreateCamera()
	PositionEntity cam,0,30,0
	RotateEntity cam,90,0,0

	
lit = CreateLight()


pl = CreatePlane()
	PositionEntity pl,0,-1,0
	EntityColor pl,0,0,0
	wdStatic(pl)
	

;bullet type
Type bullet
	Field shape
End Type

;enemy type
Type enemy
	Field shape,sight,turn#,move#
	Field state
	Field health
End Type


;good guy type
Type good
	Field shape
End Type

;enemy states of being
Global roam = 1
Global chase = 2
Global attack = 3
Global dead = 4


;create enemies
For x = 0 To 4

	e.enemy = New enemy
		e\shape = CreateSphere(2)
		EntityColor e\shape,0,0,255
		PositionEntity e\shape,Rand(-15,15),0,Rand(-15,15)
		EntityType e\shape,1
		e\turn = 1
		e\state = roam
		e\move# = .1
		e\health = 10

		

		
Next

;create the good guy
For x = 0 To 0

	g.good = New good
		g\shape = CreateSphere(2)
		PositionEntity g\shape,Rand(-20,20),0,Rand(-20,20)
		EntityPickMode g\shape,2
		EntityType g\shape,2
		
Next


;COLLISIONS

;enemy to enemy
Collisions 1,1,1,2

;enemy to good guy
Collisions 1,2,1,2
;goodguy to enemy
Collisions 2,1,1,2

;bullet to enemy
Collisions 3,1,1,1
;enemy to bullet
Collisions 1,3,1,1

;bullet to goodguy
Collisions 3,2,1,1
;goodguy = bullet
Collisions 2,3,1,1


br = 0

While Not KeyHit(1)

;update the enemies and good guy
For g.good = Each good

;player controls
If KeyDown(203) TurnEntity g\shape,0,1,0
If KeyDown(205) TurnEntity g\shape,0,-1,0
If KeyDown(200) MoveEntity g\shape,0,0,.2
If KeyHit(57) CreateBullet(g\shape)

;variable to control the rate of bullets from enemies
br = br + 1

For e.enemy = Each enemy

	dist# = EntityDistance(e\shape,g\shape)

	;if state of enemy is chase, chase the player
	If e\state = chase

		PointEntity e\shape,g\shape
		MoveEntity e\shape,0,0,e\move#

	;if roam then move around
	ElseIf e\state = roam
	
		TurnEntity e\shape,0,e\turn,0
		MoveEntity e\shape,0,0,e\move#
		
	; if attack then shoot at enemy
	ElseIf e\state = attack
	
		PointEntity e\shape,g\shape
		
		If br > 10
		
			CreateBullet(e\shape)
		
			br = 0
			
		EndIf
		
	; if dead stop from turning and moving
	ElseIf e\state = dead
	
		e\move = 0
		e\turn = 0
		
	EndIf
	
	;set enemy states according to current state
		If e\state <> dead
	
			If (dist < 10 And dist > 5)
	
				e\state = chase
		
			ElseIf (dist < 5 And dist > 0)		
		
				e\state = attack
				
			ElseIf (dist > 10)
		
				e\state = roam
		
			EndIf
		
		EndIf

		;if enemy health is less than or equal to 0 kill it
		If e\health <= 0
		
			e\state = dead

		EndIf
		
	
	;keep enemy from going off screen
	If EntityX(e\shape) < -17 Or EntityX(e\shape) > 17 Or EntityZ(e\shape) < -17 Or EntityZ(e\shape) > 17
	
		TurnEntity e\shape,0,3,0
		
	EndIf
	
	
Next








Next



UpdateBullet()

UpdateWorld
RenderWorld




Flip


Wend



;creates a bullet(sphere)
Function CreateBullet(source)


b.bullet = New bullet

b\shape = CreateSphere(2)

	ScaleEntity b\shape,.3,.3,.3
	RotateEntity b\shape,EntityPitch(source),EntityYaw(source),EntityRoll(source)
	PositionEntity b\shape,EntityX(source),EntityY(source),EntityZ(source)
	EntityType b\shape,3

End Function

; the bullet forward and destroys it when neccessary
Function UpdateBullet()

	For b.bullet = Each bullet
	
		MoveEntity b\shape,0,0,1
	
		For e.enemy = Each enemy
	
		
		If EntityDistance(b\shape,cam) > 50
		
			FreeEntity b\shape
			Delete b
		
		
		; this is the problem area---------\/\/\/\/\/\/\/\/\/\/\/\/\/\/;i keep getting a MAV saying 'collsion index out of range'	 
		ElseIf CollisionEntity(  b\shape , CountCollisions( b\shape )  ) = e\shape
					
			e\health = e\health - 1
				
			FreeEntity b\shape
			Delete b
			
		ElseIf EntityCollided(b\shape,2)
		
			FreeEntity b\shape
			Delete b
			
		EndIf
		
		Next
				
	Next
	
End Function

























End


my problem is at CollisionEntity(b\shape,countcollisions(b\shape))

i get a MAV saying 'collision index out of range'

any suggestions?

change collisionentity to entitycollided(b\shape,3) this will work. if you stop this piece of code and look at the veriables it says the enemy and goodguy types are null but i can't find out why.

hi again i was trying to use jerome's code for the ai in my game cause my verson wasn't working very well in this context. i got everything setup and tryed running it and the ai won't update its self. it stays at a constant state and won't move to another one. also it won't delete the badie when its health gets to low even though it was working when i had my sytem in place.
; A 3rd person space shooter
; By R. Manwiller
; 
Const playr=1,enem=2,world=3,lazer=4
Type player
Field ent,piv,x,y,z,speed,apiv,fpiv1,fpiv2,missle,kills,hp,score
End Type
Type enemy
Field ent,x,y,z,apiv,speed,turn,missle,state,hp,firing
End Type
Type bullet
Field ent,x,y,z
End Type
Type particle
Field ent,x,y,z,life,tex
End Type
Global cam,roll#,pitch#,count1#,pnum=0,ret,frame#=0,firecounter=0
Global explosnd
;enemy states of being
Global roam = 1
Global chase = 2
Global attack = 3
Global dead = 4

mainmenu()
End

Function mainmenu()
Graphics 800,600,16,0
SetBuffer BackBuffer()
HidePointer
AutoMidHandle True
mainbg=LoadImage("media\mbg.bmp")
button1=LoadImage("media\button1.bmp")
button2=LoadImage("media\button2.bmp")
button3=LoadImage("media\button3.bmp")
mouseim=LoadImage("media\mouseim.bmp")
MaskImage mouseim,0,0,0
Repeat 
Cls
TileImage mainbg
DrawImage button1,400,300
DrawImage button2,400,400
DrawImage button3,730,562
DrawImage mouseim,MouseX()+6,MouseY()+12

If MouseHit (1)
If ImagesOverlap(mouseim,MouseX(),MouseY(),button1,400,300) 
startup()
End
Else If ImagesOverlap(mouseim,MouseX(),MouseY(),button2,400,400) 
config()
Else If ImagesOverlap(mouseim,MouseX(),MouseY(),button3,730,562) 
End
EndIf
EndIf 

Flip
Until KeyHit(1)
End Function

Function config()
Cls
gw=Input("what is your screen width? ")
gh=Input("what is your screen height? ")
cd=Input("what is your color depth? ")
fileout=WriteFile ("config.cfg")
WriteString (fileout,gw)
WriteString (fileout,gh)
WriteString (fileout,cd)
Print "press any key to continue"
WaitKey()
End Function

Function Startup()
filein=OpenFile("config.cfg")
If filein>0
gw=ReadString(filein)
gh=ReadString(filein)
cd=ReadString(filein)
Graphics3D gw,gh,cd,0
Else 
Graphics3D 800,600,16,0
End If
SetBuffer BackBuffer()
loadlevel1()
loadplayer()
loadenemy()
loadhud()
run()
End Function

Function loadlevel1()
Collisions playr,enem,2,2
Collisions lazer,enem,2,2
explosnd=Load3DSound("media\explosion.wav")
cam=CreateCamera()
m=CreateListener(cam,100)
CameraRange cam,.1,10000
PositionEntity cam,0,5,20
light=CreateLight()
;space
c=CreateSphere(32)
ScaleEntity c,-5000,-5000,-5000
EntityOrder c,1
t=LoadTexture("media\mbg.bmp")
ScaleTexture t,.1,.1
EntityTexture c,t
;planet
c=CreateSphere(32)
PositionEntity c,-2500,-1000,900
ScaleEntity c,600,600,600
t=LoadTexture("media\planettex.png")
EntityTexture c,t
;spacestations
For q=1 To 4
c=LoadMesh("media\solarsail.3ds")
ScaleEntity c,.04,.04,.04
PositionEntity c,Rnd(600),Rnd(600),Rnd(600)
Next
End Function

Function loadplayer()
p.player= New player
p\piv=CreatePivot()
p\ent=LoadMesh("media\fighter.3ds",p\piv)
p\fpiv1=CreatePivot(p\ent)
p\fpiv2=CreatePivot(p\ent)
p\apiv=CreatePivot(p\ent)
p\x=0
p\y=0
p\z=0
p\missle=10
p\kills=0
p\hp=100
p\score=0
p\speed=1
ScaleEntity p\ent,.06,.06,.06
RotateEntity p\ent,0,180,0
PositionEntity p\ent,p\x,p\y,p\z
PositionEntity p\fpiv1,160,-50,10
PositionEntity p\fpiv2,-160,-50,10
PositionEntity p\apiv,0,0,-100
c=CreateCube(p\apiv)
EntityType p\ent,playr
EntityParent cam,p\piv
End Function

Function loadenemy()
For q=1 To 50
e.enemy= New enemy
e\ent=LoadMesh("media\saucer.3ds")
e\x=Rnd(-1000,1000)
e\y=Rnd(-1000,1000)
e\z=Rnd(-1000,1000)
e\apiv=CreatePivot(e\ent)
e\missle=10
e\hp=100
e\state=1
e\speed=1.5
e\turn=1
PositionEntity e\apiv,0,5,50
PositionEntity e\ent,e\x,e\y,e\z
RotateEntity e\ent,Rnd(360),Rnd(360),Rnd(360)
EntityType e\ent,enem
EntityPickMode e\ent,2
Next
End Function

Function loadhud()
ret=LoadSprite("media\target.bmp",4,cam)
PositionEntity ret,0,0,20
ScaleSprite ret,.5,.5

End Function

Function run()
HidePointer
While Not KeyHit(1)
SeedRnd MilliSecs()+38.08659/6*4+8
updateplayer()
updatefire()
updateenemy()
updateexplosion()
 
UpdateWorld
RenderWorld
Text 0,0,+getfps()+" "
Flip
Wend
End Function

Function updateplayer()
For p.player=Each player
PositionEntity cam,0,5,-20
PositionEntity p\ent,p\x,p\y,p\z
If KeyDown(200) pitch#=pitch+.5
If KeyDown(208) pitch#=pitch-.5
If KeyDown(203) roll#=roll+.2
If KeyDown(205) roll#=roll-.2
If roll#>0 roll#=roll-.1
If roll#<0 roll#=roll+.1
If pitch#>0 pitch#=pitch-.1
If pitch#<0 pitch#=pitch+.1
If pitch#>1 pitch=1
If pitch#<-1 pitch=-1
If roll#>5 roll=5
If roll#<-5 roll=-5
TurnEntity p\piv,pitch,0,roll
If KeyHit(57) fire(1)
If KeyDown(54) p\speed=p\speed+3
MoveEntity p\piv,0,0,p\speed
p\speed=1
Next
End Function

Function updateenemy()
br=br+1
For e.enemy=Each enemy
DebugLog e\state
DebugLog e\hp
e\hp=e\hp-10
For p.player=Each player
dist# = EntityDistance(e\ent,p\ent)
	;set enemy states according to current state
		If e\state <> dead	
			If (dist < 200 And dist > 500)
				e\state = chase
			ElseIf (dist < 100 And dist > 200)		
				e\state = attack
			ElseIf (dist > 1000)
				e\state = roam
			EndIf
		EndIf
		;if state of enemy is chase, chase the player
	If e\state = chase
		PointEntity e\ent,p\ent
		MoveEntity e\ent,0,0,e\speed
	;if roam then move around
	ElseIf e\state = roam
	    e\turn=Rnd(-.1,.1)
		TurnEntity e\ent,0,e\turn,0
		MoveEntity e\ent,0,0,e\speed
	; if attack then shoot at enemy
	ElseIf e\state = attack
		PointEntity e\ent,p\ent
		If br > 10
			fire(2)
			br = 0
	ElseIf e\state=dead
		EndIf	
		;if enemy hp is less than or equal to 0 kill it
		If e\hp<=1
		 explosion()
	     FreeEntity e\ent
	     Delete e
		 e\state=dead
		EndIf
		TurnEntity e\ent,0,3,0
	EndIf
 Next
Next
End Function

Function fire(src)
If src=1
For p.player=Each player
  LinePick EntityX(p\piv),EntityY(p\piv),EntityZ(p\piv),0,0,-1000
  If PickedEntity>0
   PositionEntity p\apiv,PickedX(),PickedY(),PickedZ()
  Else 
   PositionEntity p\apiv,0,0,-100
   MoveEntity p\apiv,0,0,1000000
  End If
  pnum=1-pnum
  If pnum=1 
   q=p\fpiv1
  Else q=p\fpiv2
  End If
  b.bullet=New bullet
   b\ent=LoadSprite("media\laser1.bmp",4,q)
   b\x=0
   b\y=0
   b\z=0
  PointEntity b\ent,p\apiv
  EntityParent b\ent,0
  EntityType b\ent,lazer
Next
Else If src=2

For e.enemy=Each enemy
  If e\firing=1
  b.bullet=New bullet
  b\ent=LoadSprite("media\laser2.bmp",4,e\ent)
  b\x=0
   b\y=0
   b\z=0
  PointEntity b\ent,e\apiv
  EntityParent b\ent,0
  EntityType b\ent,lazer
 End If
Next
End If
End Function

Function updatefire()
For b.bullet=Each bullet
 MoveEntity b\ent,0,0,-8
 For e.enemy=Each enemy
  If EntityCollided (e\ent,lazer)
   FreeEntity b\ent
   Delete b
  End If 
 Next
Next
End Function

Function explosion()
For e.enemy=Each enemy
 If e\hp<1
  For q=1 To 10
   f.particle=New particle
   f\ent=CreateSprite(e\ent)
   f\x=0
   f\y=0
   f\z=0
   f\life=39
   f\tex=LoadAnimTexture("media\explosion.png",49,64,64,0,39)
   EntityTexture f\ent,f\tex,frame#
   ScaleSprite f\ent,50,50
   EntityParent f\ent,0
   EmitSound explosnd,f\ent
  Next
 EndIf
Next
End Function

Function updateexplosion()
For f.particle=Each particle
If f <>Null
frame=MilliSecs()/50 Mod 39
f\life=MilliSecs()/50 Mod 39
EntityTexture f\ent,f\tex,frame#
If f\life<5 FreeEntity f\ent:Delete f
Else Return
End If
Next
End Function

Global FPS, FPS_temp, FPS_time
Function GetFPS()
ctime = MilliSecs()
FPS_temp = FPS_temp + 1
If ctime - FPS_time > 500 Then
	FPS = FPS_temp * 2
	FPS_temp = 0
	FPS_time = ctime
EndIf
Return FPS
End Function


If (dist < 200 And dist > 500)
   e\State = chase
ElseIf (dist < 100 And dist > 200)		
  e\state = attack
ElseIf (dist > 1000)
 e\state = roam
EndIf


Unless the dist > 1000 no state change will happen. How can dist be < 200 and > 500 or < 100 and > 200 !!?

if dist > 1000
   e\State = roam
elseif dist < 100
   e\State = attack
elseif dist < 200
   e\State = chase
endif



Only problem with this is that if dist >=200 or <= 1000 nothing will happen. You may want to set the state to roam if dist >= 200.

Stevie

thank you very much it works great now just a little more and i'll release a demo.