wiki:WikiStart

Version 5 (modified by pulkomandy, 11 months ago) ( diff )

--

Readingame

My notes about rewriting an engine for the Lectures Enjeu game.

This is a "choose your adventure" game (in French) designed for teaching kids how to learn.

Some of the adventures were initially published as books by schoolchildren, and adapted into electronic versions here.

I remember playing this at school as a kid, and recently I decided to take a closer look at how it works. Maybe I will get as far as rewriting an engine for it so the games can be played on modern systems?

Game files

Each game scenario is made of INIT.DAT, MSG.DAT, MSGGEN.DAT, CONDGALE.DAT, CONDSAL.DAT, CONDULTI.DAT.

All files are generally composed of chunks starting with a 16-bit size (self-including) followed by some data. A 16-bit 0 serves as a terminator chunk. The cunks do not appear to have an explicit type marker.

Message files

These two files contain the various messages that can be displayed during the adventure.

The messages are split by "room" chunks.

The first 16-bit word indicate the "room" chunk size

The single-page messages chunks are made of a size, followed by a NULL terminated string.

The complex messages chunks are made of a size, followed by more sub-chunks. Each sub-chunk is itself a size + a null terminated string.

The strings can contain various escape sequences:

%p - Replaced by the player's first name
%b - To insert an inline button (followed by a button ID)
\o - Insert an "Ok" button centered on the last line.
[NSome text] - Hyperlinks
{%f3|%m2~%m3} - Conditionals, if variable f3 is 0, show m2, else show m3
{%f6|%m6~\o1} - The contents of the condition doesn't have to be a message
{%c1|%m1|%m2|%m3~%m4} - Show message 1 if c1 is 0, message 2 if it is 1, etc.

Variables

This tells us a few things:

  • %m variables refer to submessages in a complex message
  • %f variables refer to boolean flags (such as owning or not owning an object)
  • %c variables refer to counters (such as health points)

where N is an identifier for the link (it's not a room number, since it can trigger other actions, picking items, moving to subrooms, ...)

Ok button

The \o sequence can be on its own at the end of the string, or suffixed with an ASCII encoded number. In that case the number seems to indicate which substring to show next.

TODO: in some games you can move north/south/east/west and up/down, how is thins handled? This is not used in Le Mystère des Lunettes which I have studied now (because it is simpler).

MSGGEN.DAT

MSGGEN.DAT is similar, but contains a single "room" with global ("general") messages that can be triggered from any room (such as global buttons or using objects).

Rehex script

Here is a rehex script to parse these files:

LittleEndian();

// Simple string chunks are defined by a size (self-including) and a
// string (NULL terminated)
struct lenstring
{
	uint16_t len;
	local uint16_t realLen = len - 2;
	char string[realLen];
};

// Room chunks have a size and are filled by string chunks
struct ROOM
{
	local uint16_t start = FTell();

	uint16_t sizeInBytes;

	struct lenstring substrings[0];
	while (FTell() - start < sizeInBytes)
	{
		ArrayExtend(substrings);
	}
};

struct ROOM rooms[0];

while(!FEof())
{
	ArrayExtend(rooms);
}

Open questions

  • How to determine which room to start the game in?
  • How to determine the action for hyperlinks?
  • How to associate an object with an action?
  • How to initialize the flags and counters?
Note: See TracWiki for help on using the wiki.