Skip to content

Game State

As mentioned earlier, the Game holds all the relevant state for the game.

Phase and PhaseCycle

One peculiarity of Mafia games is that they usually proceed in "phases", such as a "day - night" cycle. Sometimes games use more exotic phase structures, such as "morning - day - evening - night", or include abilities that skip phases.

AbstractPhaseSystem defines an abstract interface for these phase structures. All will have a "startup" phase (for pre-game stuff) and a "shutdown" phase, for when the game has ended. SimplePhaseCycle has a "startup" phase, followed by endless cyclical phases (defaults to "day" and "night"), exiting into a "shutdown" phase.

Each Phase has a name that identifies it (e. g. "day" or "night 3") and an ActionResolutionType (which is "instant" or "end_of_phase").

If ActionResolutionType.instant, which is the default for "day" phases, then all actions in the base queue (game.action_queue) are immediately executed. This corresponds to the usual "day action" activity: if you vote, your vote is immediately counted; if you kill someone in broad daylight, the effect is immediate.

If ActionResolutionType.end_of_phase, which is the default for "night" phases, then all actions in the base queue are accumulated, then executed right before the phase ends. This corresponds to the usual "night action" activity: actions happen in priority order, irrespective of what time they were actually submitted.

Factions

The Faction class represents a particular "team"/"faction". It has a name (for example, "town" or "mafia") and some members (Faction.actors).

Each Faction also has OutcomeCheckers (to see who wins/loses), described later in the tutorial.

Actors

The Actor class represents a player character (or NPC). Each actor has a name, one (or rarely more) factions, some number of abilities, and a status.

Abilities and Triggers

An Ability is, broadly speaking, a thing that allows some sort of Action, where the player has active control over when the ability is used. An Ability responds to EActivate events by creating an Action with the passed parameters.

A Trigger, often called a "passive ability", automatically responds to events. For example, an "Unkillable" passive ability can be implemented as a Trigger that nullifies all kill actions against the owner.

Ability and Trigger instances can have Constraints attached to them, which prevent the creation of Actions depending on some external or internal factors.

More information is available in the Abilities guide.

Status

Each Actor has a free-form Status object, which acts like a DefaultDict[str, Any] with a default value of None. Whenever an attribute is changed, the Status object emits an EStatusChange event, which is useful for tracking (or even undoing!) changes to status.

Auxiliary Objects

The above objects can't cover all scenarios, so the engine also supports arbitrary AuxObjects to be added to the Game. This is handled by the AuxHelper class, available as game.aux. Each AuxObject is a Subscriber with a particular key that should be unique.

A typical AuxObject is a Tally, such as a LynchTally, which tracks who the majority of players are voting for/want to eliminate.

Another useful aux object is the GameEnder, which ends the game (moves to the "shutdown" phase) when all Factions have achieved an Outcome.

Another important use for aux objects is to read out in-game events to an external source, e.g. hooks for internal events to output to external systems.

Yet another use is to create self-deleting or self-resetting temporary objects, such as for temporary (single-phase) protection or blocking abilities. Some examples are TempPhaseAux and CounterPerPhaseAux.