Introduction

The ToastStunt database file is a flat ASCII text file with relevant bits of information separated by newlines. This document will go over the structure of that file and explain how various values are derived. It’s unlikely you’ll be able to make more than minor changes to a database by hand, but this information should prove valuable if you need to parse or attempt to recover a database or data from a database.

The information below is written in the exact order you’ll encounter things in an actual database file. When a specific type of MOO value is expected, that item will link to a section explaining how to interpret that specific type in the database.

Those curious about the server source code should find these functions of particular interest:

Observations to Keep in Mind

It’s worth keeping a couple of things in mind when reading, parsing, or thinking about the database format:

Database

Initial Block

Every database file begins with a recognizable, human-readable header. This is typically something like: ** LambdaMOO Database, Format Version 17 **. This indicates that it’s a LambdaMOO database (of course) and the version of the format in use. The version is important because it tells the server which features are available at the time the database is written, which affects how it gets read back. (For example, databases prior to format version 15 didn’t include the last_move property for every object. Without a proper version, the server would assume this database has that property and attempt to read it, which would fail.) (See version.h if you’re curious to see what each database revision changed.)

Transitory Data

Objects

Verbs

Queued / Forked Tasks

For each forked task, the following will be written:

Suspended Tasks

For each suspended task, the following will be written:

Activation

Object Flags

The object flag integer is obtained by adding one or more of the values from this table together:

# Value Flag
0 1 Player
1 2 Programmer
2 4 Wizard
3 8 Obsolete
4 16 Read
5 32 Write
6 64 Obsolete
7 128 Fertile
8 256 Anonymous
9 512 Invalid
10 1024 Recycled

For example: If you want an object to be a player, a programmer, and a wizard, you would add together the ‘Value’ column for each to get: 1 + 2 + 4 for a total value of 7.

If you’re trying to decipher a flag, it’s slightly more complicated. Without going too deeply into bits, you can accomplish this with a MOO eval. Instead of looking at the ‘Value’ column, look at the ‘#’ column. Our eval will be: FLAG &. (1 << #) != 0

