This guide covers the engine architecture in detail, describing entities and showing major event flows.
The service controller player and non-player characters. Unrelated to the actor model.
Behavioral actors are controlled by the computer - NPCs.
Actors can carry items in their inventory. There is currently no inventory limit.
Actors can equip items from their inventory into specific slots. The weapon-*
slots are used to attack, for example.
Only items with a corresponding slot can be equipped, limited what some actors can use (animals may have slots for claws
and teeth instead of hands).
Configuring the engine.
The player's input lines are parsed into commands for the actor to execute. NPC AI generates input commands directly.
Commands are built by splitting input on whitespace, removing articles (a, an, the, etc) and other filler words, and assuming the verb and target are in the correct order. Some validation is done when invoking commands, but the parsing is very simple.
There are common verbs built into the engine for actions such as:
drop
an itemhit
an enemylook
at an entitymove
to another roomtake
an itemuse
an itemwait
the turn
There are some meta commands that are handled by the state service, rather than actor scripts.
create
- create a new world from the template
debug
- print the world state to output
graph
- print the world state to path in graphviz format
help
- list common and meta commands
load
- load the world state from a path
save
- save the world state to a path
quit
World entities may define their own contextual verbs, which can be invoked normally through input.
TODO: explain actors
TODO: explain items
TODO: explain portals
TODO: explain rooms
The entire engine is event-driven, with intentionally little direct coupling between services. Some operations are too trivial to bus, like translating a string, but any significant change to game state should be sent as an event.
When the player sends a create
command, generate a new world and inform the actor service, which will automatically
join the loaded world.
create
command, generate a new world and inform the actor service, which will automatically
join the loaded world.
When the player sends a load
command, the path is passed on to the loader, which responds with the loaded state and
triggers the auto-join sequence (shown in the create event flow).
load
command, the path is passed on to the loader, which responds with the loaded state and
triggers the auto-join sequence (shown in the create event flow).
When the player submits a world command, it is parsed into commands and triggers a state step, processed locally.
When the client is connected to a remote state service, with a corresponding remote actor on the server-side, the
command flow is similar but extended. Notably, localization occurs on the client-side after output has been returned,
one reason for having actor services on both sides.
Modules are dependency injection groups, binding a related set of services.
Provides:
browser-fetch-loader
browser-local-loader
browser-page-loader
browser-dom-render
Binds:
LocalCounter
NodeEventBus
NextLocale
YamlParser
AleaRandom
LocalScript
ChainTemplate
WordTokenizer
Provides:
core-behavior-actor
core-player-actor
core-local-state
core-compromise-tokenizer
core-split-tokenizer
Provides:
node-file-loader
node-fetch-loader
node-ink-render
node-line-render
Please see the services doc for details on what each service does. The list is too long to include here.
Events in the world are processed by scripts attached to the entity performing the action. Scripts may be invoked on a single target entity or broadcast to an entire room, and take a context with field for some (optional) primitive data.
The entity on which the script is being invoked. Always a world entity.
A context is prepared whenever a script is invoked, with the target (entity upon which the script has been invoked), any data that was provided, and some helpers that provide safe ways to mutate the game state.
The context contains a data field, suitable for passing in non-nested numbers and strings.
TODO: support custom template data for scripts
Signals are named events on an entity, linked to (named) scripts.
Verbs are custom commands, which invoke a slot with some additional data.