Writing:Reference Section

From Seltanikor
Jump to navigationJump to search

Your First Age

Basic Concepts

Working the Example

The Ways of Printing

Assorted Features

Reference Section

The Scripting Language

Best Practices

Code Samples

Property types

A block of text which is interpreted “wiki-style” – square brackets indicate special behavior.
A block of text which is interpreted as Python (actually TworldPy) code.
Code (args)
Same as Code, but with an extra field for arguments. These are treated as formal parameters. A code property with arguments x, y is like a function defined func(x, y): ... You can also specify default values: x=1, y="foo".
A structure used for procedural text generation.
A special property which moves the player to another location (in the same world).
A special property which sends a message to the player’s event pane (and possibly to other players in the same location).
A special property which throws the player out of the world. May optionally send an event message to the player and/or to nearby players.
A special property which allows the player to edit a text property in the location. The first field must be the name of a string value (or text) property (which acts as a default value). When edited, an instance property is written with a new string value.
The label is displayed above the edit field. The two messages at the end appear to the editing player, and nearby players, when a change occurs. By default only players with member access may edit this field, but you may set access to visitor (everybody) or a higher level.
Interpreted as a Python datetime. The value must look like “YYYY-MM-DD” or “YYYY-MM-DD HH:MM:SS” or “YYYY-MM-DD HH:MM:SS.UUUUUU” (the last field is microseconds). It is always interpreted in UTC (not your local time zone). Leave the field blank to get a timestamp of right now.
Interpreted as a Python native value.
Selecting this and confirming will delete the property entirely.

Python native values can be any of:

  • Integers or floating-point numbers
  • Quoted strings (single or double quotes are okay, but not curly quotes)
  • True, False: Booleans (must be capitalized)
  • None: Python null value (must be capitalized)
  • [1, "Foo", True]: A list (array) of Python values in square brackets
  • {"foo": 1, "bar": 2}: A dictionary (hash) written in curly braces. The keys must be strings; the values can be any Python values.


  • Python tuples are accepted but stored as lists. (So (1,2,3) will be stored as [1,2,3].)
  • Python set literals {1,2,3} are rejected.
  • Python bytes objects b"foo" are accepted, but are probably not good for anything.
  • Integers are limited to 64 bits. (Values much beyond ±9.2e18 cannot be stored.) (Float values have a much wider range, but less precision.)
  • Python datetime objects must be entered with the DateTime property type, not with Value.
  • Python ObjectId objects cannot currently be entered in the build interface.

The special property types (Text, Code, etc) are actually represented in the property database as Python dictionaries. For example, a Text value “Foo.” is really {"type": "text", "text": "Foo."} You will probably never need to know this, but if you do, the formats are defined here.

Text formatting and substitutions

Text is converted to HTML, so whitespace is generally not significant. Extra spaces, indentation, and single newlines are collapsed into single spaces. (Double newlines are taken as true paragraph breaks.)

All text, except when in square brackets, is displayed directly. You may freely enter Unicode characters as-is; you don’t have to escape them or use HTML character constants.

We’ve seen several different syntaxes for square-bracket substitutions in text.

Here’s the complete list. It can be broken down into three major groups: [hyperlinks], [[interpolations]], and [$magic] codes.

The [$magic] cases, with the dollar signs, are not hyperlinks; they mostly interpolate text. You might therefore expect them to be written [[$magic]]. In fact that will work, but we also accept the single-square-bracket form – it’s easier to type.