Say we have an object with a flag of 7. To see if that object is a wizard (# 2 in the table), we plug it into our eval: 7 &. (1 << 2) != 0

If it returns 1, the object has the flag. In our case, yep, it’s a wizard! Just remember, use the number from the ‘#’ column, not ‘Value’.

Verb Permission Flags

Verb permissions are obtained by adding one or more of the values from this table together:

# Value Flag
0 1 Readable (+r)
1 2 Writable (+w)
2 4 Executable (+x)
3 8 Debug (+d)

Strangely enough, dobj and iobj are also part of a verb’s permission flags:

# Value Flag
4 16 dobj = any
5 32 dobj = this
6 64 iobj = any
7 128 iobj = this

For example: If you want a verb to be readable (+r) and debug (+d) with arguments {"any", "out of/from inside/from", "this"}, you would add together the ‘Value’ column for each to get: 1 + 8 + 16 + 128 for a total value of 153.

If you’re trying to decipher a flag, it’s slightly more complicated. Without going too deeply into bits, you can accomplish this with a MOO eval. Instead of looking at the ‘Value’ column, look at the ‘#’ column. Our eval will be: FLAG &. (1 << #) != 0

So if you have permission flags with a value of 9, you can check if it’s writable by plugging it into our eval: 9 &. (1 << 1) != 0

If it returns 1, the permission bit is set. In this case, nope, not writable!

Verb Preposition Flags

The preposition flag is simply a number corresponding to a value. The standard prepositions are listed here. Should your server be weird and add more, you can find them in db_verbs.cc

Value Preposition
-2 any
-1 none
0 with/using
1 at/to
2 in front of
3 in/inside/into
4 on top of/on/onto/upon
5 out of/from inside/from
6 over
7 through
8 under/underneath/beneath
9 behind
10 beside
11 for/about
12 is
13 as
14 off/off of

Property Permission Flags

# Value Flag
0 1 Readable (+r)
1 2 Writable (+w)
2 4 Chown (+c)

For example: If you want a property to be readable (+r) and writable (+w), you would add together the ‘Value’ column for each to get: 1 + 2 for a total value of 3.

If you’re trying to decipher a flag, it’s slightly more complicated. Without going too deeply into bits, you can accomplish this with a MOO eval. Instead of looking at the ‘Value’ column, look at the ‘#’ column. Our eval will be: FLAG &. (1 << #) != 0

Say we have a property with a flag of 7. To see if that property is writable, we plug it into our eval: 7 &. (1 << 1) != 0

If it returns 1, the property has the flag. In our case, yep, it’s writable! Just remember, use the number from the ‘#’ column, not ‘Value’.

Interpreting Types

CLEAR

  1. Numeric type value: 5

NONE

  1. Numeric type value: 6

STRING

  1. Numeric type value: 2
  2. A string.

Example

"Hello world!"

2
Hello world!

OBJECT

  1. Numeric type value: 1
  2. Object number as an integer. (NOTE: Does not include the pound sign.)

Example

#2

1
2

ERROR

  1. Numeric type value: 3
  2. Integer representing the error value. See table below.
Integer Error
0 E_NONE
1 E_TYPE
2 E_DIV
3 E_PERM
4 E_PROPNF
5 E_VERBNF
6 E_VARNF
7 E_INVIND
8 E_RECMOVE
9 E_MAXREC
10 E_RANGE
11 E_ARGS
12 E_NACC
13 E_INVARG
14 E_QUOTA
15 E_FLOAT
16 E_FILE
17 E_EXEC
18 E_INTRPT

Example

E_ARGS

3
11

INTEGER

  1. Numeric type value: 0
  2. The integer.

Example

123

0
123

BOOL

  1. Numeric type value: 14
  2. 1 if true, 0 if false.

CATCH

  1. Numeric type value: 7
  2. Integer

FINALLY

  1. Numeric type value: 8
  2. Integer

FLOAT

  1. Numeric type value: 9
  2. The float.

Example

123.45

9
123.45

MAP

  1. Numeric type value: 10
  2. The number of keys in the map.

For each key in the map…

  1. Map Key
  2. Map value. NOTE: This could be any type, so you’ll have to identify the type by the first number and then reference it in the Interpreting Types section.

Example

["source" -> #123, "time" -> 1670634392]

10
2
2
source
1
123
2
time
0
1670634392

LIST

  1. Numeric type value: 4
  2. The number of elements in the list.
  3. If the list is not empty, the values of every element in the list. NOTE: These elements could be any type, so you have to identify the type of each element by the first number and reference it in the Interpreting Types section.

Example

{#2, "Hey, that's wizard!", 2, 2.22, {"A list in a list, oh NO!"}}

4
5
1
2
2
Hey, that's wizard!
0
2
9
2.22
4
1
2
A list in a list, oh NO!

ANON

  1. Numeric type value: 12
  2. Numeric reference.
    • If the anonymous object hasn’t been written yet, it’s given a new object number. Anonymous object numbers can be assigned to recycled objects or, if none are available, they are created after the last real object ( max_object() + 1).
    • If the anonymous object references an anonymous object that’s already been written, the number will match the original anon.

When looking for property values on anonymous objects, you have to look for the object created in this step. It will appear in the standard object list as any other object.

Example

*anonymous*

12
5

WAIF

  1. Numeric type value: 13

If the waif is a reference to an existing waif:

  1. A string beginning with r and ending with the numeric reference to the waif in the waif index.
  2. A single period (.)

If the waif is new:

  1. A string beginning with c and ending with a numeric reference to a waif in the waif index.
  2. The waif class (Integer)
  3. The waif owner (Integer)
  4. The number of properties that can be set on this waif. This is the total number of instance properties (those beginning with :) on the waif’s class and all ancestors of that class.
  5. The values of every non-clear property set on the waif instance. For each property:
    1. An integer defining the property’s index into the property map. Properties are counted from 0, beginning with properties on the class and moving down the ancestry.
    2. The value of the property. NOTE: This can be any MOO type. You’ll need to use the first number to determine the type and then reference the Interpreting Types section.
  6. The number -1
  7. A single period (.)

Example

We have two waif classes:
#4: Waifilicious with one property: :flavor
#5: Waiftastic with one property: :activity

Waif #5 is a child of waif #4. Our waif is an instance of #5 with the .flavor property set to "toast":
[[class = #5, owner = #2]]

13
c 0
5
2
2
1
2
toast
-1
.

Last Updated: 2022-12-15 for Database Version 17

Corrections? Comments? Wild bursts of irrational hatred? Contact me: lisdude@lisdude.com