**************
* Magic Maze *
**************

Written by Martijn van Iersel & Jules Beulen
for allegro speedhack competition 2001

e-mail: amarillion@yahoo.com, ikkejb@netscape.net
binaries will be uploaded at: www.student.wau.nl\~martijni

The morning after...

Well, waking up the morning after i realized that i should have written
a bit more in the original readme.txt, but when i was writing i was too
tired too think well. So in this version there is some more information
on the game, and some information on things that are not in the game.
Don't think that this is in any way me trying to "social engineer" my
way to the first place (:

CONTENTS

  compiling
  playing 
  bugfix 
  time spent  
  game story
  to do list 
  explanation of the code, files and the AI
  references
  undocumented controls

First of all, the original readme.

COMPILING THE GAME

I've included make.bat to compile the game. This works in DOS (or in
dos-box) if you have gcc in your path. Start make.bat from the
directory it is in. I didn't test it on other platforms, and to be
hounest, i have no clue which problems could arise when compiling in
other platforms, so i could take no measures against them on beforehand.

PLAYING THE GAME

The help-page that is written in-game was also written on sunday at
6:00 (so that's really monday, but for me it counts as sunday), and i
think i could have been clearer. Here is an attempt:

There can be one to four players in the game, either controlled by a
human or a computer. In the start menu, you can use the keys 1 to 4
to change the type of each player. When you press enter, a game
session starts.

The board flips over and you get to see a complicated maze.
You see reddish squares, which are walls, and black lanes, which are
walkable. Also you see brightly coloured (humanoid) figures, and
even insanely coloured little circles. Well, the figures are the
players, and the rounds are the treasures (or coins, if you want).

Now each player gets a turn. In the beginning of your turn, you get
to change the maze. You can see a small piece of maze "sticking out" of
the board. If you press left/right, you can make that piece move
around the board. When you press up/down, you can make the piece
rotate 90 degrees. When you press enter, the piece is pushed in
the maze, thus making a whole column of the maze shift. If you do
this in a clever way, new passages open up. You can reach places
you could not reach before, and maybe you can even reach the treasure!

Note that, however, you can not shift every column of the maze. On
the 7x7 board, you can only push your free piece in rows/columns 2, 4
and 6. This means there are parts of the board that can never be
moved. Luckily, all these parts are T-crossings! Note also that if your
slide has caused a player or treasure to fall off the maze, it appears
back again at the other side of the maze. You can make clever use of this!

After the change-the-maze-magically turn, you get a move-your-guy turn.
Use the cursor keys to move your guy to the treasure. If you get there,
a new treasure appears, and your turn ends. If you cannot reach the
treasure, you have to press ENTER to end your turn.

The game has ended when one player has collected 10 treasures. You get
a score based on the number of treasures and the playing time. You even
can get a hi-score if you did not win, especially if a computer player
wins, because computer players don't get to get into the hi-score table.

BUGFIX

A small bugfix. I found that there is a small bug making it impossible to
enter your name because it doesn't empty the keyboard buffer after the
game ends (and the last key you pressed in the game will always be ENTER).
This will be solved by putting the following lines somewhere in main ().
If you don't do this, the program won't ask for your name to enter in
the hi-score table, but just puts an empty string in it.

    while (keypressed()) readkey (); // bugfix

also there is this line to restore the palette:

    definecolors(); // bugfix

and in draw_menu this line needs to be changed to print the right player
numbers in the menu (guess i was thinking pascal-style again...)

    textprintf (buffer, font, 96, 96 + 32 * i, 1, "%d", i + 1); // bugfix

Of course you don't have to go through the code and fix these things
yourself, i'm only stating this because i've changed this after the
competition ended.

These bugs are due to having to write the code for the hi-score at
mondaymorning at 6:00.

TIME SPENT

This is how much time I needed programming this

friday: 13:00 - 17:00, 19:00 - 2:00
saturday: no time spent at all, because i went to my parents and
enjoyed a classical concert with them...
sunday: first a meeting with Jules, back to coding at 15:00 - 18:00
and then 19:00 - 9:00. Whew, that was a very long night.

So in total I worked about 24 hours on the game. One whole day!

I don't know exactly about Jules, I know he didn't work
much on it on friday, saturday from 23:00 - 4:00 and sunday some
in the afternoon and in the evening until about 2:00 but
i don't know exactly.

GAME STORY (OR WHAT I WANTED TO PUT IN THE GAME)

Jules and i came up with a bit of game story (for a puzzle game?
yes indeed...), but we had not much time to implement it (and i'm
still looking for a good translation for the dutch title).
Actually if we had implemented it, we would have had a very
original edge to the donkey, but alas... Well the story is
based on a dutch fairytale (or is there also an english version
of it? I don't know).

------------------------------------------------------
tafeltje dek je, ezeltje strek je, knuppel uit de zak.

This a tale about three brothers. It was about the time for them to learn
a trade, so their father sent his oldest son to work as an apprentice
for a very good carpenter. In fact, he was the best carpenter in the
world, and the first brother learned a lot from him.

After three years,  his apprenticehood was over and as a goodbye-present
the carpenter gave the first brother a table. "Dude, what is so
cool about this table?" said the first son, because he saw nothing
special to it. "Pay attention, you will see" said the carpenter. He
said the magic words "Tafeltje dek je", and behold,  the table was
instantly set with the finest foodstuffs and beverages. "Wow, that
is much better than MacDonalds you know, thanks dude" said the first
son and he went off.

It was a long way home and the first son had to stay in an inn.
It was very late, but the innkeeper said that it was ok he could stay,
but there was no food anymore. "No problemo" said the first son,
"i've got this  really cool magic table to take care of that."
So he said "tafeltje dek je". The innkeeper thought it was a really
cool table indeed, in fact he thought it was so cool he decided
to steal it. So that night he swapped the table for an ordinary
table, to the utmost disappointment of the first son when he
came home and found out.

This was the time for the second son to learn a trade, and became an
apprentice for a miller (the best one in the world). He learned everything
there was to know about milling, and after three years he was done.
As a good-bye present the miller (the best one in the world) gave
the second son a donkey. "Awesome", a real donkey" exclaimed the
second son. But the miller said "wait, there is more to it" and he
uttered the magic words "ezeltje strek je" and behold, the donkey
brayed and a gold coin came out under his tail. "Wow this is cool"
said the second son. "Well, see you later allegator"

But he had to travel a long way too, and he (really coincedentally)
had to stop over in exactly the same inn. The innkeeper said that it
was ok, "but that's gonna cost ya". "No problemo dude", said the
second son "Watch the donkey" And he uttered the magic words "ezeltje
strek je" and the innkeeper received instant payment. The innkeeper
agreed that this was indeed a cool donkey, and he just happened to
have one that looked exactly like this one. You can imagine how
disappointed the second son was when he found out when coming home
that his magic donkey ran out of gold.

In the mean time, the third son had become an apprentice to a
baker (and yes, the very best one in the world). He heard what had
happened to the two other sons and thought "well, that is just a
real bummer". When he told his master he agreed, and he said: "Well,
it is just time for you to quit here anyway, so i'm going
to give you this bag. When you say the magic words: knuppel uit
de zak, a club will come out of it and beat the hell
out of anyone you want". "Wow peace dude", said the second son.
"Hey that is actually a good idea. Well I gotta split"

So later that day the third son arrived at exactly the same
inn. It was alright he could stay, said the innkeeper.
"But what's in the bag?" "I'aint gonna tell you dude",
said the third son "but it is most definitely the most
coolest treasure in the universe". I have to get that,
thought the innkeeper, and that night he crept into the third
son's room. But the third son wasn't sleeping, and the moment
he opened the bag, the son shouted "knuppel uit de zak" and
the club came out and started beating the innkeeper until he
promised to give the table and the donkey back.

End good, all good.

So what can we learn from this?
THAT I WANTED TO DO TOO MUCH IN JUST THREE DAYS!

So the edge to the game will be, that the treasures that appear
in the maze randomly are actually falling into it from the donkey
that is above.
That is why you hear a braying sound everytime a new treasure
appears. The four players would be the three sons and the inkeeper,
trying to grab the coins as quickly as possible. I would use a
particle system to let the coins drop and bounce a little when
they are falling into the maze.

The ad in the game would have been an ad for "de efteling", a theme
park in which this fairytale is depicted (the best theme
park in the world!). I would have put it on the back of the
game board, showing it at the end of the game when the board
is flipping over. But i didn't have time to find out how to
know which side of the board is showing.

TO DO LIST (OR OTHER THINGS THAT I STILL WANT TO PUT IN THE GAME)

The game is too easy, especially for computer players (i had to
make the AI more dumb or it would be no fun playing against the
computer). This could be solved by changing two things

- more corners in the game (as opposed to straights and t-crossings)
- do not allow to move the same column in the same direction twice in a row

I checked the original board game "de betoverde doolhof" and
these two changes are actually in that game too.

- make it possible to play in a larger maze (very small change needed)
- graphics for the three sons and the innkeeper
- particle engine for the dropping coins

EXPLANATION OF REQUIREMENTS

The puzzle genre: well, you have to think to win, so it is a
puzzle. Pressing keys randomly will get you nowhere.

The donkey: all there is to it, is the sound you hear when a new
treasure appears (see game story above).

The ad: sometimes when the computer is making a move, a message
appears at the top of the screen, saying which important foodstuff
companies helped in creating this game (Yes I know,
a bit corny, but it took only two minutes and twelve seconds to code)

The hi-score routine: it is working, except for this small bug
that doesn't let you enter your name. Oh well... The score is
calculated like this: treasures * 1000 / time. The computer players
are not entered because they always win on time.

The particle engine: Some stars in the background. Took about twelve
minutes and thirty seconds to code (so even if you thought
it was cool, it is worth little credit)

EXPLANATION OF THE CODE AND FILES

well the code is a mess. I don't want to explain it. Well maybe
just a little. The way the code is modularized has nothing to do
with logic but more with the order the elements were made. Jules wanted
to do the hi-score and the menus, so i let him do main.cpp after which
i started with martijn.cpp. In this file is all the game logic. It
was almost entirely written on friday. Sunday i started to make the
3d.cpp module which contains all 3d drawing functions and which took
me a lot of time, because i never did any 3d stuff with allegro before.
The 3d.cpp was originally based on the excamera example, maybe you
can find some leftover pieces of code from it.
Also there is the scrshot.cpp module, which is very small and does nothing
but... take screenshots! All the other files are from the jgmod
library which is used to play a really cool C64 mod in the background.

EXPLANATION OF THE AI (ARTIFICIAL INTELLIGENCE)

This is I think the most interesting part of the game and that is
why i'm going to explain it a little. The board is set up in the
following way:

int map[7][7]

and for each cell the value is calculated like this:

0 + (1 if you can move north)  + (2 if you can move east ) +
(4 if you can move south) + (8 if you can move west).
So this is in fact a bitfield in which each bit represents a direction.

When the computer has to make a move, the function comp_magic_turn is
called. (not about names: magic_turn is the part of the turn in
which you slide columns, move_turn is the part in which
you move your guy)
comp_magic_turn does all the AI. It does the following:

- for each possible move (for a board of size 7x7, there
are 48 possible moves):

- copy the original board
- do the possible move by calling do_magic_turn
- score the new maze by calling get_access_table. 
This function returns a new board (int access[7][7]) in which each
value represents either: -0 if this cell is not accessible by the
current player or -a value to represent the number of cells that are
closer to the starting point than this one.
- if it is possible to get the treasure in one turn, than this
board is scored maximum, otherwise the board gets the number of
accesible cells as score.

In fact the AI analyses only about 25% of the moves this way. Which moves
to check is determined randomly. This restriction is done to make
the AI more stupid.

- after the board with the highest score is picked,
the target is determined, this is either the treasure itself, or a
spot which is the nearest one to the treasure.
- then the access table is replaced with a direction table. In this
table, each cell that is in the path from start to target,
gets a number which represents the direction which you have to take
to get to the target. All other cells get a 0. This path is calculated
very quickly by starting from the target, and looking for the adjacent
cell with the lowest number in the access table (remember that this
number represents the number of cells that are closer to the starting
point than this one).

That's all. CLEVER HUH? That's what I wanted to hear...

REFERENCES (STUFF THAT I WISH TO BE ABLE TO CREATE MYSELF)

The following stuff was not of my own creation
- donkey sound: http://www.vionline.com/sound.html
- the music playing: some C64-sound site, I don't know which
because Jules dug this one up. If you really want to know you'll
have to ask him (:
- module playing library: JGMOD (downloadable at allegro.cc)

UNDOCUMENTED CONTROLS (THEY ARE DOCUMENTED NOW, ARENT'T THEY?)

The 3D.cpp file was originally based on the excamera example. Actually
there is some bit of code left in it, amoungs others the controls.
Here are they:

a/A: change aspect ratio
r/R: rotate the board
f/F: change field of view
pgup/pgdown: pitch (flip the board over)

and I added

b/B: change the point which is in the center of view (base_offset).
F1: make a screenshot, stored as ss??????.pcx

There might be more which I forgot

See ya

Martijn van Iersel
