260 likes | 406 Vues
This lecture explores decision-making techniques in AI, focusing on decision trees and finite state machines (FSM). It introduces the concept of decision trees, which consist of simple, binary decisions leading to actions, and emphasizes their straightforward implementation. The lecture also delves into FSMs, detailing how states and transitions can manage complex behaviors in characters. By discussing advantages, such as ease of debugging and clarity in structure, as well as potential drawbacks like complexity growth, the lecture provides valuable insights into AI's decision-making processes for games.
E N D
Lecture 22 – Decision Making CS 490/590 Wesley Kerr
Acknowledgements • Ian Millington. Artificial Intelligence for Games. Morgan Kaufman Publishers. 2006 • images and organization • Mat Buckland. Programming Game AI By Example. Jones & Bartlett Publishers. 2004
AI Model AI gets information AI gets a slice of processor time AI turned into on-screen action
Decision Making Internal Changes Internal Knowledge Decision Maker Action Request External Knowledge External Changes
Decision Trees Security Guard • Fast, simple, easy to implement, easy to understand • Arguably the simplest technique we will look at • Doesn’t mean that you can’t achieve realistic AI with it • Idea • A tree of connected decision points • Starting decision is the root of the tree • Each decision leads down a path grounding out in the leaves of the tree which are actions sleeping? true false noise? idle? false true true false sleep patrol perform stir
Key Points • Decisions are simple • Decisions do not contain complex boolean logic • Types of tests • boolean (the value is true or false) • enumeration (the value is one of the set) • numeric (the value is within some range of values) • 3D vector (the vector is within some length) if (path clear AND no chasm) then go forward if (path blocked OR chasm ahead) then turn around
Complexity (for binary decision tree) • Time to reach action • Balanced tree • O(log n) • Not necessarily always the case • Try to keep most common path higher up in the tree
Interesting Ideas • Reusing nodes in the decision tree (merging) • Simply reconnect the decision node to another point in the tree • Be careful not to create loops in your tree • Loops result in infinite loops • Random decisions
State Machines • Character occupies a single state • Normally a set of actions/behaviors are associated with a state • States are connected by transitions • Each transition has a set of conditions
Pseudocode class FSM // maps from a state to the list of transitions leaving it transitionMap currentState // the current state of the FSM startState // the state that the FSM always starts in public void addState(State s) // add a state to the FSM public void addTransition(State from, State to, Transition t) public void update() { // update the active state // test all of the transitions from the active state // if a transition is active // then // call exitState() on the active state // call enterState() the endState of the transition // set the active state to be the end state of the transition
Hardcoded FSM class GuardFSM : enum State : PATROL, DEFEND, SLEEP // holds the current state of the FSM current-state = SLEEP function update(elapsed): // check for transitions if (current-state == PATROL) : if (canSeePlayer()) : current-state = DEFEND if (tired()) : current-state = SLEEP elseif (current-state == DEFEND) : if ( not canSeePlayer() ) : current-state = PATROL elseif (current-state == SLEEP) : if ( not tired() ) : current-state = PATROL function receive-sound-event(event) : if (current-state == SLEEP and loud(event)) : current-state = DEFEND function get-action(): if (current-state == PATROL) : return patrol-action if (current-state == DEFEND) : return defend-action if (current-state == SLEEP) : return sleep-action
FSM Benefits • Easy to write • Conveniently breaks down the challenges into manageable chunks • Additions are made by adding more transitions and states • Easy to picture • Easy to implement • Straightforward to debug • Deterministic – makes replication easier • Visual debugging – rendering the current state to the screen • Offline debugging – record all state transitions to a file • Applicable to a variety of situations • Menu system • Character AI
FSM Cons • When time is shortened you can easily short circuit the system • Adding in additional “switch” and “case” methods instead of proper transitions • Can grow to be very complex • The number of transitions tends to grow exponentially with the number of states • State oscillation
Walkthrough • State machine composed of layers • Transitions that occur in layers higher up, have precedence • Slightly modified version of the FSM code presented earlier. • Each enterState, exitState, update, and transition method returns a single action • For each update of the HFSM we have a list of actions to perform
1. Start in State L 2. Transition from H* A return: update-L, enter-A state: [L,A] 3. Transition 1 trace: top-level – no transitions active-state (L) – 1 fires return: exit-A, 1-actions, enter-B, update-L state: [L,B] 4. Transition 4 trace: top-level – 4 fires active-state (L) – ignored return: exit-L, 4-actions, enter-M state: [M] 7. Transition 3 trace: top-level – no transitions active-state (L) – 3 fires special case Level 1 Level 0 pass the transition up to parent unfinished return: exit-B, exit-L, 3-actions, enter-N state: [N] 5. Transition 5 trace: top-level – 5 fires return: exit-M, 5-actions, enter-N state: [N] 8. Transition 7 return: exit-N, 7-actions, enter-M state: [M] 6. Transition 6 trace: top-level – 6 fires return: exit-N, 6-actions, enter-L state: [L,B] 9. Transition 2 special case Level 0 Level 1 return: exit-M, enter-C, enter-L, 2-actions state: [L,C]
public class HeirarchicalStateMachineextends HSMBase { _states; // a list of the states stored at this level _currentState; _initialState; function getStates() if (_currentState != null) return _currentState.getStates(); else return []; function update() if (_currentState == null) _currentState = _initialState; return _currentState.getEntryAction(); // check the transitions in the current state triggeredTransition = NONE for (transition in _currentState.getTransitions()) if (transition.isTriggered()) triggeredTransition = transition break; // if we have found an active transition if (triggeredTransition != NONE) result = UpdateResult() result.actions = [] result.transition = triggeredTransition result.level = triggeredTransition.getLevel() else // pass it on down result = _currentState.update() . . . To be continued
public class HeirarchicalStateMachineextends HSMBase { _currentState; . . . function update() . . . // variable result contains transition information if (result.transition) // decide what to do based on the level if (result.level = 0) // transition internal to this machine. Handle it now. targetState = result.transition.getTargetState() result.actions += _currentState.getExitAction() result.actions += result.transition.getAction() result.actions += targetState.getEntryAction() _currentState = targetState // this may be an instance of a state, so add our action result.actions += getAction() result.transition = NONE else if (result.level > 0) // destined for a higher level, so we exit our state result.actions += _currentState.getExitAction() _currentState = null result.level -= 1 else // the transition needs to be passed down targetState = result.transition.getTargetState() targetMachine = targetState.parent result.actions += result.transition.getAction() result.actions += targetMachine.updateDown( targetState, -result.level) result.transition = NONE else result.action += getAction() return result
publicclass HeirarchicalStateMachineextendsHSMBase { _currentState; . . . function updateDown(state, level) // if not at a top level, continue recursing if (level > 0) // pass ourselves off as the transition state actions = parent.updateDown(this, level-1) else actions = [] if (_currentState) actions += _currentState.getExitAction() currentState = state actions += state.getEntryAction() return actions
Other authors actually call this state blittingIf there are relatively few emergency transitions then have the FSM remember on transitions where it came from