As you could notice with AI behaviours, I like to keep things modular and hierarchical or in straight flow. I don't have now anything really high-level for AI (on second thought: some behaviour setups can make it work), but you can still divide AI logic into to separate layers. AI behaviour tree that manages behaviours and interior of every single behaviour.
I decided that I want something simple to write, read and run. Behaviours may run in parallel and I wanted to have system of messages (more on that later) and this can bring enough complexity into system, that having some strange setup of behaviour itself, would make whole thing useless.
All I needed were just commands "what to do" and some basic flow operations (if, goto is completely enough). I talked to my colleagues and they of course told me, that there is LUA, that there are other scripting languages. While I would like to have whole logic run on LUA in future, I wanted to experiment with modular design and after looking for a while after some nice scripting language, I decided that it might be much better to create my own one.
This decision let me create syntax that suits writing AI. Adding commands such as "move there", "wait until you get there", "find all enemies around" with just single line and as similar to normal english as possible was my top priority. At some point I considered creating something simplier, that would look like assembler but I dropped that idea. BASIC was the best choice. And I am talking about normal, old school BASIC, not objective-based language with BASIC keywords. Just plan BASIC. If, goto, gosub, let and so on (sidenote: I don't have "for" nor "while" at the moment and I don't have need to add this, at least not yet).
I needed to write parser that translates code into p-code and something that will run that p-code. P-code resembles assembled code. These are just numbers and that works pretty well. Of course I had problems with parsing as some of keywords might be problematic in some cases. For example I have "to" operator that works as random operator. "2.0 to 3.0" translates into "a random number between 2.0 and 3.0" but it is used also in other places, such as writing recipent of message "to $someone". Yes, I have "$" in front of variables and only because it makes it easier to parse them...
But while I have just very basic subset of BASIC commands, I added much more to handle AI. I will give you an example now:
local distance
local circlingDir
; setup values
go sub ChooseDistance
go sub ChooseCirclingDir
Start:
movement clear
movement move to $MyEnemy at range $distance and keep
movement circle around $MyEnemy by $circlingDir and keep
movement face $MyEnemy
wait 1.0 to 3.0
if 25% chance
go sub ChooseDistance
endif
if 15% chance
go sub ChooseCirclingDir
endif
go to Start
; subs
ChooseDistance:
$distance = (1.0 to 2.0)
return
ChooseCirclingDir:
$circlingDir = (-90 or 90)
return
What does it do? Circles around MyEnemy in random direction ("movement cirlce around") at random distance ("movement move to ... at range"). Both those values change from time to time (each chance happens at 1 to 3 seconds interval) with random chance of happening.
Simple, isn't it? I already used something similar with project I worked on. Although I just created functions that had some of functionality visible above. Syntax was a little bit more complicated and less flexible, due to limitations of language I worked with.
There are also priorities for behaviours, ending behaviours only at some priority level with some time allowance. You can even execute code in other behaviour or from other part of code (such as message handler).
And on messages I will focus next time.
I decided that I want something simple to write, read and run. Behaviours may run in parallel and I wanted to have system of messages (more on that later) and this can bring enough complexity into system, that having some strange setup of behaviour itself, would make whole thing useless.
All I needed were just commands "what to do" and some basic flow operations (if, goto is completely enough). I talked to my colleagues and they of course told me, that there is LUA, that there are other scripting languages. While I would like to have whole logic run on LUA in future, I wanted to experiment with modular design and after looking for a while after some nice scripting language, I decided that it might be much better to create my own one.
This decision let me create syntax that suits writing AI. Adding commands such as "move there", "wait until you get there", "find all enemies around" with just single line and as similar to normal english as possible was my top priority. At some point I considered creating something simplier, that would look like assembler but I dropped that idea. BASIC was the best choice. And I am talking about normal, old school BASIC, not objective-based language with BASIC keywords. Just plan BASIC. If, goto, gosub, let and so on (sidenote: I don't have "for" nor "while" at the moment and I don't have need to add this, at least not yet).
I needed to write parser that translates code into p-code and something that will run that p-code. P-code resembles assembled code. These are just numbers and that works pretty well. Of course I had problems with parsing as some of keywords might be problematic in some cases. For example I have "to" operator that works as random operator. "2.0 to 3.0" translates into "a random number between 2.0 and 3.0" but it is used also in other places, such as writing recipent of message "to $someone". Yes, I have "$" in front of variables and only because it makes it easier to parse them...
But while I have just very basic subset of BASIC commands, I added much more to handle AI. I will give you an example now:
local distance
local circlingDir
; setup values
go sub ChooseDistance
go sub ChooseCirclingDir
Start:
movement clear
movement move to $MyEnemy at range $distance and keep
movement circle around $MyEnemy by $circlingDir and keep
movement face $MyEnemy
wait 1.0 to 3.0
if 25% chance
go sub ChooseDistance
endif
if 15% chance
go sub ChooseCirclingDir
endif
go to Start
; subs
ChooseDistance:
$distance = (1.0 to 2.0)
return
ChooseCirclingDir:
$circlingDir = (-90 or 90)
return
What does it do? Circles around MyEnemy in random direction ("movement cirlce around") at random distance ("movement move to ... at range"). Both those values change from time to time (each chance happens at 1 to 3 seconds interval) with random chance of happening.
Simple, isn't it? I already used something similar with project I worked on. Although I just created functions that had some of functionality visible above. Syntax was a little bit more complicated and less flexible, due to limitations of language I worked with.
There are also priorities for behaviours, ending behaviours only at some priority level with some time allowance. You can even execute code in other behaviour or from other part of code (such as message handler).
And on messages I will focus next time.
No comments:
Post a Comment