Server actions file
Actions are a collection of methods associated with an object
or person, written in a simple C/pascal like language interpreted
by the sim server. An action for an object controls what happens
when something is done to that object, while an action for a
person provides the 'intelligence' for the person.
The format of the actions file is :
action name {
type name
type name
...
method name ... {
type name
type name
...
code
}
}
action name {
...
}
...
Each action must have a unique name, corresponding to the name of the
object or person it is associated with. Inside the
action are :
- Variable declarations
Typed variables accessible to all methods of this actions. Variables
may have an initialising expression.
- Methods
Blocks of code (with 1 or more names) contained within the action.
If this action is associated with an object (for example
an object called book) and a user chooses to
read the book, then the method named read
will be invoked.
Methods may contain variables declared using the same syntax
as those outside methods. They are only accessible to code inside
the method though.
Variables
The format of variable declaration is :
type [[size]] name [= expression] ;
- Valid variable types are str for a string variable, and
dbl for a double-precision floating point variable.
- Arrays of variables may be declared by putting an integer number of
elements enclosed in square brackets after the type name. If the
array size is not given, then the array is assumed to be of size 0.
- Variable names can be any alphanumeric sequence beginning with a
letter (including underscores).
- The initialising expression can be anything that returns a value
of the same type as the variable. If you initialise an array
variable with an array of another size but the same type, then
the variable will be quietly resized. If an initialiser is not
given, then the variable will be initialised to 0 for dbls
or an empty string for strs.
Some example variable declarations :
str x; A string variable.
dbl n = 10; A floating point variable, intialised to 10.
str myString = "hello"; A string variable with an initialiser.
str[10] arr; An array of string variables.
dbl[3] darr = [5;6;7]; An array of floating points, initialised to
darr[0] = 5, darr[1] = 6 and darr[2] = 7.
dbl[] foo = someFunc(); An array initialised by the result of a
function that returns an array.
dbl baz = "hello"; A type mismatch error. Note that is will not
be detected until the action or method that
contains this is run.
By default, all variables are local (non-persistent). Variables in
a method will be re-initialised each time that method is called, while variables
outside methods will be re-initialised when any method of that action is
called. The alternative to this is to declare variables as static,
by putting the keyword static before the variable type. Such variables
will have their values kept between calls to methods, even if the server is
shutdown and restarted.
Some more variable declaration examples :
static str y; A persistent string variable.
local dbl x = 10; A non-persistent floating point variable.
dbl foo = 3+2; A non-persistant floating point.
static str bar = "hi"; A persistent string variable, initially set
to "hi".
Local variables outside of methods are always initialised before
variables inside the method being called, which are themselves always
initialised before method code is called. Static variables inside
and outside of methods are initialised when the action is read in by the
server for the first time.
Every action has 4 variables that do not need to be explicitly declared,
and that are automatically initialised whenever an action method is called.
They are :
- str name;
The name of this action.
- str player;
The name of the player who called this method. In cases
where a method was not invoked by a user (such as the
think method of an action for a person) then this
will be set to an empty string.
- str actionmethod;
The name of the method being called.
- str[] params ;
The parameters to this method, usually given by the user who
invoked it. The size of this array is determined by the number
of parameters given.
Methods
The format of method declarations is :
method name name ... {
variable
variable
...
statement
statement
...
}
A method can be called by any one of it's names, so you could have an action
for a switch that has a method called when the switch is pressed,
pushed or toggled for example. Method code is sort of C-like,
but without some of the constructs that make it hard to easily interpret
(like goto and break).
Statements
Valid statments inside a method are :
- if statement
if ( expr )
statement
else
statement
The usual C-style if-then statement (the else part is optional as
usual). The controlling expression must return a number.
- for loop
for( expr ; expr ; expr )
statement
A C-style for loop. The first expression is called once before the loop, the
second checked before each iteration (and so must return a number) and the
third called after the statement inside the loop.
- while loops
while( expr )
statement
do
statement
while( expr );
C-style pre and post checking while loops. The controlling expression must
return a number.
- statement block
{
statement
statement
...
}
A block of statements, just like C (but without the ability to declare variables
local to the block). Statements are executed in the order they are given.
- expression statement
expr ;
An expression evaluated for it's side-effects, such as an assignment or
function call. See the section on expression for more details.
Expressions
An expression is something like x + 6, foo = 7 or
print("hello"). All expression returns a value of one of the types
dbl, str, dbl[] or str[], or void
for expressions that don't really return any value. Some example expressions
and their types are :
x + 6 dbl
"hello " & "world" str
print("hi\n") void
[5;6;7] dbl[]
myString = "hi" str
["one";"two"] str[]
rand(10) dbl
myString[1] str
Most expressions work just the same as in C. The main types of expression are :
- Binary operators
Binary operators have the syntax expr op expr.
Valid operators are :
- + (numeric addition)
- - (numeric subtraction)
- * (numeric multiplication)
- / (numeric division)
- % (integer modulus)
- == (string, array or numeric equality)
- != (string, array or numeric inequality)
- < (numeric less than)
- > (numeric greater than)
- <= (numeric less than or equals)
- >= (numeric greater than or equals)
- Unary operators
Unary operators have the syntax op expr. Valid
operators are :
- - (numeric negative)
- + (numeric positive)
- ! (logical not)
- Assignment operators
Assignment operators make some change to a variable, and return
the new value of the variable. Their syntax is lvalue
op expr, where an lvalue is something that can
be assigned to (like a variable name or array element). Valid
assignment operators are :
- = (string, array or numeric assignment)
- += (numeric addition assignment)
- -= (numeric subtraction assignment)
- *= (numeric multiplication assignment)
- /= (numeric division assignment)
- Pre/post increment/decrement operators
These 4 numeric operators have the following syntax :
- lvalue ++ (return old value and increment)
- lvalue -- (return old value and decrement)
- ++ lvalue (increment and return new value)
- -- lvalue (decrement and return new value)
- String operators
- string & string
Returns the concatenation of two strings.
- string [ expr ]
Returns a character extracted from a string.
- Array operators
- array [ expr ]
Returns an element from an array.
- [ expr ; expr ; ... ]
Constructs an anonymous array from 0 or more expressions,
all of the same type.
- function call operator
The function call operator calls one of the builtin functions,
and returns a value of some type (possibly void). The syntax
of this operator is name ( expr , ... ) , where the
number and types of the parameters is determined by the function.
See the next section for a list of the inbuilt functions available.
- sizeof operator
This operator is used to find the number of elements in array or
the length of a string. It's syntax is sizeof (
expr ) , where the expression must be either an array of
some type, or a string.
- typeof operator
The typeof operator returns a string containing the type of
some expression, in the same format as used in variable
declarations. It's syntax is typeof ( expr ) .
Inbuilt functions
The various inbuilt functions allow action code to do such things as move
shapes, send messages to players and open paths.
This section describes the parameters, return value and effects of all
the functions, and gives an example of it's use :
- void print(...)
The print function takes are arbitrary number of arguments
of any types, to be sent to the player who called this
method (if there is one).
Example : print("The value is ",v,"!!!");
- dbl sqr(dbl n)
The sqr function returns the square of it's parameter n.
Example : foo = sqr(bar);
- dbl cos(dbl a)
The cos function returns the cosine of the angle a, assumed to
be in degrees.
Example : x = cos(ang);
- dbl sin(dbl a)
The sin function returns the sine of the angle a, assumed to
be in degrees.
Example : y = sin(ang)*100;
- dbl sqrt(dbl n)
The sqrt function returns the square root of n, or 0 if n is
less than 0.
Example : r = sqrt(x*x + y*y);
- void send(str data, str name)
The send function, when called in a method of an action associated
with an object, attempts to send that given data file
associated with that object to the client controlling the named
player. This function would be used in the read action
of a book for example, to send the text of that book to it's
reader. An error will occur if the named player does not
exist or is not connected to the server, or the named data file
is not found.
Example : send("text.ps",player);
- void sendstr(str data, str ext, str name
The sendstr function sends as data a string to the user controlling
the named player. The type of this data is determined by
ext, which is taken to be a filename extension from which a mime
type can be determined. This function is useful for sending small
amounts of data to a user that you don't want to store in a file
on the server, for example a small postscript program or piece of
text. An error will occur if the player does not exist
or is not logged in to the server.
Example : sendstr("This is a short sentence","txt",player);
- void moveperson(str name, str location)
The moveperson function moves the named person to a new node.
Methods for non user-controlled persons should call this
to move to a new location. If the named person or
node does not exist an error will be generated.
Example : moveperson(name,"tunnel12");
- void moveobject(str name, str location)
The moveobject function moves some object to the named
node. An error is generated if the node or object
does not exist (or is in someone's inventory).
Example : moveobject("sword","tunnel12");
- void rotate(str name, dbl ang, dbl x, dbl y, dbl z)
The rotate function sets the rotate of the named shape to
the given angle about the given axis. If the shape has
already been rotated then this new rotation overrides the old one
rather than adding to it. An error will occur if the shape
does not exist.
Example : rotate("door",90,0,0,1);
- void move(str name, dbl x, dbl y, dbl z)
This function adds the given x, y and z values to the position of
the named shape. If the shape does not exist,
an error will be generated.
Example : move("spiked_date",0,0,5);
- dbl pexists(str name)
The pexists function returns a non-zero number if the named
player exists. Useful for testing if a person is
human-controlled.
Example : if (pexists("foo")) send("quux.gif","foo");
- dbl oexists(str name)
The oexists function returns non-zero if the named object
exists.
Example : if (oexists("hat")) moveobject("hat","tunnel12");
- void chpath(str node1, str node2, dbl closed)
The chpath function opens or closes the path between two
nodes. Useful for switches that open doors and the like. An error
occurs if either of the nodes does not exist, or if there
is no path between them.
Example : chpath("tunnel5","tunnel6",0);
- str position(str name)
This function returns the name of the node that the named
person or object is located at. If an
object in a persons inventory is given, then an
empty string is returned. If the no person or
object with the given name is found an error occurs.
Example : if (position(player) == "tunnel5") foo = 5;
- dbl atod(str s)
The atod function converts a string to a double (assumes base 10
notation).
Example : dbl x = atod("10");
- str dtoa(dbl n)
The opposite of atod - converts a floating point number to a
string.
Example : s = "The number is " & dtoa(n);
- str sprint(...)
The sprint function takes an arbitrary number of arguments of
any types and returns a string containing all the arguments
concatenated together.
Example : s = sprint("The number is ",n);
- void teleport(str name, str location)
This function teleports a player to a new location
instantly. Generates an error if the player or
node doesn't exist.
Example : teleport(player,"pit1");
- void domethod(str method, str action, str[] params)
The domethod function invokes some method of some action with the
given parameters. Useful as a kind of function call, until I get
real user defined functions working :). If the action or
method doesn't exist, an error occurs.
Example : domethod("open","dungeon door",[]);
- str getshape(str name)
The getshape function returns (in string form) the named
shape. This string is meant only for passing to the
putshape(), setshattrib() and getshattrib() functions and should
not be modified. If the named shape doesn't exist an error
occurs.
Example : avatar = getshape("player");
- void putshape(str shape)
The putshape function creates a shape from the given
string and adds it to the map. If a shape of the same
name already exists, it is replaced. If the string given is not
valid, an error occurs.
Example : putshape("box { corners 0 0 0 1 1 1 }");
- str setshattrib(str shape, str attrib, value)
The setshattrib modifies one of the attributes of a shape
represented by a shape string and returns the new string. The
attrib parameter determines the attribute to modify and the
type of the value argument. Valid attribute strings and values are :
- "name", str name
The shape's name (or "" for none).
- "colour.red", dbl red
The red value of the shape's colour.
- "colour.green", dbl green
The green value of the shape's colour.
- "colour.blue", dbl blue
The blue value of the shape's colour.
- "pos.x", dbl x
The x coord of the shape's position.
- "pos.y", dbl y
The y coord of the shape's position.
- "pos.z", dbl z
The z coord of the shape's position.
- "hidden", dbl hidden
Whether the shape is visible or not.
- "rot.a", dbl angle
The angle of rotation of the shape (in degrees).
- "rot.x", dbl x
The x axis of the rotation vector.
- "rot.y", dbl y
The y axis of the rotation vector.
- "rot.z", dbl z
The z axis of the rotation vector.
- "sc.x", dbl x
Scaling factor along the x axis.
- "sc.y", dbl y
Scaling factor along the y axis.
- "sc.z", dbl z
Scaling factor along the z axis.
- "surf", dbl surface
Shape surface type. Can be "flat", "glass" or "shiny".
An error can occur if the string given is not a valid
shape, if the attribute is not in the list above or
the value type is incorrect.
Example : foo = setshattrib(foo,"surf","glass");
- str/dbl getshattrib(str shape, str attrib)
The getshattrib function extracts and returns an attribute from
a shape string. The attrib parameter (which must be from the list
of attributes for the setshattrib() function) determines the type
and value returned by this function. If the shape string
given is not valid or the attribute does not exist an error will
occur.
Example : print("Angle = ",getshattrib(foo,"rot.a"));
- str getperson(str name)
The getperson function returns (in string form) the named
person. This string is meant only for passing to the
putperson(), setprattrib() and getprattrib() function and so should
not be modified. An error will occur if the named person
does not exist.
Example : str me = getperson(name);
- void putperson(str person)
The putperson function creates a person from the given
string and adds it to the server, replacing any existing
person of the same name. An error occurs if the string
given is not valid.
Example : putperson(setprattrib(p,"pos","tunnel2"));
- str setprattrib(str person, str attrib, value)
This function modifies one of the attributes of a person
represented by a string and returns the new string. The attrib
parameter determines the attribute to modify and the type of
the value parameter. Valid attribute string are :
- "name", str name
The person's name.
- "pos", str node
The name of the node this person is at.
- "ang", dbl ang
The facing angle (in degrees) of this person.
- "email", str address
This person's full email address.
- "fullname", str name
The person's full name.
If the person string given isn't valid or the attribute
doesn't exist an error will occur.
Example :
- str/dbl getprattrib(str person, str attrib)
The getprattrib function extracts and returns an attribute from
a person string. The attrib parameter (which must be from
the list of attributes from the setprattrib() function) determines
the type and value returned by the function. If the person
string is invalid or the attribute doesn't exist an error occurs.
Example : print("You are at ",getprattrib(player,"pos"));
- str[] pathsfrom(str location)
The pathsfrom function returns an array of strings containing the
names of all nodes connected by paths from the
given location, except for those where the path is closed
or the node is a connection to a remote server. If the
named node does not exist an error occurs.
Example :
- void say(str message)
This function (when called by a method belonging to a
person) sends the given message to all nearby
persons, just like the say command available in user's
client programs. If this is called by an action that doesn't belong
to a person, an error occurs.
Example : say("Hello dude!");
- void yell(str message)
The yell function sends the given message to all persons
on this server, like the yell command in user client programs. If
it is called by an action not associated with a person
an error occurs.
Example : yell("Hello everyone!!");
- void rotateperson(str name, str location)
This function rotates the named person to face the
given node. Methods for controlling persons should
use this to face in the right direction before moving. If the
node or person doesn't exist an error occurs.
Example : rotateperson(name,"tunnel4");
- dbl rand(dbl max)
The rand function returns a pseudo-random number in the range
0 .. max-1.
Example : print("The dice rolls a ",rand(6)+1);
- void sendurl(str url, str name)
The sendurl function will download the given url from a web server
and send it to the named player's client, like the send()
function. Useful for having data sent to a client when something
is done to an object (like reading a book) without having to store
that data on the sim server. An error occurs if the player
does not exist or is not logged in, or if something goes wrong
accessing the given url.
Example : sendurl("http://www.foo.com/stuff.ps",player);
- str[] personsat(str location)
The personsat function returns an array of the names of
persons at the given node. An error occurs if
the given node doesn't exist.
Example : str[] foo = personsat("tunnel5");
- str system(str command)
The system function passes the given command to /bin/sh for
execution and returns a string containing the standard output from
that command.
Example : str dir = system("/bin/ls /u/hon/jmc | sort");
- str mid(str string, dbl start, dbl length)
The mid function extracts a substring from a string, from the
character given by the start parameter and continuing for length
characters. An error occurs if the substring is out of range
of the given string.
Example : foo = mid("quux foo bar",5,3);
Special methods
Actions created to be associated with and control a person are
different to actions associated with objects in that their methods
are not called by users. Instead, two special actions called think
and listen can be defined, to be called automatically by the server
in the following circumstances :
- think
Called once every 2 seconds (by default) so the person
can sense it's environment, move about and so on. You can change
the period between calls to this method by defining a dbl
action variable called thinktime and setting it to a time
in seconds (>= 2) for the server to wait between calls to
think. Note that your actions can change this value, in
order to do something like putting a person to sleep.
When this method is called, the action's player variable will be
set to an empty string and it's params variable empty.
- listen
Called when the person hears a message from a
player. You can use this to have your person
carry out conversations with users, hopefully fooling them into
thinking that they are talking to a real human :)
When this method is called, the action's player variable will be
set to the name of the player who sent the message and
it's params variable set to the words of the message heard.
An action associated with an object can have methods that are for
internal use only, not callable by users. Any method with a name starting
with an underscore _ is not visible to users, but may be called using the
domethod() function from other methods of the action.
One special case of this is the _trigger method. If an action has
such a method and the object associated with it is at some location
then this method will be called whenever any person 'steps on' that
object. This is useful for creating things like pressure plates that activate
when someone steps on them, for example.
When this method is called, the actions's player variable is set to the name
of the person who triggered it and it's params variable set to an
empty array.
Errors
If an error of any kind occurs in the execution of a method, it's execution will
immediately terminate and an error message written to the server log file (and
sent to the client of the user who invoked the method, if applicable). Possible
errors are :
- Type mismatch
- Division by zero
- Function does not exist
- Wrong number of parameters to function
- Player does not exist
- Player is not logged on
- Data file not found
- Node does not exist
- Object does not exist
- Path does not exist
- Person does not exist
- Method does not exist
- Parse error
- Attribute does not exist
- Not an lvalue
- Array size mismatch
- Action does not belong to a person
- Error accessing URL
- Error executing program
Return to the [final report]