Displays a hyperlink “prop”, which invokes the prop property. If that’s Text, it is displayed as a close-up pop-up. If it’s Code, it’s executed. Move, Event, etc properties take effect as defined. Value properties are displayed as events (to the player only).
[Text in brackets.]
A hyperlink; the contents are sluggified, then invokes a property as above. This example would display as “Text in brackets,” but invoke a property named text_in_brackets.
A hyperlink that displays “single” but invokes the property named bar.
[single bar|code()]
A hyperlink that displays “single bar”, and executes the given line of code.
This is really the same as the previous case. bar as a code statement means “invoke the property named bar.”
[single bar|http://whatever/]
A hyperlink that displays “single bar” and opens an external web page (in a new browser window). The URL after the bar must begin with http: to be recognized this way.
[with double||bar]
A hyperlink that displays “with double bar” and invokes the property named bar.
[with double||bar words]
A hyperlink that displays “with double bar words” and invokes the property named bar_words. The text after the double bar is sluggified, so it may not contain arbitrary code.


Evaluates the interpolation symbol and inserts the result in-line. This is not a hyperlink.
Executes the line of code and inserts the result in-line. The code doesn’t have to be a function call; it could be an expression, such as foo+3. However, it may not be an assignment (a property change).
[ [[symbol]] | bar]
Displays symbol as the text of a hyperlink which invokes bar.
This nests an interpolation inside a hyperlink. You may not nest a hyperlink inside a hyperlink!

$ codes


A paragraph break. This is the same as putting a blank line (two line-breaks) in the text.
[$openbracket], [$closebracket]
Literal square brackets.
The name of the acting player.
[$they], [$we]
One of “he”, “she”, “it”, “they”, as appropriate for the acting player.
[$them], [$us]
One of “him”, “her”, “it”, “them”.
[$their], [$our]
One of “his”, “her”, “its”, “their”.
[$theirs], [$ours]
One of “his”, “hers”, “its”, “theirs”.
[$themself], [$ourself]
One of “himself”, “herself”, “itself”, “themself”.
The pronouns are available in capital forms: [$They] for “He”, “She”, “It”, etc.
You can use [$name player] or [$they player] to refer to the name or pronoun of a given player object. Currently there is no easy way to get any player object other than the acting player, so this is not interesting.
Why not also accept [$he], [$she], [$his], etc? First, it would be a lot of pronoun variants. Second, the male and female pronouns are ambiguous! Notice that “his” appears in two of the above lists. If you put [$his] in your code, the system would not be able to figure out whether you meant [$their] or [$theirs]. “Her” also appears in two lists, but not the same lists. English is wacky.


Emphasized text (italics).
Fixed-width text (monospace font).
D’ni font. Notice that this is handled with double square brackets and function calls, rather than a dollar-sign notation. Sorry about the ugliness.
D’ni text must be encoded in ASCII (mostly) using the D'ni Font Encoding.
These style tags may be nested. However, if you screw up the nesting or fail to close a tag, you'll see an error message when Seltani tries to print your text.

Conditional statements

[$if ...] Text [$end]
Displays the text if the $if expression is true. Otherwise, displays nothing. A Python expression is considered false if it is None, False, zero, the empty string, the empty list, or the empty dictionary. Anything else is considered true.
A property-not-found error in an $if expression is also considered false.
[$if ...] A [$else] B [$end]
If the expression is true, display A; otherwise, display B.
[$if ...] A [$elif ...] B [$else] C [$end]
The same, with an if... else-if... else chain.

Functions and references

global (top-level) symbols

The underscore always refers to the namespace of built-in functions, as described in this section. This can be useful if a property has shadowed one of these functions. For example, if you defined a location property named text, it would replace the text() function in that location. But you could still refer to _.text().

If you are silly enough to define a property called _, it will be ignored. The global _ cannot be replaced.

The length of a list, or the length of a string, or the number of entries in a dict.
min(list), max(list)
min(X, Y, Z), max(X, Y, Z)
Return the smallest or greatest of a list or bunch of arguments.
int(), str(), bool(), dict(), list(), set()
Standard Python type constructors.
Convert a Python string into a chunk of wiki-style text.

Square-bracket interpolations in the text are not performed immediately; they will be performed when the text is displayed.

code(str, args=None)
Convert a Python string into a code object. The optional args specify parameters to be passed in to the code.
If the code object appears on a line by itself, it is executed immediately. In an expression, it is executed when written as a function call in the usual way (followed by arguments in parentheses).
Find the database key for a player or location. If obj is not given, this generates a new unique database key (but does not store it in the database). If obj is a string with the correct form (a 24-character hex string), this generates a database key with that value.
isinstance(object, typ)
Test whether the object is an instance of the given type.
Return a Python dictionary that reflects the current set of local variables. (Not properties or builtins.) This dict is “live”; modifying it affects the locals in the environment.
style(str), endstyle(str)
Begin or end a style span with a named style. Currently only supports three values: "emph" (same as [$em]), "fixed" (same as [$fixed]), and "dni".
link(target, external=False), endlink(external=False)
Begin or end a hyperlink span. (Note that endlink() does not need a target argument.)
The target must be a string, containing code or the name of a property.
If external is True, the target must be an http: URL.

style(), endstyle(), link(), endlink() calls must occur in matched pairs, properly nested. If you do not arrange them correctly, error messages will appear in the displayed output.

Print a paragraph break. This is equivalent to the [$para] interpolation in a Text property.
Print a string. A print() call in a Code property is generally equivalent to putting plain text in a Text property.
You may include several arguments; they will be displayed with spaces between them.
If the argument is Text, it will be interpolated according to the usual rules. For example, print(text("[$para]")) generates a paragraph break.
event(you, others)
Display a message in the event pane of the acting player, and (optionally) other players in the same location.

If the message contains square-bracket tokens, remember to wrap it in text().

event(you, others, player)
Display a message in the the event pane of the given player, and (optionally) other players in the same location. The given player must be in the current instance.
eventloc(loc, str)
Display a message to everybody in the given location. This may be given as a location reference (locations.shortname) or a short name string ("shortname"). If you pass realm as the first argument, the message will go to every player in the instance.
move(dest, you, oleave, oarrive)
move(dest, you, oleave, oarrive, player)
Move a player to a location. This may be given as a location reference (locations.shortname) or a short name string ("shortname"). The optional other arguments are event messages for the moving player, other players in the start room, and other players in the destination room. The final (optional) argument is a player reference; if not given, the acting player moves. (Must be a player in the same instance as the executing code.)
panic(you, others, player)
Cause a player to panic-link out. The optional you and others arguments are event messages for the player and other players in the same room. The final (optional) argument is a player reference; if not given, the acting player moves. (Must be a player in the same instance as the executing code.)
The acting player. This can be used to get or set player properties; e.g., player.foo.
The acting player’s location.
The location with the given database key (an ObjectId).
The location with the given short name.
The location of the given player.
The location with the given short name. Same as location("shortname"), but you don’t use the parentheses or quotes.
A reference which can be used to get or set realm-level (instance) properties; e.g., realm.foo.
The location (in this world) which the player was in before moving here. If the player arrived in this location by linking, lastlocation is None.

You might use lastlocation to display a description conditionally as “Halfway up the stairs” or “Halfway down the stairs.”

Set the current player’s focus to the given string. This must name a text or code property: setfocus("sign"), not setfocus(sign).
setfocus("prop", player)
setfocus("prop", loc)
Set a given player’s focus, or the focus of every player in a location. If the loc argument is realm, this sets the focus of every player in the current instance.

The focus property must be accessible in the player’s location. So if you use the realm form, you’ll have to make sure the property is available realm-wide.

Clear the current player’s focus (if set).
Clear the current player’s focus, but only if it’s currently set to the given (named) property.
unfocus(None, player)
unfocus(None, loc)
Clear the focus of the given player, or all players in a location, or all players in the instance.
unfocus("prop", player)
unfocus("prop", loc)
Clear the focus of the given players, but only those whose focus is currently set to the given (named) property.
sched(delay, func, repeat=False, cancel=None)
Schedule the given function to be called after a delay. The delay argument is the number of seconds, or a datetime.timedelta value. The func argument must be a function or Code property. The delay must be at least 1 second, or at least 10 seconds if the timer is repeating.
If the (optional) repeat argument is True, the function will be called repeatedly, every N seconds, until the instance is abandoned.
If the (optional) cancel argument is given, the timer can be cancelled later by the unsched() function.

See the warning in “Timers” about scheduled code.

Cancel all upcoming events for this instance, if they were launched with the same cancel argument. If you call unsched() with no arguments, all upcoming events for the instance are cancelled.

access module

access.FOUNDER, access.OWNER, access.MEMBER, access.VISITOR, access.BANNED
Access level constants. These are integers, so they can be compared with > and >=. FOUNDER is 4, from there values descend down to 0 for BANNED.
Return the access level of the acting or given player to the current instance. The current implementation says that a player has FOUNDER access to his personal instances, and to the global instance of a world he created. All other cases return VISITOR.
(Planned feature: a way to give your friends access to your personal scope.)
(Planned feature: once group scopes are in, you will be able to give people various levels of access to the group.)
access.level(player, level)
Returns True if the player’s access level to the current instance is at least level.

players module

Returns the player object for the acting player, or the player with the given database key (an ObjectId). If the argument is a player object, this returns it unchanged.
Returns the name of the acting player, or the given player, as a string.
Returns the preferred pronoun of the acting player, or the given player. This will be one of the strings "he", "she", "it", "they", "name".
Same as location().
Return whether the player has Age-building permission. (This is False for new accounts until they go to the builder interface and request it. It is always False for guest accounts.)
Return whether the player is an (anonymous) guest. Guest accounts cannot build, and are reset after each use.
Returns True if the acting/given player is in this instance.
Returns the focus of the acting/given player. This is normally a string (the name of a text property, if the player has it as a close-up window) or None (if the player has no close-up window). However, there are special cases where this will return a list. (When the focus is another player, a linking book, a bookshelf, etc.)
Returns the number of players in the given location. If loc is realm, it’s the number of players in the entire instance.
Returns a list of players in the given location. If loc is realm, it’s the players in the entire instance.

gentext module

Convert a Python string into a gentext data structure.
gentext.display(obj, cooked=None, seed=None)
Display a symbol (text, gentext, or code) with different printing parameters. The cooked flag (True or False) controls auto-spacing and auto-capitalization. The seed parameter controls the pseudo-random behavior of generated text. For details, see Writing:The Ways of Printing.
gentext.Para(), gentext.Stop(), gentext.Semi(), gentext.Comma(), gentext.RunOn()
Generate a break (or lack of break) in a cooked text stream.
gentext.A(), gentext.An()
Generate the word "a" or "an" in a cooked text stream, whichever matches the next printed word. (You may use either gentext.A() or gentext.An() -- they produce the same result.)
gentext.AForm(), gentext.AnForm()
Resolve a pending gentext.A() or gentext.An(), as if a following word started with a consonant (gentext.AForm()) or vowel (gentext.AnForm()).

pronoun module

pronoun.they(), pronoun.them(), pronoun.their(), pronoun.theirs(), pronoun.themself()
pronoun.we(), pronoun.us(), pronoun.our(), pronoun.ours(), pronoun.ourself()
Returns the appropriate pronoun for the acting player. You may supply a player argument to specify a different player. All of these functions also exist in capitalized form.
pronoun.resolve(pronoun, player)
Returns the appropriate pronoun for the given or acting player. The pronoun argument must be one of the strings "We", "we", "Us", "us", "Our", "our", "Ours", "ours", "Ourself", "ourself". (The third-person forms don’t work here.)

random module

A randomly-selected entry in the list.
random.randint(A, B)
A random number from A to B, inclusive. (That is, random.randint(4, 6) will return either 4, 5, or 6, with equal probability.)
A random number from 0 to A-1.
random.randrange(A, B)
A random number from A to B-1. (That is, the result will be at least A but always less than B.)
random.randrange(A, B, step)
A random number which is at least A, less than B, and a multiple of step above A. (That is, random.randrange(0, 10, 2) will return 0, 2, 4, 6, or 8.)

datetime module

The current time, as a datetime.datetime object. Always in UTC.
datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0)
Create an object representing a date and time. (This can be stored in the database.)
A datetime object has these attributes: year, month, day, hour, minute, second, microsecond.
This differs from the Python datetime constructor in that the result is always timezone-aware and in UTC. If you try to pass in a tzinfo argument, it will be ignored.
datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
Create an object representing an interval of time. (Cannot be stored in the database. You may instead store timedelta.total_seconds(), which is a float.)
A timedelta object has these attributes: days, seconds, microseconds, total_seconds().

