Curveship

Curveship-py
Reference:
Major Terms & Ideas

Familiarity with narrative theory and interactive fiction is very helpful for understanding the way Curveship-py works. Below, I have defined some of the major terms and explained some of the major ideas that underlie the system. This explains some of the ways in which Curveship-py differs from other state-of-the art IF systems.

To create a new fiction, an author will mainly define an Items list, along with necessary subclasses. The Items list specifies an arrangement of Items (a tree) in a simulated World. Initial Actions and a spin can also be specified. If a description is supposed to be produced initially, the best way to do that (so that changes in spin can apply to everything) is not to type in the text that is supposed to be produced, but to define a Sense Action in the initial Action list and have that apply to a Room.

World & Concept // Curveship-py

World. The main, simulated interactive fiction world, which defines the “reality” within which all of the characters live, is called the World in Curveship-py. Any interactive fiction will model a world—that’s one of the main things that distinguishes interactive fiction from hypertexts, conversational characters, and other digital media productions.

Concept. A Concept is a particular Actor’s theory of the actual world, based on knowledge (put into a fiction file to begin with) and perceptions (gained as the Actor moves around and looks at things). Concepts are almost never complete, and they may be wrong. They allow the telling of Actions and the description of Items to be focalized, that is, based on what a particular Actor knows and sees.

What Exists: Items // Curveship-py

Item. Basically, this is any physical object that has a representation in the simulation. In other contexts these are called “objects,” but that term means something different in object-oriented programming. I could have called these “existents,” the term Seymour Chatman and other narratologists use, and that is indeed the way these are referred to in Curveship-js, because that system has narrative theory education as part of its purpose. But Items in Curveship-py are called “Items.” They must be in one of four categories, so that they are either Actors, Doors, Rooms, or Things.

Actor. An Item that can act on its own, due to either code that an IF author has written or a script the author has dropped in. Any Item can react (that is, any Item can have its own react method defined) but only an Actor can initiate an Action (that it, only an Actor can have an act method). Each Actor has a Concept; when an Actor acts, the Action is put together using this Concept. The player character is a Actor. Although particular fictions may allow or disallow this, any Actor has the potential to be commanded and focalized, becoming the player character.

Door. A door, passageway, or other portal that connects exactly two Rooms. Doors, like Rooms, are all on the first level of the Item tree, directly below Cosmos. Therefore, they are not children of either Room which they connect, although they are among the Items that can be seen and accessed from both Rooms. A door is in many respects like a Room that one can only go through, not remain in.

Room. A discrete location which can have exits leading to other Rooms or to doors. Rooms are all on the first level of the Item tree, directly below Cosmos.

Thing. This is typically an Item that is not a location and is more or less inert. Any Item that isn’t a Room and doesn’t need to act or have its own a Concept is a thing. Things can react when something is done to them or done in the same Room, so that pressing a switch on a lamp can cause the lamp to react by increasing its glow.

Substance. A Substance is something like a powder or liquid that can be poured into a vessel but can’t really be carried around otherwise. Sources provide an endless supply of Substances; vessels are used to contain them. Adventure in Style provides an example of the implementation of two Substances, water and oil. It’s not necessary to define any of the particular amounts of a Substance as Items; after defining an overall Substance Item and designating other Items as sources or vessels, the rest is done during setup.

Cosmos. The special Actor that is the root of the Item tree is the Cosmos. This Item is responsible for earthquakes, power outages, and any occurrence where the author doesn’t want to model the cause as its own Actor. The Cosmos can also change the spin, which allows for a connection between the simulated world and the way the telling of this world is done.

Item Tree. A structure representing all of the Items in the world (or in a Concept) and the relationship between them, expressed as links. It is a graph with a designated node (Cosmos), directed links from parent to child, and no loops—that is, no Item is its own descendant. Since it satisfies these properties, it is a tree.

Parent-Child Relationship. The relationship between an Item and an Item a level under it, and connected by a link, in the tree. When an Actor walks into a Room, he or she becomes the child of the Room. If the Room moves (perhaps it’s an elevator) the Actor will move with it. If the lights in the Room become brighter, the Actor and everything else in the Room will be better illuminated. An apple placed in a sack similarly becomes the child of the sack and, for instance, is stolen if the sack is stolen.

Typing world tree immediately after starting Cloak of Darkness shows all of the Items in this tiny simulated world and described how they are arranged:

@cosmos: nature []
    @bar: bar [of]
        @message: message [part_of]
    @cloakroom: cloakroom [of]
        @hook: hook [part_of]
    @foyer: foyer [of]
        @person: operagoer [in]
            @cloak: cloak [on]

Typing concept @person tree shows the operagoer’s Concept, which contains only those Items that this player character, the only Actor in this simple fiction, knows about:

@cosmos: nature []
    @foyer: foyer [of]
        @person: operagoer [in]
            @cloak: cloak [on]

In this case, it is a simple subset (or subtree), but Actors can also be loaded with knowledge about the world that is incorrect. To see the Item tree change, type “remove cloak” and then check either the world’s or the operagoer’s Concept’s Item tree again. The cloak will be “of” the person (indicating possession) rather than “on” the person (indicating a garment being worn).

What Happens: Actions // Curveship-py

Action. A specific, usually intentional Action taken by an Actor. A command (such as “get lamp”) usually corresponds to a single Action. An Action can succeed, be refused by the Actor, or fail. Authors can easily make up new Actions. The representation of Actions is the basis of narrative. There are four categories of Actions: Behave, Configure, Modify, and Sense.

Behave. An Action which has no direct effect on the world, but which an Item may react to and which may be narrated. For instance, if an Actor waves, this would most straightforwardly be represented with a behave Action.

