Sim Polis

← Back


AI

Agents need an AI script for decision making; put simply it tells them what to do next. Sim Polis aims to provide a “one size fits all” approach to AI agents using Behaviour Trees.

The design of Sim Polis revolves around flexible systems that are evolving with player interaction, and the AI as such needs to be adaptable to the “open world assumption” (meaning, anything is possible.) It’s not enough to have an apple merchant show up in the town square every morning expecting to sell his apples, if due to player interaction apples are now widely believed to be poisonous by the townspeople or the town square has been overrun by zombies. Better than not showing up at all, the apple merchant should show up in the town square, they should realise that something is wrong and then they should start to panic. Flexibility like this is challenging enough, but we also need a structure accessible enough that players can create and share these this scripts themselves via the interface. Thankfully both of these vectors favour a modular approach to AI: when the apple merchant needs to panic, they can discover a “panic module”, which they can be designed and executed in relative isolation to everyday merchant behaviour.

Behaviour Trees are essentially flowcharts that direct the decisions to be made and the actions taken by an agent. A simple behaviour tree might instruct an agent to eat if it is hungry:

A flowchart displays a control node, 'hungry?'. One branch (yes) feeds into the action node, 'eat'. A second branch (no) feeds into another control node, labelled '...' to illustrate that in this case the tree continues

The tree here begins with the control node “is the agent hungry?”. If the agent is hungry, it would execute the action node: “eat something”. If the agent is not hungry, it would follow the other side of the tree. The result is that hunger is prioritised. If the agent is not hungry, then the flow continues. We can imagine a situation where (relieved of hunger) the agent is free to subsequently pursue a more whimsical chain of behaviours:

In a second example, the flowchart leads through two action nodes; wander and shout. These nodes are followed by a new type of node, a mutate node, which is labelled 'destroy branch'. Finally we have a control node signifying that the tree continues

In the example above the agent will wander, and then shout. This branch of the tree finishes with a forget node, a special kind of control node for permanently modifying the behaviour tree itself. Execution of this node will destroy the wander-shout sub-branch, since the behaviour should be executed once - it was intended to be whimsical; a moment of madness. It also demonstrates that behaviour trees are modular; we can imagine the wander-shout branch being sufficient to define the entire behaviour tree of a raving lunatic, but for another agent we could plug in the same branch as just one aspect of their behaviour:

In this example both previous examples are pulled together. There is a condition, 'drunk?' which triggers the wander, shout and forget nodes, rendered smaller to indicate that they are a module that has been imported. This branch leads into a new behaviour, labelled 'learn'. If the agent is not drunk then the chart flows into the hunger tree from the first example, also imported

If the agent is drunk, they wander, shout and forget, before executing a new node, “learn”. If the player is not drunk, the chart moves on to the hunger condition from the first example. We can see here how the behaviours wander-shout-forget, and hunger-eat, have been packaged into branches. Once packaged, they can be re-used by their creator in the behaviour trees of different agents, and published online with some metadata about what the branch does. Once published online other players can import the behaviour into their own agents, which is already a powerful mechanism for building a games commons. Further from this we have the “learn” node, which with the right metadata, can use search parameters for the agent to discover a new drunken behaviour online from the games commons. The next time this tree executes and the agent is still drunk, he will have forgotten the wander-shout behaviour but may discover a behaviour someone has published on the games commons that causes him to fall over and begin singing.

Node Types

Sim Polis is data-driven and Behaviour Trees are no different. If you are reading because you want to create and edit your own behaviour trees, note that you can do this directly in the game interface:

The Heads Up Display of Sim Polis, showing the portrait of a humanoid Fox and a number of tabs for the basic information, inventory and behaviours of the Fox. The selected tab shows a grid with a number of branching nodes, the AI behaviour script for the character

The interface is very much a work-in-progress.

Action Nodes

The action node is used when the agent is instructed to try and do something. It may fail to slay the dragon, but your AI script has instructed it to try. The node is an Action, which will have its’ own guide.

Condition Nodes

A condition is a question: “Should I slay the dragon? Am I brave enough? Do I have a sword? Do I think it deserves it?”

Control Nodes

Condition and Action nodes will fail if the condition isn’t met, and so they can be used to change the decision-making flow of an agent when they are combined with Control nodes, basically, nodes which organise their children into a plan-of-action:

  • A selector branch will try each child and will stop when one succeeds.
  • A sequence branch will try each child in turn and will stop when one fails.

A sequence with a node that fails will not complete the actions and any further conditions that exist after it.

Some special control nodes also exist to change the behvaiour of the tree more directly:

  • A change node is like a link to another tree; it’s there to change which tree is running via urlid.
  • A forget node is used to destroy a sub-branch in the tree. Typically it will destroy its’ own sub-branch and is used for temporary behaviour, like a one-off dialogue script.

The following control branches are TODO:

  • mutate: Transform the active behaviour tree itself, permanently modifying behaviour.
  • parallel: Execute multiple children simultaneously
  • sort: Change the order of children before executing the next one in a sequence
  • lotto, repeat, retry: Actions inspired by https://github.com/nikkorn/mistreevous