This is manual for the graphical version of DCSnake. But
most of applies to the text-mode version.
DosCore Snake 0.8 Manual
About
___ _____ ____ __
/ _ \___ ___ / ___/__ _______ / __/__ ___ _/ /_____
/ // / _ \(_-(/ /__/ _ \/ __/ -_) _\ \/ _ \/ _ `/ '_/ -_)
/____/\___/___/\___/\___/_/ \__/ /___/_//_/\_,_/_/\_\\__/
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|_|_|_|_|_| www.dcsnake.narod.ru |_|_|_|_|_|_|_|_|_|_|
|_| Version: 0.9 _ _ _ _ _ _ _ _ |_|
|_|_ _ _ _ _ _ _ _|_|_|_|_|_|_|_|_| For MS-DOS |_|
|_|_|_|_|_|_|_|_|_|_|An Ultimate|_| _ _|_|
_ _ _ _ _ _ _ _ _ |1| |_|_|
|_| |_|_|_|_|_|_|_|_|_ _ _ _ _ _ _|_|
|_|_ _ _ _ _|_|Multiplayer|_|_|_|2| |P| |3|_|_|_|
|_|_|_|_|_|_|_|Battleworm Simulator
You should carefully read this file to know of all the
features of the game and to be able to understand and use
them.
You can jump over this history section, especially since it
is under development is not readable yet...
History
HISTORY
The main idea of the game was derived from a very old Rus-
sian game "Russkaya zmayka" for Win 3.1. Once upon a time, I
lost this excelent game. Seven (or more) years later I de-
cided to write a similar one...
Handling the snake's motion was quite easy to implement. At
each step the head of the snake moves in a certain direction
(defined by the player) and the last snake's cell (e. g.
it's tale) is cleared so that the next to last cell becomes
last. Sometimes (for example, when the snake runs into a
wall) the head should not be moved, and sometimes (for exam-
ple, if the snake has eaten a prize) the tale doesn't shift.
To check collisions with walls and other snakes I embeded a
two-dimensional array whose elements denoted the contents
the correcponding map cells. Now the handling of motion had
to include the modification of map-array elements connected
to the motion of the snake, and collision checking.
But there was a bigger problem: keyboard handling. In Turbo
Pascal I knew the readkey procedure which returned the last
key in the keyboard buffer. Hence, I couldn't check for a
key if it is pressed. The keyboard buffer is like a single-
line where you type and sometimes press backspace which de-
notes reading a key and deleteng it from the buffer. My
friend Peter proposed a way to use this function for con-
trolling the snake. I the procedure responsible for the
snake's motion I called this function once and then changed
the direction accordingly tothe read key. If no key was
read, the direction was not changed. This worked well. Of
course, to control a snake you didn't need to press keys for
a long time. You just needed to "type" the desired key for
it to be read by the readkey
function.
When testing the game on various computers I found that it's
text menu is displayed in different textmodes, so that the
splashscreen made by Peter for the game didn't look as it
had been conceived. To fix this, I decided to display menu
in graph mode. For this purpose I created text functions for
graph mode analogue to those of the CRT unit (for text
mode). Fortunately, the Graph unit had a procedure for
printing a character at the desired place on the screen.
Usin this procedure I created an analog of the CRT unit for
graph mode. Since this time the game have become fully
graphical.
A grandiose epic was our (with Peter) struggle anainst one
stubborn bug. The bug was the following: sometimes (mainly
when the snakes were combatting at a close distance, trying
to envolve the enemy into their long bodies and, if that was
not a success, to make the opponent lose some cells or at
least force the enemy back to a bad position) near the head
of a snake insted of one of it's cells appeared a black
cell, which wasn't moving, so it seemed that the snake was
crowling through this black cell. When it finally creeped
throug it, nothing resembled about this strange cell. On the
place where it had appeared there were nothig. It was free
of obstacles. Here I should note that as the strange cells,
the cells noting free space (the game is 2d, so read free
plains) were also black.
Of course, I turned to the source code, namely - to the
place where snake moves are performed. I examined the code
over and over, but I didn't find a place where a cell which
wasn't the tale was coloured black. Debugging was made even
harder due to the fact that this bug didn't like to show
himself very frequently. You could have played for 10-15
minutes and haven't seen it. So, after every chnge in the
code, I spent a lot of time before the computer playing DC-
Snake for 20-60 minutes waiting for the bug. And every time,
sooner or later, the bug came into view. Several times I
thought I had fixet it, but Peter or his companions at uni-
versity, found this bug.
Terrible as it is, it seemed that my changes made the bug
come out more and more rarely, but not disappear!
When debugging I didn't make an effort to write good code,
highly readable and optimal. I just "piled up" expressions
on expressions, yielding extremly complicated logical ex-
pressions, embranchments, and a multitude of additional
variables, with names, not corresponding to their purpose.
One time I made an umpteeth chamge to one of the many com-
plicated logical constructions, and, as I always had done,
began playing. I played for 30 minutes, than for an hour...
and there were no bug. For an umpteeth time I hoped that the
bug had been finally killed. I gave the new version to Pe-
ter, and he distributed it among the students of his group
at university. For several days there were no bugreports
concerning this bug. I breathed with relief.
But something terrible happened. I and Peter were playing
DCSnake. Several times we went into action with two bots.
The four snakes got entangled and coiled. And no bugs were
observed. We had already been playing for a quite long time,
when during one of such a melee, two snakes crossed! One
creeped through another as if it had had a hole in it's
body! A bit later I understood: i hadn't fixet the bug. I
had just hidden it. Now that empty clell had become colored,
but it was still empty. Oh no!
I examined the whole game code trying to find a place where
a cell is colored but is left empty. And... I was unsuccess-
full!
Then I decided to automotiaze the debugging process. Peter
wrote a procedure which, for every map cell, checked the
following: if the cell was black it swithced to the next
cell, otherwise it checked if the cell was empty. A colored
cell (not black) should never be empy, so if it turned to be
so, the procedure paused the game and showed the broken
cell. Now, to find the bug, a human sisn't have to con-
stently watch the game. You just needed to set the game to
the maximum speed, let bots play for all the snakes and
wait. That is where Peter's Bot aided in game developing...
Now it took 2-7 minutes to make sure the bug was alive. Now
I found that the broken cell always appeared on the place of
the first body cell of the snake (next to the head). With
this powerful bugtrapping instrument I continued the strug-
gle. I was searching the bug for about a week. Now I don't
remember if I really understood the cause of the bug and
what I did to fix it, but I did something in the snake mov-
ing procedure and the bug finally disappeared.
Another fun accident occured when debugging the Bot. The
problem was that the initial bot often algorythm made the
Bot to get caught in a loop. Not a loop in the algorythm,
but a trajectory loop. The Bot crawled as if it had been a
train put on a cycled railroad. His path was a closed line.
Peter designed an unnatural solution to this problem. In the
Bot code there is function which estimates how a given di-
rection is good for the next move. And every time the Bot
calls this function for three cells: the one to the left
from the head, the one to the right, and the one in front of
the head. The chosen direction is that for which he value
returned by the funtion is maximal. In order for the Bot not
to fall is a cycle Peter made the Bot to leave a tail area
behind the snake's tail - as if the snake was a slug and
left a slime trail behind itself. But that trail gradually
"evaporated" until the full disappearance. And the Bot algo-
rythm tried to choose a cell without that "footprint". Thus,
crawling in a cycle would imply creepeng on "marked" cells,
but the Bot now tried to avoid them. Evaporating rate could
be tuned.
But, for some reason, the Bot still was prone to cycling. To
debug it, Peter decided to draw in each map cell on the
screen the amount of the "slime" left by the Bot. Now we
could observe how the Bot left thaces and how they evapo-
rate. The amount os "slime" in a cell was denoted as the
height of the gray bar in it. No slime - no bar, a cell full
of slime was whole gray. The colors of snakes were not
drawn. So, we just drew the slime map. When we launched the
game with this built-in debugger we found that the slime
trails were not correct. But there was something much
stranger. From the snakes (on the slime map only their heads
could be seen), controlled by the Bot, gradually separated
two cells seen due to different amount of slime in them as
compared to the adjacent cells. And it seemed to us that the
two cells were moving on their own, independently of the AI-
controlled snakes. We got two ghosts on the screen! The pro-
gram no way could draw anything except the snakes. And there
were only two snakes! We were amazingly watching the ghosts
roaming on the screen and remembering fun bugs we had met
before. That was definetly the funniest. How many we had
seen, but a pair of ghost cells...
The explanation was trivial. I was disappointed when I un-
derstood. The ghosts were the tails of the snakes. It was a
pity.
But one day the time came to implement the two-player mode.
In every cycle I called my motion procedure for the first
and the second players. And initially I found that, strange
as it may seem, the game worked, both the snakes could be
controlled by the two players. And only in extremly rare
cases I felt that the key I had just pressed hadn't changed
the direction. This might be explained by the fact that
sometimes I didn't fully press keys because a was hurrying.
At that time I was occupied by a more noticeable problem. It
was such for me, a man who had played "Russkaya Zmeyka" for
win31. The point was that my game had a kind of unsymmetry
relative to the players. It the situation when the two
snakes were moving in the same direction and one of them was
just by the head ahead of the other, the leading snake might
turn towards the other snake so that the former would run
into the latter at one stroke. But this was possible only
when the leading snake was the first plaer's snake. Other-
wise, the leading snake couldn't do this, it run into the
first snake and lost one cell.
After thinking a while I understood how it happened. The
fact was that my motion procedure moved the snakes in a cer-
tain order: first, it moved the first player's snake and
then the second player's. That was the cause of he unsymme-
try. In the situation when the leading snake belonged to the
first player it could turn towards the other snake becuse
it's move was performed first, but in the other case it
couldn't because by the moment it tried to turn the other
snake had already moved and the heads of the two snakes were
side by side.
A solution was found. It was in changing the snakemoving or-
der according to who is the leading snake. But for this I
would need to write the code which would determine such
"critical" situations where the order of snake moves matters
and, if it does, correct it. But Peter proposed the follow-
ing method of snake moves order correction. The order was
defined by the order of key pressings of the players. Who
pressed a key first moved first. Who didn't press a key dur-
ing the current cycle had the lowest priority in moving.
This automatically corrected all unsymmetrical situations
(except the one when the snakes collide head to head).
But this method allowed chittering: in a critical situation
you could disturb the natural sneke moves order by fre-
quently pressing the key which corresponded to your current
direction (or to the opposite one). To fix it I decided to
check if the pressed key changed the direction. If it
didn't, it didn't participate in the "competition" for the
snake moving order.
And at that time only one key could be read during a cycle,
so, first to move in a cycle was tha player who pressed a
key. Of two keys pressed in the same cycle was read the last
one. That is why sometimes one noticed that his keys didn't
work. To eliminate this problem I used a string variable to
store all the keys pressed in a cycle in the order thay were
pressed. If the string had twp or more keys bolonging to the
same player I left the last key. After that I could easily
derive the order of snake moves and new directions.
Another problem with keyboard handling was the following. As
I have already said, of two control keys of the same player
pressed in the same cycle only the last was read. And if you
wanted to make a quick manuever, to turn around for example,
you had to press yur keys exactly one per cycle, not having
missed one, and not having pressed two keys in one. That is
quite hard.
Fast turning around:
1 ***************************X right
2 *************************** down
X
3 ******************
X********** left
I wanted that it was possible to press two or more keys in
one cycle in order for the keys to be read one after another
in the current and followinf cycles, one key per cycle. For
this purpose I created a keyboard buffer, with the help of
wich key sequences for every player were stored and executed
in following cycles.
Thus, using only the readkey function from the CRT unit I
made a comfortable keyboard handling for my realtime
multiplayer game. Now all pressed keys were read without
fail.
In parallel with this work Peter was working on the Map
Generetor and on the Bot (Computer Control for snakes). The
map generator was aimed to fill the game area with
obstacles, given the filling density. It was not a very hard
task for a primitive generator. However, a filled map
dramatically changes the gameplay, as we found it after
testing the Map Generator.
The Bot was even more important. Here is what Peter tells
about it and it's development.
REST
In the beginning this was a simple snake game. But now it
have become the full featured and highly customizable multi-
player flatworm simulator with AI players, running prizes,
and more.
It is the best snake game I have seen. And I say this not
because I am the author, but because I really think so
(however, it may be caused by my being the author ;). I made
a search in the web and tried some snake games, and, IMHO,
they all turned to be less interesting than mine. What do
you think, the User?
SOME FEATURES:
1. Up to 4 players can take part in the game. Up to four of
them can be AI controlled players (Bots). Now AI is at the
development stage, so we ask you to treat indulgently lots
of AI bugs and inform us of them.
2. The game doesn't come to the end if a snake runs into a
wall, another snake, or itself. In this case the snake's
head stops, but it's tail continues moving, so the snake
loses it's sections, until it's head begins to move. If a
snake has lost all it's sections it dies.
3. Arbitrary map size can be set.
4. It is possible to edit the map using the map editor
(mapedita.exe) or to automatically create random maps with
the map generator.
5. You can set arbitrary game speed, the speed being device-
independent.
RUNNING TIPS
This is a protected mode application. To run in under DOS,
you should run cwsdpmi.exe first.
Make sure that no files in the distributive have an
attribute read-only.
SETTINGS
After you run the game the following menu appears:
1. Start game
2. Number of players
3. Game speed
4. Bots settings
5. Map settings
6. Define keys
7. Other
8. Screen resolution
9. Quit
The item 9 do not require explanation.
1. Start game
After you press '1' the game screen will apear. But the
snake(s) will not move until you press any key (including
your control keys) to turn pause off. To turn pause on press
'p'.
2. Number of players. The total number of snakes taking part
in the game (including AI-controlled ones)
3. Game speed
This is the number of game steps per second. A step consists
of one move of each snake (by one cell).
4. Bots settings
4.1 Number of bots
If one bot is chosen it will control the first snake. Two
bots - the first and the second snakes. In order to play
without bots set this parameter to 0.
5. Map settings
5.1. Density of the map
The more this parameter is the more walls the map generator
generates. If you don't want the map generator to work set
this parameter to 0. If somebody have created a better map
generator let him send the algorithm to the authors.
5.2. Size of the map cells
Cells of which snakes consist are meant. In other words, the
more this parameter the less the map. It is defined in
pixels. Anyway The map is scaled to fit the screen.
This parameter can assume the following values:
+-------------+--------------+-------------+
| Resolution | Min. value | Max. value |
+-------------+--------------+-------------+
| 640x480 | 08 | 48 |
+-------------+--------------+-------------+
| 800x600 | 10 | 60 |
+-------------+--------------+-------------+
| 1024x768 | 13 | 76 |
+-------------+--------------+-------------+
If after you have changed the resolution and the map cell
size have become incorrect it will be automatically changed
to a correct value.
7. Other
7.1. Double head prize.
The probability of the fact that a prize has double head
bonus in it. When such a prize is eaten, the snake gains an
extra head instead of the tale. And in this state the snake
can easily switch the leading head, e.g. turn over. To do
this just press the key corresponding the direction opposite
to the current snake's direction. In tens of percents.
Allowed values: 0,1,2,..,10.
7.2. Double head steps
The number of steps which can be passed by a snake which
have eaten a double head prize until it becomes a normal
snake.
7.3 Vampire mode
If on, in case you have been hit by another snake you gain
as many sections as the snake, which hit you, loses.
7.4 Turn over prise.
The probability of the fact that if a snake eats the prise
all other snakes will turn over. In tens of percents.
7.5 Temporary immortality.
The probability of the fact that if a snake eats the prise
it will become immortal. If its hits an obstacle, it will
not loose it's sections. In tens of percents.
7.6 Number of immortality steps.
Number of steps in the game before an immortal snake becomes
mortal.
7.7 Transparent walls.
If on, when a snake hits a border of the map its head is
teleported to the opposite border. (Cycled space). This
drastically changes gameplay.
7.8 Keyboard buffering.
It's function can be explained in the following example.
Your snake is crawling left. To turn over you need to turn
up (or down) and, then, right. You press the keys up and
right very quckly. Without keyboard buffering, it may happen
that your snake won't do anything, because you pressed the
keys during the same game step, and only the latest pressed
key will be treated. But (if your snake is not double
headed) a snake can not change direction to the opposite at
once. And, nothing will happen. Keyboard buffering fixes
this.
7.a Relative control. [Under Development] When on the snake
is controlled only by two keys: left and right. The
direction is defined relative to the snake's current
direction.
8. Screen resoluton.
!!!New resolution will be applied after you restart the
game. Do not set a resolution other that 640x480 unless you
have troubles with it. For example, if you have an LCD with
another native resolution.
Colors of snakes:
1. Magenta
2. Green
3. Red
4. Yellow
To know the control keys just choose Define keys from the
main menu. Here press a number 1..4 to define the keys for
the corresponding player or 9 to exit this menu.
Default control keys:
Left Right Up Down
1: a d w s
2: 4 6 8 5 ----On the numeric keypad
3: j l i k With NumLock ON
4: f h t g
If Running Prize is off, the prize can be controlled by the
cursor keys and the key '/' puts a shield.
DURING THE GAME
'p' - pause on/off
Escape - finish the battle and return to the main menu.
USING THE MAP EDITOR
1. Run mapedita.exe
2. The map editor creates the map with the size which is set
in the 'Size of the map cell' in the game menu. So before
you create a map set the desirable size.
3. The cursor can be moved by keys 8, 4, 5, 6 of the numeric
keypad with numlock on.
4. The editor creates only vertical and horizontal walls. To
create a wall set the cursor where you want the beginning of
the wall to be, press 's', set the cursor where you want the
end of the weall to be and press 's' again.
5. To enter the delete mode press 'd'. The cursor will
become blue. The process of deleting walls is equal to that
of creating walls in the drawing mode.
6. To clear the entire map press 'c'.
7. To save the map and exit press '0' (nil).
8. Do not create walls to limit the screen area. They are
created automatically.
Be free to send us all questions, proposals, bug reports and
advices.
And I will be very glad if you send us this manual with
corrected contents, grammar and spelling mistakes.
If you have an idea of the AI for this game consult with me.
I will explain what information AI must receive from the
game and what information it must give the game. I can help
you with realizing your algorithm and including it in the
game.
Any feedback will be appreciated.
Sorry, for my English and for spelling mistakes. That is on
account of my symbol generator which sometimes does not
support the required typematic delay.
Anton Shepelev.
22.01.05 0:50:37
|