Configure. An Action that changes the position of an Item in the Item tree and/or changes its relationship with its parent. So, wearing a cloak that one is holding is a configure Action; so it taking a lamp.

Modify. An Action that changes the state of an Item. For instance, an Actor may turn on a lamp or open a door; those Actions are best represented as modify Actions.

Sense. Apprehending an Item with a particular sense (usually sight) is represented by a sense Action. By itself, this does not change the Item tree (which is only changed by configure) or change any state of any Item (which is only changed by modify).

Successful Actions, Failure & Refusal // Curveship-py

Successful Action. Actions have preconditions and may have a postcondition, indicating that something changes in the world as a result of this Action happening. After an Action succeeds, it can be viewed using the world actions debugging directive and will be displayed like this:

/ / / has_feature @grate open
/ / / modify_to_different @grate open True
/ / / has_value @grate open False
/ / / can_access_direct @adventurer ['@grate']
/ / / has_value @grate locked False
:19: OPEN (modify) agent=@adventurer direct=@grate force=0.2 feature=open
 old_value=False new_value=True cause="OPEN_UP @grate" start=18
\ \ \ has_value @grate open True

This is Action 19, an OPEN Action (that is its the verb) which is of the modify type. Specifically, it an Action undertaken by the adventurer (agent=@adventurer) on the grate (direct=@grate) to change its “open” feature from False to True. Actions can be caused by act methods (representing the decisions to act made autonomously by Actors), and by react methods (representing quick responses that any Item can produce), and by being entailed by other Actions, but the cause of this one is a command that was typed in and understood as "OPEN_UP @grate". The amount of force used is the default; the Action starts at tick 18 of the World’s clock.

There are five preconditions, indicated by the “/ / /” lines. In order, they state that the grate has to have the open feature (it has to be an openable Item), that this has to be an attempt to modify its open feature to a different value (so that trying to open an already-open grate will fail), that the open feature is False to begin with (meaning that the grate is closed to begin with), that the adventurer has access to the grate, and that the grate is not locked. If the grate didn’t have the locked feature—if it were an openable Item that was not lockable—the system wouldn’t add this last precondition. The second and third preconditions turn out to be redundant in this case and whenever the feature is True/False or otherwise two-valued. It would be nice to fix this, but except for a tiny bit of time spent checking it, there is no harm to having the extra precondition there.

The one postcondition, indicated by "\ \ \", is that the grate’s open feature has a new value, True. That is, after the Action has completed, the grate is open.

Failure. An Action fails either because some precondition is not met or because some Item in the vicinity prevents it from succeeding. For instance, “open the grate” fails if the grate is already open. A message is produced: “You are unable to open the grate because the grate is open to begin with.” And inspecting the Action by typing world actions shows that preconditions 2 and 3 fail and that the postcondition does not obtain:

/ / / has_feature @grate open
#####> modify_to_different @grate open True
#####> has_value @grate open False
/ / / can_access_direct @adventurer ['@grate']
/ / / has_value @grate locked False
:20: Failed OPEN (modify) agent=@adventurer direct=@grate force=0.2 feature=open
 old_value=False new_value=True cause="OPEN_UP @grate" start=19
 ##### has_value @grate open True

Even if the grate were closed, the Action would fail if some guardian was in the area and (by means of the appropriate prevent method) prevented any gate-opening Actions.

Refusal. An Action is refused by the player character under a small number of pre-defined circumstances. Namely, if a player types a command to go in a certain direction (for instance, "go east") and there is no obvious exit in that direction, the Actor will refuse. Beyond this, an Actor may have special cases for refusal defined and associated with its “refuses” keyword. In the Curveship-py version of Cloak of Darkness, the operagoer refuses to drop the cloak anywhere, although it can be hung on the hook in the cloakroom. This produces the message “You decide not to set the cloak down because the floor is not the best place to leave a smart cloak lying around.” Typing world actions shows this representation of the refusal:

:3: Refused DROP (configure) agent=@person direct=@cloak force=0.2 new_link=in
 new_parent=@foyer cause="DROP @cloak" start=2
 ##### parent_is @cloak in @foyer

Unlike a failure, a refusal doesn’t really represent represent any physical action happening in the simulated world. In a failed attempt to open the grate, the agent probably is exerting some energy and moving around. Something else may happen as a consequence. (In Cloak of Darkness, the message is unintentionally rewritten by the operagoer if that Actor blunders around in the dark, trying to go in directions where there are no exits and failing.) But refusals do not correspond to the same sorts of attempts at Action as do failures.

Refusal to Go in Particular Directions. In a particular Room, there will simply not be exits in certain directions. In many cases, it may be clear to any Actor that exiting in those directions is impossible. To indicate a special reason why there is no exit in a particular direction, one can simply place a template in the “exits” dictionary of the Room. This is the dictionary that is used in other cases to specify adjacent doors or Rooms. This template will produce a sentence completion such as “the crack is far too small to follow” that explains why any Actor can’t go in a particular direction.

Different Files // Curveship-py

Fiction File. What others call the “story file” or “game.” It can be a game, of course, but it can also be any sort of fictional (simulated) world.

Spin File. A very short file with a few parameters and perhaps a bit of code. These parameters determine how the story is told at a fairly high level. When the system reaches production level, the fictions/games that are published may simply include spin information in their fiction files without using separate spin files. However, sets of spins files are useful in research and teaching dealing with narrative. They demonstrate how the telling can be separated from the underlying story or story world by allowing different methods of telling to be applied to the same fiction file.

Main Curveship Page