Another Try
by David House · in Torque Game Builder · 11/23/2007 (8:28 am) · 49 replies
OK, lets see if you like this behavior instead. The Event System behavior I had created was really just a finite state machine, so I created a new behavior specifically for that. And really this is more useful as a behavior anyway. For our game we needed a simple AI system for the enemies, so we are going to use a basic FSM for that. I also simplified how the Datablocks are created/named so it doesn't have some of the ugly indexes of the Event System datablocks I had.
The behavior has a single parameter, the name of the initial State. All the states are Datablocks that look like this:
So you have a delay & method when you first enter the state. Then a state method that is called after the state is entered, or after a repeat (when you are staying at the same state). The nextMethod allows you to determine which state to transition to (or stay at the current state). The leaveDelay and leaveMethod are called when you are leaving the state. The finally the repeatDelay is the time delay if you are simply repeating the current state. All the delays are evaled, so you can put code in there to determine the delay (for random delays).
As an example, I have a quick YouTube video:
www.youtube.com/watch?v=nG64IBhC9tw
As a test, I have a single fish and falling food. Both the fish and food are controlled by a FSM. The fish has the following states:
- MoveLeft (moves to the left side of the screen)
- WaitLeft (waits around on the left side of the screen for a few seconds)
- MoveRight
- WaitRight
- EatFood (move to a close bit of food)
The food simply has a single state DropFood with a random repeatDelay
The MoveLeft and MoveRight states move the fish and check for 2 conditions. Either the fish has arrived and it moves to the Wait state, or it finds a close bit of food, then moves to the EatFood state.
Nothing too fancy yet here (this is a basic FSM). Just wondering if anyone has any comments/suggestions. What I'm thinking of is to build some kind of GUI app to simplify the creation of the datablocks. It would be awesome to get this to a point where very little scripting is necessary (part of the point of Behaviors).
The behavior has a single parameter, the name of the initial State. All the states are Datablocks that look like this:
new t2dSceneObjectDatablock(moveLeft)
{
enterDelay = 1000;
enterMethod = "moveToLeft(%this);";
stateMethod = "";
nextMethod = "lookForFood(%this,\"-34.762 -3.92\",10.5,\"waitLeft\",\"moveLeft\")";
leaveDelay = 1000;
leaveMethod = "";
repeatDelay = 1000;
};So you have a delay & method when you first enter the state. Then a state method that is called after the state is entered, or after a repeat (when you are staying at the same state). The nextMethod allows you to determine which state to transition to (or stay at the current state). The leaveDelay and leaveMethod are called when you are leaving the state. The finally the repeatDelay is the time delay if you are simply repeating the current state. All the delays are evaled, so you can put code in there to determine the delay (for random delays).
As an example, I have a quick YouTube video:
www.youtube.com/watch?v=nG64IBhC9tw
As a test, I have a single fish and falling food. Both the fish and food are controlled by a FSM. The fish has the following states:
- MoveLeft (moves to the left side of the screen)
- WaitLeft (waits around on the left side of the screen for a few seconds)
- MoveRight
- WaitRight
- EatFood (move to a close bit of food)
The food simply has a single state DropFood with a random repeatDelay
The MoveLeft and MoveRight states move the fish and check for 2 conditions. Either the fish has arrived and it moves to the Wait state, or it finds a close bit of food, then moves to the EatFood state.
Nothing too fancy yet here (this is a basic FSM). Just wondering if anyone has any comments/suggestions. What I'm thinking of is to build some kind of GUI app to simplify the creation of the datablocks. It would be awesome to get this to a point where very little scripting is necessary (part of the point of Behaviors).
#2
Thanks for the response. That pretty much confirms what I was thinking. Work has crawled to a stop on the current game I'm working on because I'm having to do all the coding and the others are waiting on me. Ideally if I can create a system that they can use to create more configurable FSMs it would be awesome.
Perhaps an external tool that generates the FSM code. I'll think on this for a bit and maybe go for attempt #3.
It would also be interesting to see where GG is going with Torque 2 and behaviors. I don't want to duplicate their efforts.
12/14/2007 (7:58 pm)
Don,Thanks for the response. That pretty much confirms what I was thinking. Work has crawled to a stop on the current game I'm working on because I'm having to do all the coding and the others are waiting on me. Ideally if I can create a system that they can use to create more configurable FSMs it would be awesome.
Perhaps an external tool that generates the FSM code. I'll think on this for a bit and maybe go for attempt #3.
It would also be interesting to see where GG is going with Torque 2 and behaviors. I don't want to duplicate their efforts.
#3
It would take a fair bit of work for me to try and convert, since some of the scripts were written by my programmer friend and are organized much differently than mine. There's also the issue that we were working mostly with the beta releases early on, and lastly the matter of changes to the code that he made. Again, in beta, that may or may not conflict with where the TGB 1.5 code is at this point.
I suppose the biggest hurdle might be in the changing of states for the object. I.e. if it's attacked you and then meets a 'disengage' criteria, you'd want to go back... to... actually, that might not be too hard. Hrmm. I'm going to have to see if I can get those old scripts at least working in TGB - this has my curiosity worked up.
12/15/2007 (3:53 pm)
It's interesting to me to think about how an FSM is organized, I realy should do some more reading on it so I know what the 'real' system is. It sounds like something that should be easy enough to do, and sort of like what I was doing in script at one point. Essentially, I had a patrolling object that was detecting, and if it saw the player it could track and fire, or it could pursue, or both.It would take a fair bit of work for me to try and convert, since some of the scripts were written by my programmer friend and are organized much differently than mine. There's also the issue that we were working mostly with the beta releases early on, and lastly the matter of changes to the code that he made. Again, in beta, that may or may not conflict with where the TGB 1.5 code is at this point.
I suppose the biggest hurdle might be in the changing of states for the object. I.e. if it's attacked you and then meets a 'disengage' criteria, you'd want to go back... to... actually, that might not be too hard. Hrmm. I'm going to have to see if I can get those old scripts at least working in TGB - this has my curiosity worked up.
#4
Is your FSM Torque scripted or is c++ coded in TGB? The video of the fish does show AI. Good work.
Carpenter Software
12/19/2007 (1:52 pm)
@ DavidIs your FSM Torque scripted or is c++ coded in TGB? The video of the fish does show AI. Good work.
Carpenter Software
#5
12/24/2007 (7:05 am)
Totally scripted. I am trying to make this 100% script based if possible. I did an event system way back by modifying the engine, but it just seems like it is easier to leave it all script based. But I'm still not sure that this can be done as cleanly as I would like just with script. Got a few new ideas that I'll probably play around with over the holiday break (took this whole week off from work). I'll update the thread with the progress.
#6
Curious! I am also looking at the book GPGT at chap 6.6.5 State Machines. There it speaks about ShapeBaseImageData but this belongs to TGE. I am still working on a script for TGB 1.1.3 to set up a simple state machine. It seems that the commands from TGB were used in your state machine so I was curious about it and I asked the question after viewing the movie you had posted. Very Good AI for a simple FSM.
Anyway thanks for the info....
Carpenter Software
12/24/2007 (7:39 am)
@ DavidCurious! I am also looking at the book GPGT at chap 6.6.5 State Machines. There it speaks about ShapeBaseImageData but this belongs to TGE. I am still working on a script for TGB 1.1.3 to set up a simple state machine. It seems that the commands from TGB were used in your state machine so I was curious about it and I asked the question after viewing the movie you had posted. Very Good AI for a simple FSM.
Anyway thanks for the info....
Carpenter Software
#7
Question: Is it possible to use parentheses after the method's name (ie $stateObj.methodName()) to call the dynamic method instead of using the call() function?
Game (weak) AI is one of my big interest. There are many ways to write a fsm once you know how it works. Please comment. Thanks Carpenter Software.
01/06/2008 (12:15 pm)
Finally I have finished a simple finite state machine (fsm) using torquescript. Although I am still using TGB 1.1.3, the fsm works as expected. I also used the t2dSceneObjectDatablock as did David House above. In the datablock, I place static members and methods for states with embedded rules via their static methods (but these members and methods must be consistent with other states). Then I used t2dSceneObject to place all dynamic members and methods that match the static variables but also placed additional variables in this base object. Since all other objects are a subclass of t2dSceneObject nearly all objects may use this paradigm. To make the state machine operate, I used several commands. To switch datablocks, I used setConfigDatablock(%config), an t2dSceneObject function. To call the dynamic methods, I used "call(%function, [%args = ""])", a console function. (I believe this call() function may have been renamed in newer versions of TGB). Lastly to cycle the state machine, I used a single schedule(%time, %refObject, %command, %args), another console function. Also I used the related functions of the previous functions mentioned above.Question: Is it possible to use parentheses after the method's name (ie $stateObj.methodName()) to call the dynamic method instead of using the call() function?
Game (weak) AI is one of my big interest. There are many ways to write a fsm once you know how it works. Please comment. Thanks Carpenter Software.
#8
I know just enough about the technical aspects of scripting to follow most of what you described and it sounds like a very good script solution.
One part I'm not quite clear on is how the single schedule is affecting the FSM - do you mean that A) one schedule is run to update all elements that use the FSM at once, or B) there's a common schedule that every object calls as it needs to check what to do next?
When I was working on a project with a programmer friend, he used the analogy of having one brain to do the thinking for our enemies as opposed to the way I had done it which was like lots of little brains, and not very bright ones at that.
I had made a series of functions that the entities started stepping through the moment they were created. I.e. detect, if yes orient and shoot, if no go back to detect - I was hitting a wall of complexity really fast when I began trying to get into things like pursue, flee, etc.
Anyway, getting back to your system, I guess the way I'm trying to understand it is with that brain analogy - do the entities get told what to do next in a single broadcast ("Now hear this, if you're doing X it's time to do Y.") Or do they ask what to do next? ("Hello, I've been doing X and this is what's going on, what should I do now?")
Fascinating stuff, I should make the time to learn more about it - thanks for sharing your process!
@ David House:
I forgot to follow up on an earlier post so I'll do that now. I did take the time to go back to my earlier project and look at some of the functions we had been working with. What I discovered was that the elements my partner had been working on were relying on some additions he'd made to the C++ code base.
I wasn't entirely clear if he'd changed any of the stock code as well, and the only response I was able to get from him was that it could be difficult to migrate to the current version since "GG changed some things between builds." I have been tempted to go ahead and use WinMerge to see if I could find what he was referring to, but just haven't had that much time to actually sit down and do it.
I suppose I'd had visions of being able to turn some of that past project into behaviors and miraculously continue the project on my own. ;)
EDIT: Grammar.
01/06/2008 (1:47 pm)
@ Carpenter Software: I know just enough about the technical aspects of scripting to follow most of what you described and it sounds like a very good script solution.
One part I'm not quite clear on is how the single schedule is affecting the FSM - do you mean that A) one schedule is run to update all elements that use the FSM at once, or B) there's a common schedule that every object calls as it needs to check what to do next?
When I was working on a project with a programmer friend, he used the analogy of having one brain to do the thinking for our enemies as opposed to the way I had done it which was like lots of little brains, and not very bright ones at that.
I had made a series of functions that the entities started stepping through the moment they were created. I.e. detect, if yes orient and shoot, if no go back to detect - I was hitting a wall of complexity really fast when I began trying to get into things like pursue, flee, etc.
Anyway, getting back to your system, I guess the way I'm trying to understand it is with that brain analogy - do the entities get told what to do next in a single broadcast ("Now hear this, if you're doing X it's time to do Y.") Or do they ask what to do next? ("Hello, I've been doing X and this is what's going on, what should I do now?")
Fascinating stuff, I should make the time to learn more about it - thanks for sharing your process!
@ David House:
I forgot to follow up on an earlier post so I'll do that now. I did take the time to go back to my earlier project and look at some of the functions we had been working with. What I discovered was that the elements my partner had been working on were relying on some additions he'd made to the C++ code base.
I wasn't entirely clear if he'd changed any of the stock code as well, and the only response I was able to get from him was that it could be difficult to migrate to the current version since "GG changed some things between builds." I have been tempted to go ahead and use WinMerge to see if I could find what he was referring to, but just haven't had that much time to actually sit down and do it.
I suppose I'd had visions of being able to turn some of that past project into behaviors and miraculously continue the project on my own. ;)
EDIT: Grammar.
#9
First of all, I do not know anything about behaviors in the TGB 1.5.1 or 1.6.0 versions. Sorry! I am still using TGB 1.1.3. My interest is setting up a simple finite state machine (fsm) using torquescript. I have searched throughout all GG forums for any information on the subject. The results were very little on the subject. David House has a nice UTube movie on his fsm fish that demonstrated how dataBlocks may be used as States with embedded rules on how the fish will behave. So we have a dilemma. AI behavior in general and TGB's behaviors. The topic on fsm may or may not be related to behaviors BUT here we are....
The single schedule function is only used to loop the state machine only. A way to update the state object either to continue the current state or to transition to another state. To reiterate, the State Machine is always looping checking on the current state. The embedded rules are checked to see if a condition is warranted to change to another state. Thus making an object look smart. So the States and the State Machine that operates on the States is a very interesting idea. There are several good books on the subject.
As yet, I do NOT have a firm knowledge on how dataBlocks and Objects work. I have come to the conclusion that GG has this knowledge under their belt. FSM is an abstract model to make game objects look smart (AI). So my goal is to discover that knowledge. So do not give up....
The brain thing is what fsm does, change one state of the object to another based on the rules of the state.
(added)
Also I should mention that David House uses a nextMethod implying chain-rules instead of state-rules, I could be wrong but David does not go into any details on how rules are used in his State Machine. It is likely he is also using state-rules.
Thanks for your comment....
Carpenter Software
01/06/2008 (2:17 pm)
@ Don Hogan:First of all, I do not know anything about behaviors in the TGB 1.5.1 or 1.6.0 versions. Sorry! I am still using TGB 1.1.3. My interest is setting up a simple finite state machine (fsm) using torquescript. I have searched throughout all GG forums for any information on the subject. The results were very little on the subject. David House has a nice UTube movie on his fsm fish that demonstrated how dataBlocks may be used as States with embedded rules on how the fish will behave. So we have a dilemma. AI behavior in general and TGB's behaviors. The topic on fsm may or may not be related to behaviors BUT here we are....
The single schedule function is only used to loop the state machine only. A way to update the state object either to continue the current state or to transition to another state. To reiterate, the State Machine is always looping checking on the current state. The embedded rules are checked to see if a condition is warranted to change to another state. Thus making an object look smart. So the States and the State Machine that operates on the States is a very interesting idea. There are several good books on the subject.
As yet, I do NOT have a firm knowledge on how dataBlocks and Objects work. I have come to the conclusion that GG has this knowledge under their belt. FSM is an abstract model to make game objects look smart (AI). So my goal is to discover that knowledge. So do not give up....
The brain thing is what fsm does, change one state of the object to another based on the rules of the state.
(added)
Also I should mention that David House uses a nextMethod implying chain-rules instead of state-rules, I could be wrong but David does not go into any details on how rules are used in his State Machine. It is likely he is also using state-rules.
Thanks for your comment....
Carpenter Software
#10
As far as behaviors go, the short explanation would be that they are encapsulated functions, attributes or variables that are formatted in a way to be accessible through the TGB editor behavior menu. The existing ones in the current build of TGB are actually pretty simple from a scripting viewpoint.
My experience so far is that you can get some interesting results out of a combination of simple behaviors, but I really wonder if they might make things more difficult as a project got more complex. In wrapping them up to be accessible to the editor, it seems to me that you wind up sort of 'hiding' the information from other scripts.
The biggest draw to them (in my opinion) is that they definitely make the creation process more approachable for people new to development and scripting.
If I were to try and relate this to a development environment using FSMs in TGB, I would have to say that my first choice for implementation would be a behavior that simply assigns the object to use the FSM.
The next step would be adding options to the behavior that allows for tuning any of the parameters of the FSM functions. I.e. the amount time for the schedule call to make the entity appear to be a fast or slow 'thinker'; or the datablock to start with so the entity could be passive or aggressive on creation; and so on, depending on what's available in your particular FSM.
Anyway, just some more thoughts on the subject, thank you for the interesting conversation!
01/06/2008 (3:11 pm)
Thank you for the further explanation, that does help me see the process a little clearer.As far as behaviors go, the short explanation would be that they are encapsulated functions, attributes or variables that are formatted in a way to be accessible through the TGB editor behavior menu. The existing ones in the current build of TGB are actually pretty simple from a scripting viewpoint.
My experience so far is that you can get some interesting results out of a combination of simple behaviors, but I really wonder if they might make things more difficult as a project got more complex. In wrapping them up to be accessible to the editor, it seems to me that you wind up sort of 'hiding' the information from other scripts.
The biggest draw to them (in my opinion) is that they definitely make the creation process more approachable for people new to development and scripting.
If I were to try and relate this to a development environment using FSMs in TGB, I would have to say that my first choice for implementation would be a behavior that simply assigns the object to use the FSM.
The next step would be adding options to the behavior that allows for tuning any of the parameters of the FSM functions. I.e. the amount time for the schedule call to make the entity appear to be a fast or slow 'thinker'; or the datablock to start with so the entity could be passive or aggressive on creation; and so on, depending on what's available in your particular FSM.
Anyway, just some more thoughts on the subject, thank you for the interesting conversation!
#11
I believe that dataBlocks used by David House is so far the best scriptable way to set up States for a State Machine. So if there are any other ideas, please share them. Thanks.
Carpenter Software
01/06/2008 (3:57 pm)
I have looked over Gustavo Boni blog on his FSM Click Here to View Blog but it seems he uses Globals for his states but it is a good example how rules are embedded within the State or within the State Machine itself. Upon further reading, his FSM was c++ coded. Personally I think torquescript is already set up for a FSM unless there is a performance problem.I believe that dataBlocks used by David House is so far the best scriptable way to set up States for a State Machine. So if there are any other ideas, please share them. Thanks.
Carpenter Software
#12
01/06/2008 (9:43 pm)
Lua makes this pretty easy with coroutines. I wish TorqueScript had something similar... My game logic is pure Lua. I have a behavior like Don talks about, to simply tell the object to use a FSM. When the level is loaded, the object gets a new coroutine attached to it. My objects can send and receive messages from the game or other objects, then decide how to react based on the message. I'm not sure if it helps those not using Lua at all, but I figured I'd share how I'm handling this...
#13
Programming languages are all the same to me. Since I have the code to TGB and TGE, I can modify using c++. I am still learning patterns and weak AI with OOP in c++. One of the main reasons I purchased a license from GG is to tinker with the code. Furthermore, I have many books oriented towards c++ and also torque script is similar to c/c++ so I am happy with it. I trust that c/c++ will also be around for a long time.
I am presently working on a torque scripted example with a single fsm to handle 10+ objects. This AI example will be using the fish data in a food chain scenario. One big fish, two medium fishes and eight small fishes looking for food. I am presently working on 4 states: EvadeState, ChaseState, RestState and RoamState. Where the first priority starting with EvadeState and the last priority with RoamState. Some of the fishes will not use all states, for example, the big fish may not evade and the small fishes may not chase.
Since I am using TGB, I will be using its editor. Already I have a small setback in assigning the states. Instead of using dataBlacks like in the above fsm example, I'll use the Dynamic Fields in the editor to place the dynamic states. So each fish will have a loopingState initiated with the loopingRoamState which is a static method. I am testing only one assignment at this time but maybe later there will also be an enterState and an exitState. Now I have two accessor function: getState() and setState(). The setState function replaced the setConfigDatablock(%config) function.... I tested the finite state machine last night and it works as expected.
Later this week I may have a working example.
Carpenter Software
01/07/2008 (11:12 am)
Thanks Joe - I have heard many good things about the Lua programming language. Maybe you can tell us more how lua uses the fsm.Programming languages are all the same to me. Since I have the code to TGB and TGE, I can modify using c++. I am still learning patterns and weak AI with OOP in c++. One of the main reasons I purchased a license from GG is to tinker with the code. Furthermore, I have many books oriented towards c++ and also torque script is similar to c/c++ so I am happy with it. I trust that c/c++ will also be around for a long time.
I am presently working on a torque scripted example with a single fsm to handle 10+ objects. This AI example will be using the fish data in a food chain scenario. One big fish, two medium fishes and eight small fishes looking for food. I am presently working on 4 states: EvadeState, ChaseState, RestState and RoamState. Where the first priority starting with EvadeState and the last priority with RoamState. Some of the fishes will not use all states, for example, the big fish may not evade and the small fishes may not chase.
Since I am using TGB, I will be using its editor. Already I have a small setback in assigning the states. Instead of using dataBlacks like in the above fsm example, I'll use the Dynamic Fields in the editor to place the dynamic states. So each fish will have a loopingState initiated with the loopingRoamState which is a static method. I am testing only one assignment at this time but maybe later there will also be an enterState and an exitState. Now I have two accessor function: getState() and setState(). The setState function replaced the setConfigDatablock(%config) function.... I tested the finite state machine last night and it works as expected.
Later this week I may have a working example.
Carpenter Software
#14
Note: This is an incredible simplification of my actual FSM and is untested. I am only posting this to show the logic behind my basic FSM.
01/07/2008 (2:22 pm)
I use a FSM for my animation manager, it is a pretty simple intergration and works well.function AnimationManager::onAddToScene(%this, %scenegraph)
{
%this.RegisteredStates = new ScriptObject();
%this.RegisterState("idle");
%this.RegisterState("run");
%this.CurrentState = "idle";
}
function AnimationManager::registerState(%this, %state)
{
%datablock = %this.getDynamicField(%state @ "Animation");
if (isObject(%datablock))
%this.RegisteredStates.setFieldValue(%state, %datablock);
}
function AnimationManager::updateAnimation(%this)
{
eval("%targetState = " @ %this.CurrentState @ "State::execute(%this);");
%this.setState(%targetState);
}
function AnimationManager::AnimateCharacter(%this, %animation)
{
%this.Owner.setAnimation(%animation);
}
function AnimationManager::setState(%this, %targetState)
{
if (%targetState $= NULL || !isObject(%this.RegisteredStates.getFieldValue(%targetState)))
return;
%this.exit();
%this.PreviousState = %this.CurrentState;
%this.CurrentState = %targetState;
eval (%this.CurrentState @ "State::enter(%this);");
}
function AnimationManager::enter(%this)
{
// Find transitions
}
function AnimationManager::execute(%this)
{
// Perform any transitions here
}
function AnimationManager::exit(%this)
{
// More stuff
}
//-------------------------------------------------------
// Various States
//-------------------------------------------------------
function IdleState::enter(%this)
{
%this.enter();
%this.TransitionTo = %this.IdleAnimation;
if (!%this.Transitioning)
%this.AnimateCharacter(%this.TransitionTo);
}
function IdleState::execute(%this)
{
%this.execute();
if (%this.Owner.LinearVelocity.X != 0)
return "run";
return NULL;
}
function RunState::enter(%this)
{
%this.enter();
%this.TransitionTo = %this.RunAnimation;
if (!%this.Transitioning)
%this.AnimateCharacter(%this.TransitionTo);
}
function RunState::execute(%this)
{
%this.execute();
if (%this.Owner.LinearVelocity.X == 0)
return "idle";
return NULL;
}Note: This is an incredible simplification of my actual FSM and is untested. I am only posting this to show the logic behind my basic FSM.
#15
Thanks! This is the first torque scripted fsm I have seen, and I like the way you use registerState to set up your dynamic states. I'm coming to the conclusion the best way to learn the code (c++ and the script commands) is to jump right in. This is a simple fsm but elegant. I like it.
Curious - could you show or talk about the AI of your animation between your Idle and Run States. Of course some would argue that the keyboard could be used for that but this is not a player character rather a NPC. Again thanks Phillip for sharing this with us.
I am still using static sprites to experiment. I want to use multiple class objects and multiple states (at least 4 states). As soon as I get one going. I'll share. The easy part is the fsm. The hard part as I am learning is setting up the states. So far I threw out code the was rubbish. I started to use a state table to layout the current states, the conditions and the state transitions. The states I had mentioned above now have been changed to the following:
Please comment on this table (Method taken from "Programming Game AI by Example" by Mat Buckland, p47)
Maybe with Phillip's FSM maybe the static sprites can then be animated sprites.
Carpenter Software
01/08/2008 (11:03 am)
@ Phillip OsheaThanks! This is the first torque scripted fsm I have seen, and I like the way you use registerState to set up your dynamic states. I'm coming to the conclusion the best way to learn the code (c++ and the script commands) is to jump right in. This is a simple fsm but elegant. I like it.
Curious - could you show or talk about the AI of your animation between your Idle and Run States. Of course some would argue that the keyboard could be used for that but this is not a player character rather a NPC. Again thanks Phillip for sharing this with us.
I am still using static sprites to experiment. I want to use multiple class objects and multiple states (at least 4 states). As soon as I get one going. I'll share. The easy part is the fsm. The hard part as I am learning is setting up the states. So far I threw out code the was rubbish. I started to use a state table to layout the current states, the conditions and the state transitions. The states I had mentioned above now have been changed to the following:
Current State Conditions State Transitions ----------------- ------------- -------------------- RoamState isHungry HuntState RoamState isThreaten EvadeState (DoEvade) HuntState foundPrey ChaseState (DoChase) HuntState isThreaten EvadeState (DoEvade) ChaseState caughtPrey RoamState ChaseState lostPrey RoamState EvadeState isSafe RoamState Still Deciding to Use: EvadeState isDead (spawn) RoamState
Please comment on this table (Method taken from "Programming Game AI by Example" by Mat Buckland, p47)
Maybe with Phillip's FSM maybe the static sprites can then be animated sprites.
Carpenter Software
#16
(added)
As in Philip's fsm above, he has two states, therefore a max of one condition per state. Either the avatar is moving or it is not. I noticed also that his state machine has an enter and an execute calls that operate on his states where I am using only one call similar to his execute call. Later I may add an enter and an exit call as well.
Carpenter Software
01/08/2008 (1:18 pm)
I just noticed now in the table above that if there are a finite number of states there cannot be a number of conditions greater than the number of states minus one. I do not know if this makes any sense. If there are four states, then there cannot be more than 3 conditions per state. I think that the HuntState above is more a chain-rule than a state-rule. Maybe the current state roam can also jump straight into a ChaseState depending the kind of AI effect.(added)
As in Philip's fsm above, he has two states, therefore a max of one condition per state. Either the avatar is moving or it is not. I noticed also that his state machine has an enter and an execute calls that operate on his states where I am using only one call similar to his execute call. Later I may add an enter and an exit call as well.
Carpenter Software
#17
edited
Image removed
Carpenter Software
01/14/2008 (9:41 am)
I am surprised how big the State Transition Table may become when working with multiple objects.... All I did this last week was WORK on this table until it was logical. (Made sense).edited
Image removed
Carpenter Software
#18
I will build the test game from the State Transition Table above....
Below is a few code snippets to show the Roam state:
This machine was tested on a few sprites, I love to see if it will work on the above State Transition Table.
Carpenter Software
01/14/2008 (10:05 am)
I am also finished with a working fsm (very simple)// FINITE STATE MACHINE
// Carpenter Software
// Accessor Functions
function getState(%this)
{
// All Objects have a Looping State
%string = %this.loopingState;
%start = 7;
%length = strlen(%string);
%numChars = %length - %start + 1;
%state = getSubStr(%string, %start, %numChars);
return %state;
}
function setState(%this, %state)
{
if (%state $= "none") return;
// 8 States player predator mediumFish smallFish
// ---------- ------ -------- ---------- ---------
// EvadeState x x
// FightState x
// ChaseState x x
// HuntState x x
// RoamState x x
// PlayState x
// EatenState x x x
// DeadState x x
// Set Current State in Dynamic Fields
// %this.enterState = "enter" @ %state;
%this.loopingState = "looping" @ %state;
// %this.exitState = "exit" @ %state;
}
$spriteAvatarCount = 0;
function getSprite()
{
if ($spriteAvatarCount > 9) $spriteAvatarCount = 0;
$spriteAvatarCount++;
if ($spriteAvatarCount == 1) return $smallFishA;
if ($spriteAvatarCount == 2) return $player;
if ($spriteAvatarCount == 3) return $smallFishB;
if ($spriteAvatarCount == 4) return $player;
if ($spriteAvatarCount == 5) return $smallFishC;
if ($spriteAvatarCount == 6) return $player;
if ($spriteAvatarCount == 7) return $mediumFish;
if ($spriteAvatarCount == 8) return $player;
if ($spriteAvatarCount == 9) return $predator;
if ($spriteAvatarCount == 10) return $player;
}
// Simple Finite State Machine
function cycleFSM(%this)
{
// Finite State Machine
// Get Current State from Dynamic Fields
%method = %this.loopingState;
// Call Current State [i]edited Jan 14, 2008[/i]
call(%method, %this);
// Cycle Next Sprite
$cycleSpriteEvent = schedule(100, 0, "cycleSprite");
}
$machineOn = 1;
function cycleSprite()
{
// cycle FSM
if ($machineOn)
{
%this = getSprite();
$cycleFSMEvent = schedule(100, 0, "cycleFSM", %this);
}
}I will build the test game from the State Transition Table above....
Below is a few code snippets to show the Roam state:
// RoamState
// smallFish
function smallFishRoam(%this)
{
%class = %this.class;
if (%class $= "smallFish")
{
minusEnergy(%this, 1);
////////////////////
DoRoam(%this);
////////////////////
// Check Transition Rules
if (isThreaten(%this))
{
setState(%this, "EvadeState");
return true;
}
return true;
}
return false;
}
// mediumFish
function mediumFishRoam(%this)
{
%class = %this.class;
if (%class $= "mediumFish")
{
minusEnergy(%this, 1);
////////////////////
DoRoam(%this);
////////////////////
// Check Transition Rules
if (isThreaten(%this))
{
setState(%this, "EvadeState");
return true;
}
if (isHungry(%this))
{
setState(%this, "HuntState");
return true;
}
return true;
}
return false;
}
// Static Looping Roam State
function loopingRoamState(%this)
{
if (smallFishRoam(%this)) return;
if (mediumFishRoam(%this)) return;
}This machine was tested on a few sprites, I love to see if it will work on the above State Transition Table.
Carpenter Software
#19
01/14/2008 (10:56 am)
Although I have an unread game AI book sitting on my shelf, this is really interesting stuff. Do you have any plans to share the fish game you create, Carpenter Software? Something like this would make for a great tutorial on TDN.
#20
added
Also I took an associates advice on using a State Transition Table as a guide. Imagine trying to code multiple objects without it.
Thanks
Carpenter Software.
01/14/2008 (11:08 am)
This is my first finite state machine in torquescript being applied. Game (weak) AI is very interesting. Mike if you start reading your unread game AI book, it maybe that you will read the book several times just because it is interesting. I had finished a game recently but it is lacking some AI. I went back to the drawing board to incorporate a FSM. If this game test works out, I will incorporate the FSM. The fish game is just a test on TGB 1.1.3. If you are interested, I'll post a blog here at GG with the complete torquescript.added
Also I took an associates advice on using a State Transition Table as a guide. Imagine trying to code multiple objects without it.
Thanks
Carpenter Software.
Torque Owner Don Hogan
In thinking about it, I could also see where having this in a behavior could be useful if it gave you the ability to only use portions of the system at a time. I.e. a dumb object that shoots when it sees you, then a smarter one that moves toward you, then one that moves toward you and tries to avoid your shots, etc.
That said, it might start to get pretty difficult to set up that sort of configurable FSM through the behavior interface.
Anyway, I found the threads a good read and wanted to share my reactions. =)