State system

37 views
Skip to first unread message

Griatch

unread,
May 1, 2009, 11:32:00 AM5/1/09
to Evennia

Ok, so I have a state system coded for Evennia. I commited it for
review (rev 617), it's all in one commit so should be easy to revert
away if there's no interest in it.

So what is a state system? Basically it allows the engine to shift a
player object (only) into a "state" where only a certain set of
commands are available. The player stays in this state either until
they exit by choice or the system throws them out. A state is sort of
an application or game within the game, where a completely different
set of rules and choices can apply.

Examples of uses:
- In-game line text editor
- All sorts of menus, like
- NPC conversation dialogues
- Options
- Character creation (no need to give long commands, just pick
options)
- Special 'combat state-only' commands
- etc.

Technically I implemented this as stand-alone as possible from the
rest of Evennia, by use of a new StateTable class in src/statetable.py
that intantiates a GLOBAL_STATE_TABLE object. The only other changes
were a variable on the Object class and an if statement in
cmdhandler.

The GLOBAL_STATE_TABLE is essentially a dict of command tables, keyed
by the name of the state they belong to (like 'menu', 'combat' or
whatever). The class works the same way as the pluggable command
system works; you define your commands as normal in gamesrc/commands
except you use GLOBAL_STATE_TABLE.add_command() instead of
GLOBAL_CMD_TABLE.add_command().
This add_command function looks similar to the cmd_table one, with the
main difference that you must also specify which state the command
belongs to. It also takes a few more flags related to adding
auto_help.

Auto_help creates a separate dynamic help index for the state (non-db-
based) to properly isolate the user and only show help on the commands
available in the state. Full auto-help markup as normal is supported.
If you set the 'global_help' flag in the call to add_command the
system auto-adds the help also to the normal persistent help index
(this could be useful for complex states which people might want to
read up on before actually entering).

Every state created has by default two commands @exit and help defined
them in order to escape the state and read help files respectively.
They can be omitted by flags to add_command.

To make the game aware what state each player is, a single variable
named 'state' was added to the main Object model as well as a few
access functions get_state(), set_state() and clear_state(). Default
state is None. It should be noted that this is NOT intended to be a
persistent thing (so there's no new Fields in the database) -- a state
is supposed to be a *temporary* break-away from the normal gameplay.

The final tweak is a small addition to the cmdhandler that checks the
player object to see if it is in a special state and if such a state
has been defined in GLOBAL_STATE_TABLE; in which case it replaces the
lookup in the normal global command table with a lookup in the state-
specific command table. I also let the idle and the channel command
check stay, I figured it would be annoying if people could suddenly
not talk in channels just because they had entered a state.

I made an example menu in gamesrc/commands/examples/state_example.py.
It was quite intuitive to code if you have used the pluggable command
system before.

It seems to be working here, but you never know of course, so comments
would good.
.
Griatch (Starkiel)

Griatch

unread,
May 2, 2009, 10:44:57 AM5/2/09
to Evennia
Testing out the functionality of the state system ... fixed some minor
bugs along the way. :-)

Text editor: It was very simple to implement a fully functional
attribute text editor using the state system; just a bunch of commands
and a temporary buffer attribute saved on the player to hold the work
until the player chooses to actually save it. Since the attributes do
not handle line breaks, its usability is somewhat limited at this
point, but it's kinda neat to edit and replace text with it.

I went on to create a talkative NPC parent class with a npc that talks
back to you. This was more tricky. While it works fine to have a
command on the npc that puts the player into a talk-state, it is
difficult to properly store the position in a nested menu tree.
A nested menu tree can be made quite simplistic as far as the state
system goes (for example a menu that always give you only options
numbered 1-5 only need one state with those five commands made
available). But one has to store the state between each command (so we
know where either of those five choices lead at every point in the
menu tree). It quickly becomes cumbersome to store the menu state
between commands since the Attribute class only handles strings.

... So I'm holding off with this until the Attribute class get updated
to handle lists and dicts (or even better, pickles); once that's been
done it will be quite simple to set up a generic menu class that
parent scripts can just import and instantiate, and which handles all
the state information transparently. Also the text editor could hold a
list of lines this way.
.
Griatch (Starkiel)
Reply all
Reply to author
Forward
0 new messages