Tricks of the Windows Game Programming Gurus:Making Silicon Think with Artificial Intelligence

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

#### Elementary State Machines

At this point, you should be seeing a lot of overlap in the various AI techniques. For example, the pattern techniques are based on finite state machines at the lowest level which perform the actual motions or effects. What I want to do now is take finite state machines to another level and talk about high-level states that can be implemented with simple conditional logic, randomness, and patterns. In essence, I want to create a virtual brain that directs and dictates to the creature.

To better understand what I’m talking about, let’s take a few behaviors and model them with the aforementioned techniques. On top of these behaviors, we’ll place a master FSM to run the show and set the general direction of events and goals.

Most games are based on conflict. Whether conflict is the main idea of the game or it’s just an underlying theme, the bottom line is that most the time the player is running around destroying the enemies and/or blowing things up. As a result, we can arrive at a few behaviors that a game creature might need to survive given the constant onslaught of the human opponent. Take a look at Figure 12.10, which illustrates the relationships between the following states:

  Master State 1: Attack.
  Master State 2: Retreat.
  Master State 3: Move randomly.
  Master State 4: Stop or pause for a moment.
  Master State 5: Look for something—food, energy, light, dark, other computer-controlled creatures.
  Master State 6: Select a pattern and follow it.

Figure 12.10 Building a better brain.

You should be able to see the difference between these states and the previous examples. These states function at a much higher level, and they definitely contain possible substates or further logic to generate. For example, states 1 and 2 can be accomplished using a deterministic algorithm, while states 3 and 4 are nothing more than a couple of lines of code. On the other hand, state 6 is very complex because it dictates that the creature must be able to perform complex patterns controlled by the Master FSM.

As you can see, your AI is getting fairly sophisticated. State 5 could be yet another deterministic algorithm, or even a mix of deterministic algorithms and preprogrammed search patterns. The point is that you want to model a creature from the top down; that is, first think of how complex you want the AI of the creature to be, and then implement each state and algorithm.

If you refer back to Figure 12.10, you also see that in addition to the Master FSM, which selects the states themselves, there’s another part of the AI model that’s doing the selection. This is similar to the “will” or “agenda” of the creature. There are a number of ways to implement this module, such as random selection, conditional logic, or something else. For now, just know that the states must be selected in an intelligent manner based on the current state of the game.

The following code fragment implements a crude version of the master state machine. The code is only partially functional because a complete AI would take many pages, but the most important structural elements are there. Basically, you fill in all the blanks and details, generalize, and drop it into your code. For now, just assume that the game’s world consists of the AI creature and the player. Here’s the code:

    // these are the master states

    #define STATE_ATTACK  0    // attack the player

    #define STATE_RETREAT 1    // retreat from player

    #define STATE_RANDOM  2    // move randomly

    #define STATE_STOP    3    // stop for a moment

    #define STATE_SEARCH  4    // search for energy

    #define STATE_PATTERN 5    // select a pattern and execute it

    // variables for creature

    int creature_state   = STATE_STOP, // state of creature

        creature_counter = 0,   // used to time states

        creature_x       = 320, // position of creature

        creature_y       = 200,

        creature_dx      = 0,   // current trajectory

        creature_dy      = 0;

    // player variables

    int player_x = 10,

        player_y = 20;

    // main logic for creature

    // process current state

    switch(creature_state)

        {

        case STATE_ATTACK:

              {

              // step 1: move toward player

              if (player_x > creature_x) creature_x++;

              if (player_x < creature_x) creature_x—;

              if (player_y > creature_y) creature_y++;

              if (player_y < creature_y) creature_y—;

              // step 2: try and fire cannon 20% probability

              if ((rand()%5)==1)

                   Fire_Cannon();

           } break;

        case STATE_RETREAT:

               {

            // move away from player

               if (player_x > creature_x) creature_x—;

               if (player_x < creature_x) creature_x++;

               if (player_y > creature_y) creature_y—;

               if (player_y < creature_y) creature_y++;

               } break;

        case STATE_RANDOM:

           {

               // move creature in random direction

               // that was set when this state was entered

               creature_x+=creature_dx;

               creature_y+=creature_dy;

           } break;

        case STATE_STOP:

                {

                // do nothing!

                } break;

        case STATE_SEARCH:

                {

                // pick an object to search for such as

                // an energy pellet and then track it similar

                // to the player

                if (energy_x > creature_x) creature_x—;

                if (energy_x < creature_x) creature_x++;

                if (energy_y > creature_y) creature_y—;

                if (energy_y < creature_y) creature_y++;

                } break;

        case STATE_PATTERN:

                {

                // continue processing pattern

                Process_Pattern();

                } break;

        default: break;

        } // end switch

    // update state counter and test if a state transition is

    // in order

    if (--creature_counter <= 0)

        {

        // pick a new state, use logic, random, script etc.

        // for now just random

        creature_state = rand()%6;

        // now depending on the state, we might need some

        // setup...

        if (creature_state == STATE_RANDOM)

            {

            // set up random trajectory

            creature_dx = -4+rand()%8;

            creature_dy = -4+rand()%8;

            } // end if

        // perform setups on other states if needed

        // set time to perform state, use appropriate method...

        // at 30 fps, 1 to 5 seconds for the state

        creature_counter = 30 + 30*rand()5;

        } // end if

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.