summaryrefslogtreecommitdiff
path: root/appl/spree/man/gamesrv.man2
diff options
context:
space:
mode:
Diffstat (limited to 'appl/spree/man/gamesrv.man2')
-rw-r--r--appl/spree/man/gamesrv.man2471
1 files changed, 471 insertions, 0 deletions
diff --git a/appl/spree/man/gamesrv.man2 b/appl/spree/man/gamesrv.man2
new file mode 100644
index 00000000..fd910519
--- /dev/null
+++ b/appl/spree/man/gamesrv.man2
@@ -0,0 +1,471 @@
+.TH GAMESRV 2
+.SH NAME
+Gamesrv \- game server module
+.SH SYNOPSIS
+.EX
+.ps -1
+.vs -1
+include "draw.m";
+include "gamesrv.m";
+gamesrv := load Gamesrv Gamesrv->PATH;
+Range, Object, Game, Player: import gamesrv;
+
+Range: adt {
+ start: int;
+ end: int;
+};
+
+Object: adt {
+ transfer: fn(o: self ref Object,
+ r: Range, dst: ref Object, i: int);
+ setvisibility: fn(o: self ref Object,
+ visibility: int);
+ setattrvisibility: fn(o: self ref Object,
+ name: string, visibility: int);
+ setattr: fn(o: self ref Object,
+ name: string, val: string, vis: int);
+ getattr: fn(o: self ref Object, name: string): string;
+ delete: fn(o: self ref Object);
+ deletechildren: fn(o: self ref Object, r: Range);
+
+ id: int;
+ parentid: int;
+ children: array of ref Object;
+ objtype: string;
+ visibility: int;
+ # ...private data
+
+};
+
+Game: adt {
+ newobject: fn(game: self ref Game, parent: ref Object,
+ visibility: int, objtype: string): ref Object;
+ action: fn(game: self ref Game, cmd: string,
+ objs: list of int, rest: string, whoto: int);
+ player: fn(game: self ref Game, id: int): ref Player;
+
+ objects: array of ref Object;
+ # ...private data
+};
+
+Player: adt {
+ name: fn(player: self ref Player): string;
+ hangup: fn(player: self ref Player);
+ obj: fn(player: self ref Player, id: int): ref Object;
+
+ id: int;
+ # ...private data
+};
+
+Gamemodule: module {
+ clienttype: fn(): string;
+ init: fn(game: ref Gamesrv->Game, srvmod: Gamesrv): string;
+ command: fn(player: ref Gamesrv->Player, e: string): string;
+ join: fn(player: ref Gamesrv->Player): string;
+ leave: fn(player: ref Gamesrv->Player);
+};
+
+rand: fn(n: int): int;
+.ps +1
+.vs +1
+.EE
+.SH DESCRIPTION
+.I Gamesrv
+provides a general server interface that allows distributed
+clients to interact in a controlled manner, with the
+interaction mediated
+by Limbo modules, known as
+.IR "game engines" ,
+or just
+.I engines
+for short.
+Each engine decides on the rules
+of its particular game; the engine interface is described
+at the end of this manual page, under
+``Module Interface''.
+.PP
+This manual page describes the
+interface as presented to an engine
+once it has been loaded by
+.IR gamesrv .
+An engine is responsible for a particular
+.IR game ,
+in which one or more
+.I players
+participate. Messages sent by players
+are interpreted by the game engine, which
+responds by making changes to the hierarchical
+.I object
+database held by the game.
+Behind the scenes
+.I gamesrv
+distributes updates to this database to players
+of the game as appropriate.
+.SS "Objects and visibility"
+Objects hold a game's visible state. An object
+has a unique integer
+.IR id ,
+which is an index into the array
+.IB game .objects\fR;\fP
+it also holds a set of attribute-value pairs, a type, and
+zero or more child objects. Together, all the objects
+in the game form a hierarchical tree, rooted at
+the
+.IR "root object"
+(id 0), which always exists.
+Each attribute and each object also has an associated
+.IR "visibility set" ,
+the set of players that sees updates to the attribute or the children
+of the object. A visibility set is an integer, a bitmask where each
+bit represents one player, hence
+.B ~0
+is visible to all players, and
+.B 0
+is visible to no-one.
+In general, each player has a unique
+identifier
+.IR id ;
+in an integer
+.I i
+representing a set of players,
+the
+.IR id th
+bit represents the presence of the player with
+identifier
+.IR id .
+Thus, for a player
+.IR p ,
+.BI "(1<<" p ".id)"
+is the set containing only
+.IR p ,
+.BI "(" i "&~(1<<" p ".id))"
+excludes
+.I p
+from the set, and
+.BI "(" i "|(1<<" p ".id))"
+includes
+.I p
+in the set.
+.PP
+Note that the visibility set of an object does not alter the visibility
+of that object's attributes, but only that of its children (and of
+their children: in general an object is visible to a player if the
+intersection of all its ancestors' visibility sets contains that
+player).
+.PP
+Objects can be transferred inside the hierarchy from one parent to
+another. If an object is moved to a parent whose visibility conceals it
+from a player, then it will appear to that player to have been deleted;
+if it is later made visible, then it will be recreated for that
+player.
+A game engine can almost always ignore this technicality,
+except for one thing: the identifier used by a particular player to
+identify an object is not necessarily the same as that used by the game
+engine. Thus when an engine receives an object id in a player's
+message, it should convert it using the
+.IB player .obj()
+function.
+.SS \fBGame\fP
+The
+.B Game
+type holds all the objects in a game. It allows the
+creation of new objects, and provides way of communicating
+with players outside the object hierarchy.
+All data members of a
+.B Game
+should be treated as read-only.
+.TP 10
+.IB game .objects
+This array holds the objects in the game. An object with
+identifier
+.I id
+is found at
+.IB game .objects[ id ]\fR.\fP
+.TP
+.IB game .newobject(\fIparent\fP,\ \fIvisibility\fP,\ \fIobjtype\fP)
+.B Newobject
+creates a new object at the end
+of
+.IR parent 's
+children;
+If
+.I parent
+is nil, the new object is created under the root object.
+The new object has visibility
+.IR visibility ,
+and type
+.IR objtype .
+An object's type cannot be changed once
+it has been created.
+.TP
+.IB game .action(\fIcmd\fP,\ \fIobjs\fP,\ \fIrest\fP,\ \fIwhoto\fP)
+.B Action
+sends a message to some players without affecting
+the object hierarchy. It can be used to send transient
+events that have no meaning when stored statically
+(for example, network latency probes).
+The message is sent to the set of players given by
+.IR whoto .
+.I Objs
+is assumed to be a list of object ids, which are
+converted appropriately for each player
+receiving the message; the final
+message is a string built by concatenating
+.IR cmd ,
+the list of object ids, and
+.IR rest ,
+separated by spaces.
+.TP
+.IB game .player(\fIid\fP)
+.B Player
+yields the player corresponding to identifier
+.IR id ,
+or
+.B nil
+if there is none.
+.SS Player
+The
+.B Player
+type represents a player of a game.
+.TP 10
+.IB player .id
+The player's identifier, an integer between
+0 and 31. This is unique across all current players,
+but ids of players that have left the game will
+be reused.
+.TP
+.IB player .obj(\fIid\fP)
+.B Obj
+converts from a player's external object
+identifier to the game's local
+.B Object
+that it represents. It returns
+.B nil
+if there is no such object.
+.TP
+.IB player .hangup()
+.B Hangup
+hangs up a player's connection to the game;
+no more requests from
+.I player
+will be received by the game engine.
+.TP
+.IB player .name()
+.B Name
+yields the authenticated name of the player.
+This is not necessarily unique over the players
+of a game.
+.SS \fBObject\fP
+The
+.B Object
+type is the basic unit of game engine state.
+An object's children can be selectively concealed
+from players; it holds a set of
+.RI ( attribute ,\ value )
+pairs, each of which can be concealed likewise.
+Where an argument
+.IR r ,
+of
+.B Range
+type is used, it refers to a range of an object's
+children starting at index
+.IB r .start\fR,\fP
+and finishing at
+.IB r .end-1\fR.\fP
+All the data members of an
+.B Object
+should be treated as read-only.
+.TP 10
+.IB obj .setattr(\fIname\fP,\ \fIval\fP,\ \fIvis\fP)
+.B Setattr
+sets attribute
+.I name
+in
+.I obj
+to
+.IR val.
+If the attribute is being created for the
+first time, then it will be given visibility
+.IR vis .
+.I Name
+should be non-empty, and should not
+contain any space characters.
+Note that it is not possible for an attribute
+to refer directly to an object by its identifier;
+if this facility is needed, another identifying
+scheme should be used. This also applies
+to player identifiers, which will change
+if the game is saved and loaded again (not
+implemented yet).
+.TP
+.IB obj .getattr(\fIname\fP)
+.B Getattr
+yields the current value of the
+attribute
+.I name
+in
+.IR obj .
+If an attribute is not set, it yields
+.BR nil .
+.TP
+.IB obj .delete()
+.B Delete
+removes
+.I obj
+from the object
+hierarchy.
+.TP
+.IB obj .deletechildren(\fIr\fP)
+.B Deletechildren
+deletes children in range
+.I r
+from
+.IR obj .
+.TP
+.IB obj .transfer(\fIr\fP,\ \fIdst\fP,\ \fIi\fP)
+.B Transfer
+transfers the children in range
+.I r
+from
+.I obj
+to just before the object at index
+.I i
+in
+.IR dst .
+It is permissible for
+.I obj
+and
+.I dst
+to be the same object.
+.TP
+.IB obj .setvisibility(\fIvisibility\fP)
+.B Setvisibility
+allows the set of players
+given in
+.I visibility
+to see the children of
+.IR obj ,
+and denies access to all others.
+Players are notified of the change.
+.TP
+.IB obj .setattrvisibility(\fIname\fP,\ \fIvisibility\fP)
+.B Setattrvisibility
+allows the set of players
+given in
+.I visibility
+to see the value of
+.IR obj 's
+attribute
+.IR name ,
+and denies access to all others.
+Players are not notified of the change;
+if there is a need to communicate
+the fact of an attribute becoming invisible to
+players, it should be done by using another
+(visible) attribute to communicate the change.
+.SS "Module Interface"
+A game engine module,
+.IR mod ,
+must implement the
+following functions. Where a function returns a string,
+it is interpreted as an error response to the player
+responsible for the request; an empty string signifies
+no error.
+.TP
+.IB mod .clienttype()
+.B Clienttype
+should return the type of client required
+by the engine (e.g.
+.B cards
+for the card-game client).
+Each client type has its own conventions
+as to the meaning of object types and attribute
+names and values.
+This function may be called before
+.BR init() .
+.TP
+.IB mod .init(\fIgame\fP,\ \fIsrvmod\fP)
+.B Init
+initialises the game engine.
+.I Game
+is the game that the engine is controlling,
+and
+.I srvmod
+is the
+.B Gamesrv
+module holding its associated data.
+An error response from this function
+causes the game to be aborted.
+.TP
+.IB mod .join(\fIplayer\fP)
+.I Player
+has made a request to join the game;
+an error response causes the request to be
+refused, otherwise the player joins the
+game.
+.TP
+.IB mod .leave(\fIplayer\fP)
+.I Player
+has left the game.
+.TP
+.IB mod .command(\fIplayer\fP,\ \fIe\fP)
+.I Player
+has sent the command
+.IR e .
+The command usually follows
+the simple message conventions
+used in
+.IR gamesrv (4),
+i.e. simple space-separated tokens.
+.SH EXAMPLE
+The following is a small, but working example
+of a game engine that acts as a chat server
+(parsing error checking omitted, and white-space
+compressed to save paper):
+.PP
+.EX
+.ps -1
+.vs -1
+implement Gamemodule;
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+include "../gamesrv.m";
+ gamesrv: Gamesrv;
+ Game, Player: import gamesrv;
+game: ref Game;
+clienttype(): string
+{
+ return "chat";
+}
+init(g: ref Game, srvmod: Gamesrv): string
+{
+ (sys, game, gamesrv) = (load Sys Sys->PATH, g, srvmod);
+ return nil;
+}
+join(nil: ref Player): string
+{
+ return nil;
+}
+leave(nil: ref Player)
+{
+}
+command(player: ref Player, cmd: string): string
+{
+ game.action("say " + string player.id + " " + cmd, nil, nil, ~0);
+ return nil;
+}
+.ps +1
+.vs +1
+.EE
+.SH SOURCE
+.B /appl/cmd/games/gamesrv.b
+.SH "SEE ALSO"
+.IR gamesrv (4)
+.SH BUGS
+The reuse of object ids can lead to
+problems when objects are deleted and
+recreated on the server before clients become
+aware of the changes.
+.PP
+This interface is new and will change.