Roguelike News

The articles in the Roguelike
Development Topic list have been
generously donated by very kind
individuals. All rights remain
with the authors.

Main | News | Development | Archives | Articles
Links | FAQs | Contact : rogue@skoardy.demon.co.uk
How To Write A Roguelike Game/Engine - Esa Ilari Vuokko [eivuokko@mbnet.fi].
		      Some ideas that could be useful ?
		       As shared by Esa Ilari Vuokko.
		Comments and bugfixes ;) to eivuokko@mbnet.fi



      I've played roguelike games for 7 years now. First I hacked Moria,
   which I got from friend (no modem or net connection :(). Then I got
   Omega which I still play (newer version, thought ;). At that time I
   got rid of Basic I was programming with and got Turbo Pascal. Well,
   I tried to do some pathetic games myself but they were just dead
   as they were real mode programs. Then (not earlier) I got nethack
   which I didn't like at that time. I hated djgpp (it's not bad, it's
   ugly in msdos) so I was bounded to real mode. Then I got Linux and
   installed it few times with no success (one time I installed it on
   broken hd, guess did it work, no - it just paniced suddenly ;). And
   I played ADOM, a lot. And then little Nethack and Omega.

      Because Linux I got all so mighty gcc and make. After playing for a
   while with graphics stuff (in linux and in win) and in winenv doing
   some accounting program (with delphi, thought I quitted after it
   started compiling wrong - I mean(debugged) it) I got an idea. In an
   accounting program we move money from one account to another (I'm sorry
   I know finnish terminology better than english). Well those accounts
   must be linked list because : they must be easy to create, modify and
   delete. Nothing new - a linked list. Of course all objects in rg should
   be in linked lists. But the what if even attributes were linked lists ?
   So that we had a linked list which can store data (some 16 bytes is enough)
   and a name (string) and children list.

      Listing attributes, skills, and everything that describes object with
   such presentation would be quite flexible. But if one does such game,
   and many people contribute to it ? It can go way off road as everybody
   add something new. A bloated memory use, and unneeded complexity are
   real threats. As normally, say ADOM, player char needs more memory
   (more variables) than npc. But in this approach we give npc only those
   skills and attributes it needs and we are still able to use same routines
   on both, player and npc.

      Of course above system can be optimized. I've defined it like this :
   Okey, I've got a bit more complex.
         class List {
	   private:
	         List *child,*next,*parent;
		 int id;
		 int data[4];
		 Link(List *);
		 Unlink(List *);
		 Query(int,int,int,int,int);
	  public:
		 int *Data();
		 char *Name();
		 int *Data(char *);
	         List *Name(char *);
		 int *Data(int,int,int,int,int);
		 List *Name(int,int,int,int,int);
		 Item *Index(int);
		 int Index(Item *);
		 int Count();
		 List *Add();
		 List *Remove();
         } ;
      Quite clear, I think. Id can be converted (by another class) to char.
   Almost all ints are for quick query. I use dot as delimiter between child
   and parent and I don't have plurals.  "skill.weapon.blade.short".

      Then I wanted an engine that doesn't need special cases. It would be
   (sorry for saying this) stupid to do special levels, which have special
   if of switch statement in level code. How could one have such a really
   flexible system ? Well I read Thomas Biskup's ideas of JADE. I don't know
   whetever he meant the same as I with the mentioning everything to be
   event based. So what I'm chasing here is that every object should have
   message handler list, which would handle requests to do something.

     Say we have a character A. A has handler list of next functions
   (stacked):
       creature_shield_deflector,
       creature_ro_poison_res,
       creature_basic_poison,
       player_non_ai,
       basic_creature_handler.

   First a monster(mage) B would shoot an firebolt to A. Firebolt code would
   send a message to A that some fire damage is  coming. First this message 
   would reach first handler in list, creature_shield_deflector. That would 
   say "no,no fire damage" and that would be it, no damage to creature. Then
   B would throw a acidbolt. Well this time deflector would say nothing as 
   wouldn't other before basic_creature_handler. That would make some damage 
   to creature and spare some to inventory too (and send approciate messages 
   to items). Then would engine send TIMEUPDATE to creature, which would be 
   handled first by creature_basic_poison. Well it seems this creature has 
   poisoning and handler would notice that it just ending. First it sends to 
   creature A (self) damage message of poison, which would end to 
   creature_ro_poison_res, and no damage. Then it would return 
   UNLINK_AND_CONTINUE so that it would be removed from list and message 
   (TIMEUPDATE) would be sent on. Then message would reach basic_handler which
   would add some speed to energy (ADOM) or add a timepulse (nethack,angband).
   If it would be creature's turn to move, it would send message ACTION to 
   itself (creature A). That would be caught by player_non_ai which would wait 
   for keypress and then do whatever is defined and player wishes to do.

      Because paragraph above seems a bit unclear ;) I'll do an easier
   table here :
      1 creature_shield_deflector,
      2 creature_ro_poison_res,
      3 creature_basic_poison,
      4 player_non_ai,
      5 basic_creature_handler.

   Messages :
     Fire damage
       1 - take message (do nothing) return KEEP_AND_STOP -> that's it.
     Acid damage
       1 - no action, return KEEP_AND_CONTINUE
       2 - no action, return KEEP_AND_CONTINUE
       3 - no action, return KEEP_AND_CONTINUE
       4 - no action, return KEEP_AND_CONTINUE
       5 - Share damage to creature and inventory, send damage message to
           inventory. Return KEEP_AND_STOP.
     TIMEUPDATE
       1 - no action, return KEEP_AND_CONTINUE
       2 - no action, return KEEP_AND_CONTINUE
       3 - Check if it's poison time. If it is send poison damage to self:
              Poison damage
                1 - no action, return KEEP_AND_CONTINUE
		2 - Take message (do nothing) and return KEEP_AND_STOP.
	   If poison is diluted enough return UNLINK_AND_CONTINUE
	   else return KEEP_AND_CONTINUE
       4 - no action return KEEP_AND_CONTINUE
       5 - Check whetever it's time to move or not (some way to count time
           compared to time). If it is send ACTION to self.
              ACTION
                1 - no action, return KEEP_AND_CONTINUE
                2 - no action, return KEEP_AND_CONTINUE
                3 - no action, return KEEP_AND_CONTINUE
                4 - Normal player's turn in roguelike games.
	   return KEEP_AND_STOP.

      KEEP_AND_CONTINUE, UNLINK_AND_STOP etc mean whatever function which
   handles handler lists should keep sending message on in list and if
   handler should be removed from list.


      Yes, I know, this is really heavy way to do things. But if we can count
   on fast 486, it is REALLY flexible. I think that with handlers lists and
   description lists we can mimic any game we want or make just about anything
   we want (well world conquest is a _bit_ hard maybe, but as rg game anything)

      I'm sorry if there's too many errors in my english. I didn't mean to
   be offensive either but I needed to make my point clear (if it can be
   done at all). If someone has implemented this allready, good, sorry to
   say that I were to late.

      I'm sorry if there is something that have been published before and
   I don't want to claim that I've been first to thing this kind of things
   but I haven't seen anything like this before (I haven't read too much).
   Anyway Copyright 2000 Esa Ilari Vuokko. I don't (of course) take any
   responsibility of anything you do or don't do with this text. It can be
   freely copied and published electronically as long as it isn't modified.
© Copyright 2000 Darren Hebden.