When implementing such bot as Hunter, first you have to propose goals, then you write a productions. In this section we will show you goals of Hunter and some of his productions.
Hunter has goal chunk with two slots defined in declarative memory:
<chunk-type name="pogamutGoalChunk"> <slot name="finished" equals="nil" /> <slot name="intention" equals="nil" /> <slot name="following" equals="nil" /> </chunk-type>
First slot says if Hunter is running. If some production set this slot to true, agent will stop.
Second slot is determining what is current intention of bot. It is simple state of agent mind. Hunter can be only in two states:
runAround: state when agent is running randomly around the map looking for enemy
following: state when Hunter is chasing enemy
Third slot is for enemy ID
Simplest production is only reaction to buffer and adding to another buffer. In this example Hunter is reacting only on goal buffer. If procedural modul match this production it simply add command chunk with rotate command to movement command buffer. If body command module don't have any job it will send rotate command throught Pogamut to UT2004. For explanation of command chunks see javadoc for CommandChunkWrapper. For list of supported command see javadoc for concrete command buffer.
<production name="doNothing"> <condition> <match buffer="goal" type="pogamutGoalChunk"> <slot name="finished" equals="false" /> <slot name="intention" equals="runAround" /> </match> </condition> <action> <add buffer="movementCommandBuffer" type="commandChunk"> <slot name="command" equals="rotate" /> <slot name="param1" equals="3000.0" /> </add> <output>"Do nothing - rotate"</output> </action> </production>
Another simple production is modifying production. This production
only change values of pogamut goal chunk in goal buffer. It saves id of
player to slot following
. Again, javadoc for concrete
module, buffer and chunk wrapper will give you another information about
chunks and content of buffers.
<production name="beginToFollow"> <condition> <match buffer="goal" type="pogamutGoalChunk"> <slot name="finished" equals="false" /> <slot name="intention" equals="runAround" /> </match> <match buffer="defaultVisualObjectBuffer" type="visualObjectChunk"> <slot name="class" equals="player" /> <slot name="id" equals="=pl" /> <slot name="location" equals="=loc" /> </match> </condition> <action> <modify buffer="goal"> <slot name="intention" equals="following"/> <slot name="following" equals="=pl"/> </modify> <output>"Beginning to follow"</output> </action> </production>
Important production is request production. Sometimes you has to ask your perception module, if it still receiving some stimuli. In Hunter's case it is question to visual object buffer, if it still see enemy player. Production with question looks like this:
<production name="stillFollowBot"> <condition> <match buffer="goal" type="pogamutGoalChunk"> <slot name="finished" equals="false" /> <slot name="intention" equals="following" /> <slot name="following" equals="=pl"/> </match> </condition> <action> <add buffer="defaultVisualObjectBuffer" type="visualObjectChunk"> <slot name="id" equals="=pl" /> </add> <output>"ask if still following"</output> </action> </production>
If PoJACT-R perception buffer receives chunk with slots id or class, it will look for object that maches it. Important is that it is searching through full content of buffer, not only few chunks visible to buffer. If search was successful, chunk with that id or class will apear in buffer for later matching. If such chunk doesn't exist in buffer, buffer will expose error chunk with same id or class. Reaction on such error shows this production.
<production name="stopFollowBot"> <condition> <match buffer="goal" type="pogamutGoalChunk"> <slot name="finished" equals="false" /> <slot name="intention" equals="following" /> <slot name="following" equals="=pl"/> </match> <match buffer="defaultVisualObjectBuffer" type="errorChunk"> <slot name="id" equals="=pl"/> </match> </condition> <action> <add buffer="bodyCommandBuffer" type="commandChunk"> <slot name="command" equals="stopshooting" /> </add> <modify buffer="goal"> <slot name="intention" equals="runAround"/> </modify> <output>"stop following, i cannot see any player"</output> </action> </production>