functools module

functools.partial(func, *args, **keywords)
“Wraps up” a function with arguments, producing a new function.
This may be helpful for timer events. For example, if func is a code property that takes one argument, then this code will schedule a timer event that calls func("foo"):
   sched(1, functools.partial(func, "foo"))


The on_wake property (from our example with timers) is one type of hook: a specially-named property that the server invokes in certain circumstances. There are several of these.

(Realm property) Invoked exactly once when the instance is created, which is the first time a player ever links in. This is immediately followed by an on_wake call.
(Realm property) Invoked when the instance is awakened; that is, if the instance is asleep (or freshly created) and a player links in. The temporary variable _slept will be the timestamp that the instance was put to sleep, or None if the instance has never been awake before.
(Realm property) Invoked when the instance has been uninhabited for ten minutes. After this call, all outstanding timers are cancelled.
Warning: the on_sleep does not occur if the server crashes or is rebooted by the administrator. In these cases, the server restarts with all instances “asleep” and immediately calls on_wake for the inhabited ones. (The _slept argument in this case will be the crash time.) So you should regard the on_sleep hook as unreliable; you may see two on_wake calls in a row with no on_sleep between them.
(Location property) Invoked when a player enters a room, either by moving or linking. The temporary variable _from will be the previous location (or None for linking); _to will be the new location.
(Location property) Invoked when a player leaves a room, either by moving, linking, or panic-linking. The temporary variable _from will be the current location; _to will be the new location (or None for linking).

