Hi!
While TADS is object-oriented, Dialog is perhaps better described as aspect-oriented. You can still break up complexity, but you do it by keeping related rules together in the source code, rather than by putting code inside objects or classes.
NPCs are typically animated using (on every tick)
. But of course, putting all of your NPC antics inside the same rule would quickly become unreadable. So, keeping the aspects separate, you’d use one (on every tick)
rule for every NPC, located close to the NPC definition in the source code.
Furthermore, the library exhausts (on every tick)
. Like this:
(exhaust) *(on every tick)
This means that if you leave any choice points around, Dialog will come back and run them—essentially running every possible branch of the code after each move. In practice, you’d often want to limit this to a single action per NPC per tick. Thus:
%% This section contains everything related to Alice.
#alice
(name *) Alice
(female *)
(proper *)
...
(on every tick)
%% Here we do a normal query rather than a multi-query.
%% This will ensure that Alice does, in fact, only do one thing per tick.
(alice does one thing)
(alice does one thing)
~(alice has delivered the lollipop)
(* is in room $AliceRoom)
(current room $PlayerRoom)
(if) ~($AliceRoom = $PlayerRoom) (then)
(first step from $AliceRoom to $PlayerRoom is $Dir)
(let * go $Dir)
(else)
(par)
Alice hands you a blue lollipop.
(now) (#lollipop is #heldby #player)
(now) (alice has delivered the lollipop)
(endif)
(alice does one thing)
(player can see *)
(par)
Alice inspects a speck on the wall.
In the above example, Alice can be said to be in one of two states, depending on the value of the global flag (alice has delivered the lollipop)
. If the first (alice does one thing)
rule succeeds, for instance because she hasn’t delivered the lollipop yet, then the second rule never executes. But if the first rule fails (for whatever reason—it could be because the lollipop has been delivered or because there is no path from Alice to the player), then the second rule executes which prints a message if Alice is within sight.
The term “actor state” is perhaps not the best way to describe what is going on here. It’s more apt to say that the story has a state (the global flag) that the actor is affected by. Now, in a game with lots and lots of actors with similar behaviour, it can make sense to model their state using per-object flags or per-object variables. But the quintessential Dialog way is to think of state as a property of the story, and thus to model it with a global flag or variable.
Some of this is also covered by the NPC chapter in the manual.