RIMpython Guide

Anders Petersson, demitar@worldforge.org

v0.1.1, 5 September 2001
This document is an introduction to the rimpython STAGE module (STAGE is an effort by the WorldForge Project). You can find the most recent version here.

1. Introduction

2. Playing text based WereWolf

3. Writing a game

1. Introduction

rimpython is a RIM with most of it's functionality abstracted into python. Eventually most calculations should be done by calling c++ helper functions.

A RIM basically intercepts operations routed by pegasus, does some logic on them and replaces them with other ops.

1.1 Why should anubis/I care?

<Demitar> Basically server development was moving so slow I ran out of things to implement in silence-py and got bored. :)

<James> Becuase I told him too.

Official reason: Becuase it's vital to demonstrate that the RIM system is not tied to C++.

1.2 Installation

To install you need to get a copy of stage (and python of course) and apply some patches:


(stage/sys/) add -lpython1.5 to the stage linking.


(stage/sys/pegasus/rim/) add Py_Object.h/cpp and rimpython.h/cpp to the sources. (And perhaps you need to add -I/usr/include/python1.5 to the INCLUDES too.)


(stage/sys/pegasus/) apply the following patch:

Index: sys/pegasus/pegasus.cpp
RCS file: /home/cvspsrv/worldforge/forge/servers/stage/sys/pegasus/pegasus.cpp,v
retrieving revision 1.22
diff -c -r1.22 pegasus.cpp
* sys/pegasus/pegasus.cpp     2001/07/26 10:45:50     1.22
--- sys/pegasus/pegasus.cpp     2001/09/05 15:51:44
 27,32 ***
--- 27,33 ----

#include "rim/rimcreate.h" #include "rim/rimchat.h" + #include "rim/rimpython.h"

#include <Atlas/Objects/Operation/Sound.h> #include <Atlas/Objects/Operation/Create.h> ************* 94,99 ** --- 95,117 ---- Galileo::log(2,1405, "Pegasus: Added RimChat as a RIM"); m_rim = rimchat; } + if(Config::inst()->getItem("pegasus","rim") == "rimpython"){ + RimPython rimpython = new RimPython(); + m_rimPre.push_back(RimItem("action",rimpython)); + m_rimPre.push_back(RimItem("create",rimpython)); + m_rimPre.push_back(RimItem("look",rimpython)); + m_rimPre.push_back(RimItem("talk",rimpython)); + m_rimPre.push_back(RimItem("imaginary",rimpython)); + m_rimEcos.push_back(RimItem("create",rimpython)); + m_rimEcos.push_back(RimItem("look",rimpython)); + m_rimEcos.push_back(RimItem("talk",rimpython)); + m_rimEcos.push_back(RimItem("imaginary",rimpython)); + m_rimPost.push_back(RimItem("sound",rimpython)); + m_rimPost.push_back(RimItem("sight",rimpython)); + m_rimPost.push_back(RimItem("info",rimpython)); + Galileo::log(2,1405, "Pegasus: Added RimPython as a RIM"); + m_rim = rimpython; + } } return true; } ************* 105,110 *** --- 123,131 ---- delete m_rim; } if(Config::inst()->getItem("pegasus","rim") == "rimchat"){ + delete m_rim; + } + if(Config::inst()->getItem("pegasus","rim") == "rimpython"){ delete m_rim; } }


(stage/sys/) Add the following to the config:

rim = "rimpython"

2. Playing text based WereWolf

Disclaimer: This has nothing to do with the official WorldForge WereWolf and is a simple server aided implementation (server narrates and filters completely) of the social game with the same name. (This will hopefully keep th3walrus from biting me. ;-)

2.1 Instructions

  1. Gather atleast four people wanting to play werewolf in STAGE (in-game).
  2. Say: "start the werewolf session"
  3. Everyone is given their true identity and night falls.
  4. During the night seers, healers and werewolves act. Speech is filtered so only werewolves hear other werewolves.

    /look /who/ - reveals the true identity of a character.


    /me charms /who/ - protects a character from werewolves that night.


    Can speak with each other during the night. /me votes for /who/ - determines who you will vote for, even votes result in no attack.

    When all actions are done the night ends.

  5. When the day comes the deeds done during the night are uncovered and the villagepeople can vote to lynch someone. /me votes for /who/ - casts a vote, the status is then echoed to everyone. When no votes are left to be cast night falls.
  6. If all werewolves or townspeople are dead the game ends otherwise it repeats.

Also dead people can always talk but they only hear what other dead say, they also hear werewolves and see their votes.

2.2 Bugs and Limitations

3. Writing a game

Currently there are no helpers and you therefore have to keep all data structures in python (read as: don't use it yet). And it is likely to break as soon as Lee cleans up the pegasus or rim code.

3.1 Checklist

3.2 The logic

Currently the magic happends in rimpython.py, when creating a new game you essentially create a new game_*.py edit rimpython.py so it imports your module and change createWorld() so it instantiates a world from your module.

On init createWorld(id) is called, this is mainly a hack to pass a worldid to python and allowing easy reloading of the game (explained more below).

To handle objects that come from pegasus you simply define a callable object (function or SomeClass.__call__), this will be called when the appropriate op arrives from pegasus. A typical function definition would look like:

def look(op):

the function name called is determined by the first parent present in the incoming op.

When the op has been processed you should return a dict (or sequence of dicts) representation of the outgoing ops, all other return values are ignored.

3.3 Bugs and Limitations

Please note that entity registration currently uses the evil feature that info operations are parsed on their way out to register in-game ids, hopefully that won't work any longer when you read this. Also there are some evil id magic to allow reloading of the rim.

3.4 Development Helpers

I currently log all incoming and outgoing ops (to/from rimpython) to rimpython.log this can be extremely helpful when you're wondering where things bork.

To speed thing up I shortened the development cycle to edit-reload-test, to reload you need to /load debug (in silence-py) and /remote:reload, after that you need to recreate any characters so they will be registered again.