Finite State Machine Quest Tracking

From Infinite Worlds
Jump to navigation Jump to search

Information icon.svg Player Guide

This page is a player-created guide. Information may reflect personal opinions or playstyles; instruction snippets are examples only. See all guides for more advice.

This is an approach for managing the evolution of a storyline (such as a "quest" or mission, though not necessarily limited to these) using a tracked item and a number of triggers. Whilst not necessary for an AI to manage a plotline, this can provide much more structure and possibly better pacing.

What is a Finite State Machine?[edit]

A Finite State Machine is a model which has a finite number of states, and transitions between those states - easily visualisable as a directed graph.

For example, a state machine for a simple plotline:

  • Intro state - can transition to the "quest active" state
  • Quest active - can transition to either the "complete" or "failed" states
  • Complete - no transitions
  • Failed - no transitions

This is a very linear plotline with only one branch (the quest can either be completed or failed). More complex examples might have multiple branches or even loops, allowing one to return to a prior state. For very complex scenarios, it may be easier to implement them as multiple different state machines rather than having a state for every possible combination of events.

Implementing an FSM as a Tracked Item[edit]

We can use a tracked item to represent our state. Each state must have a tracked item value - either a numerical index, or a unique word or phrase. Set the tracked item's initial value to the "entry" state, and provide update instructions for the AI which reflect any of the possible transitions from this state.

For example:

Update to "QUEST ACTIVE" when I accept or begin the quest. NEVER update to any value other than "INTRO" or "QUEST ACTIVE"

Note: Whilst the exact same functionality can be achieved using a collection of situation triggers (triggers which fire when a certain situation occurs, as determined by the AI), using a tracked item to track the state makes implementation easier and less prone to errors, and allows us to avoid using any situations (which are currently limited in number to 10), as well as presenting only those which are relevant at any given point in time to the AI (providing a slight cost saving, and giving it less to think about).

Triggers as Transitions[edit]

For each transition, we must create a trigger. Rather than using a traditional situation trigger, this trigger should be set to fire when the tracked reflects a particular state. Essentially, the tracked item's update instructions replace the situation - the AI will evaluate whether the state should change this turn and, if so, it updates the tracked item, which in turn causes the trigger to fire. If the state can be revisited once left, set this trigger to be able to trigger multiple times. The entry state can be omitted if it cannot be revisited (we can set the state to the entry state as the default).

In the above example, the transition from "INTRO" to "QUEST ACTIVE" would require a trigger which will be set to fire when the tracked item's value is exactly "QUEST ACTIVE".

These triggers should then update the tracked item in turn, replacing the update instructions with the next set of transitions. In our example, we would tell the AI when and how to move to "COMPLETED" or "FAILED" as these are the only two transitions available to us now (the INTRO state is forgotten - it cannot be revisited).

Using the tracked item in this way avoids the need to use situation triggers - effectively, the tracked item is the situation.

Finally, if we have reached an ending state and can never return to any other state, the transition trigger can hide the tracked item from the AI, efectively removing it from the game.

Adding an Extra Instruction Block[edit]

We can store all the information we need about the quest in the tracked item's update instructions. However we may prefer to set an [instruction block] too, in the triggers which update the tracked item.

Using YAML for the Instructions[edit]

We can extend this idea further, potentially avoiding the need for many or even all of our triggers! Instead, the different states could be stored in another YAML tracked item, and then selected using PawScript. For example:

INTRO: "Update to 'QUEST_ACTIVE' when I accept or begin the quest. NEVER update to any value other than 'INTRO' or 'QUEST ACTIVE'"
QUEST_ACTIVE: "Update to 'COMPLETE' when I complete the quest. Update to 'FAILED' if I fail the quest. NEVER update to any value other than 'COMPLETE' or 'FAILED'"

We can then use an expression in our update instructions - this could be as simple as

<<try($quest_info.item($quest_state), "")>>

Indeed, it would be possible to genericise this whole system - but that remains outside the scope of this wiki page!