Open Game Source: Beasts

by Dennis Payne

Name: Beasts
Version: 991004
Authors: Kevin Turner
License: Free
Operating System: Linux and other Unixes
Website: http://www.oberlin.edu/~kturner/linux/

Game

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."

Mostly Playable

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.

Loopty Loop

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.

Unimplemented

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.

Marines, We Are Leaving

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".

Footnotes

(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.

Back to OGS


Copyright (c) 2000 Dennis Payne / Identical Software