Debugging commands

The in-game chat prompt offers a few helpful debugging commands. With the exception of /playstate, these can only be used in worlds you created.

Displays the database keys (ObjectId) of your avatar, world, instance, scope, and location.
/move loc
Teleport yourself to the location (in this instance) with the given short name.
/getprop prop
Check for a property named prop in the current location. If found, display its value, and whether it was a world or instance property.
/getprop .prop
Display the value of a realm property named prop (world or instance).
/getprop loc.prop
Display the value of a location property named prop in the location named loc.

Note that this syntax does not match script code. In script code, you’d be writing realm.prop and locations.loc.prop.

/setprop prop value
/setprop .prop value
/setprop loc.prop value
Set a property in the current location, realm, or the named location. This sets an instance property, like script code would, not the world property. (Again, world properties are defined solely by the world-building interface.)
The value can be any simple Python literal: None, True, False, integers, quoted strings, lists, dictionaries.
To set a text property, you have to use the ugly spelled-out form: {"type": "text", "text": "Foo."}
/delprop prop
/delprop .prop
/delprop loc.prop
Delete an (instance) property in the current location, realm, or the named location. If there is a world property with the same name, this will allow it to shine through again.
/eval code
Run the line of code in the current location, as if it were an action that you had clicked on.

So /eval foo=1 is the same as /setprop foo 1, really.

Local variables in an /eval (variables beginning with underscores, i.e., _x) live in a special environment which will persist as long as your connection is active. These locals will never spill over from your /eval commands into running world code.

Kick everybody out of the current instance, including yourself. Then put the instance to sleep. The next time someone enters the instance, the on_wake hook will run. (See the “Hooks” section for more details.)