Name: | Beasts |
---|---|
Version: | 991004 |
Authors: | Kevin Turner |
License: | Free |
Operating System: | Linux and other Unixes |
Website: | http://www.oberlin.edu/~kturner/linux/ |
Every gamer, who has been playing for a couple of years, fondly remembers some of his old games. Invariably game programmers attempt to recreate these classics. Beasts is Kevin Turner's remake of one such game (1). Like many older games the premise is simple yet captivating. "Push the blocks around and squish the beasts."
Beasts is not currently being developed. The web site lists it as just barely playable. I'd have to agree with the author's assessment. Having never played the original game, I had no understanding of the game rules. No text or online documentation is included with beasts. Instead the instructions can only be deciphered from the source code.
When the game starts a playing field slightly smaller than the terminal size is created. This area is filled randomly with blocks, walls, and holes. The walls are immovable. Any number of blocks can be pushed by the hero into empty or hole squares. The holes are permanent and destroy any block pushed into them. There are six beasties which appear as large 'H's. The player's character is drawn as a '<>'. Movement is controlled by the arrow keys or number pad(2). The level is beaten by killing all the beasties. The easiest way to kill a beast is to crush it between a block and another object. The other object can even be another beast. Otherwise the hero can trap the monster which will eventually cause the monster to explode. Whether you beat the level or are killed by the opponents, the program exits without any message.
The beast-play.patch(3)
makes the player continue until death. There is no score or level
indicator. The game does keep track of the level number so it would not be
too hard to output it. The levels are generated in the exact same manner
currently. By adjusting the block percentage and number of beasties, the
levels could be made progressively more difficult. Since the playing field
is increased depending on the terminal screen size, players with large
terminal are more likely to start far away from the monsters. To keep
consistent difficulty the level could be limited to a specific size or the
number of beasts could be a percentage of the playing area. Also the
endlevel
function takes a text message about the reason for
death which is currently ignored.
One additional game play issue deserves special attention. The player should never feel cheated by the game. If there is a trap, the designer needs to provide some way for the player to spot it. Even if he doesn't see it the first time, he'll blame himself for not spotting the clue. In beasts, the hero's start position is randomly generated and could be right next to a monster. Unless the player spots the character right away and begins moving, the beast will kill him.
Games generally have a central game loop. The game loop checks for input,
performs the requested action, moves enemies and repeats.
ConsoleLoop
, the game loop in Beasts, skips moving the enemies.
Instead an alarm signal, SIGALRM
, is generated every 1/6 of a
second. The alarm stops regular program execution and calls
beastie_call
. beastie_call
moves the beasts then
returns control to the interrupted section of code.
There are two important considerations when creating a game core such as this. The first is that there is no limit to the player's ability to enter actions. Faster machines will, in theory, allow the player to enter more commands in 1/6 of a second than a slower machine. Thankfully players will probably never notice since keyboard input and repeat rates haven't increased with the faster machines. You see the program will receive one keystroke for every key press and release combination or multiple keystrokes when the key is held but this rate is already fixed by other software. By relaying on the input rate of the keyboard the program runs at a fixed speed but there is no simple way to add joystick support. The joystick only knows the current status. So where the keyboard might not return a keystroke right away even if the key is currently being held, the only information the joystick has to return is the position.
The second problem is that signals will interrupt code without any
discrimination. For example moving the hero involves erasing the old
position and drawing the new position. So if the alarm activates just after
the old position is erased but the new position isn't drawn yet, the hero
lives despite being attacked by the beastie. This
patch solves the issue by use of the
sigprocmask
function. Before the character is allowed to move
sigprocmask
is used to block alarm signals. Upon completion of
the movement the signal is unblocked which allows any pending alarm to be
processed.
There are four different types of beasts. The current game has no
difference between the various creatures but provides some hints. The
pusher beast probably attempts to crush the hero in the same method he
crushes the beasts. The Beastie
structure includes an
unused field preggers
which is probably intended for the
momma beast to spawn more creatures.
The game appears to have been designed so that the user interface can be
swapped out easily. Instead of using ncurses, an X windows version complete
with graphics could be used. Unfortunately the initial groundwork for
this ability has been commented out. This
patch(3) restores the code
and expands it a bit but doesn't add any new user interfaces. The author
lists a gnome_canvas
version as something he'd like to see.
Another possible enhancement is to move the user interface code to a dynamic
library and allow the user to choose at run time which mode to use.
I watched the movement of the beasts in the program for some time before looking carefully at the code. From my observation it seemed like the monsters occasionally moved faster. The code provides a simple explanation to the fast beasts. As mentioned early every 1/6 of a second, an enemy attempts to move. After all the monsters attempt to move a turn counter is incremented. The beasts store the last turn that they moved so that if one beast is blocked by another but the second has not moved, he can be asked to try. The perceived faster movement could be caused by the monster moving, the turn completing, and the monster being asked to get out of the way.
Further investigation found that this wasn't the case. They were in fact
moving faster. Although the lastmoved
attribute is properly
set when a beast is asked to move, it isn't checked when the creature's
original movement phase occurs. This patch
prevents the beasts from moving twice. One thing to consider though is
that these type of bugs are fairly common in old arcade and computer games.
The remakes that "fix" the bugs aren't usually liked by players because of
the missing problems. Games don't need perfect algorithms and awe
inspiring graphics to reach that nebulously quality "fun".
(1) The original game was written and developed by Dan Baker, Alan Brown, Mark Hamilton, and Derrick Shadel. It's licensing status is unknown but it is listed on the "GigaGames" CD from cdrom.com.
(2) There are other keys that can function for movement as well. The number pad or arrow keys are probably the easiest. Although the end key which should go down and to the left doesn't return the appropriate keycode on my machine.
(3) Applying both the game play and drawing patch will cause patch to fail. Here's a combined patch.