BDCFF Object 000A: Amoeba

Object number: $000A
Game class: Boulder Dash (by Peter Liepa)
Object name: Amoeba

In this document:


Properties

Animate: yes
Impact explosive: no
Chain explosion action: consumed
Explosion type: n/a
Rounded: no


Attributes

Attribute format: %00000000 00000000

There are no attributes for this object type.


Graphics

Amoeba animation sequence
This GIF shows the animation sequence of amoeba from the C64 implementation of Boulder Dash (hence the graphics are 8 double-width pixels wide and 16 pixels high).

Interactions with other objects

The boulder interacts with the following objects:

Specification

Amoeba is stuff that grows randomly. If trapped such that it can't grow any more, it "suffocates" and turns into diamonds. If it grows too large, it turns into boulders. Fireflies and butterflies will explode on contact with amoeba.

Every scan, a count is kept of how many amoeba have been found. For each amoeba found during the current scan, it does these things:

  1. If there were too many (see below) amoeba found in the scan during the last frame, the amoeba is considered to have grown too large, and so all amoeba found in this scan frame are quietly replaced with boulders.
  2. Failing that, if it was determined in the scan during the last frame that the amoeba was completely enclosed (could not grow), then each amoeba is quietly replaced with a diamond.
  3. Failing that, if there have been no amoeba found during the current scan that had the potential to grow, then a check is made to see whether this amoeba could grow. If it is possible for it to grow, then the flag is changed to indicate that there is at least one amoeba in existance that can grow during this frame.
  4. If the amoeba did not turn into a diamond or a boulder (in steps 1 or 2 above), it may or may not attempt to grow. A random number is generated to decide whether the amoeba will attempt grow: it has a 4/128 chance (about 3%) normally, or a 4/16 chance (25%) in some circumstances. If the decision is that the amoeba will atempt to grow, it randomly chooses one of the four directions to grow in. If that direction contains a space or dirt, the amoeba grows to fill that spot. The new amoeba just grown does not itself get the chance to grow until the next frame (ie the new amoeba is marked as "amoeba, scanned this frame").

How many is too many?

For the Commodore 64 implementation of Boulder Dash, "too many" amoeba (the point where they turn into boulders) is 200 or more. Since other implementations of Boulder Dash may permit cave sizes other than 40 x 22 (= 880 squares), I suggest that "too many" is defined as being 200/880 = 22.7% of the total number of squares available in the cave. In other words, once 22.7% or more of the cave is occupied by amoeba, it should turn into boulders.

When is it 3% and when 25%?

Initially, the amoeba growth probability is 4/128 (about 3%). Once the "amoeba slow growth time" has elapsed, the amoeba suddenly starts growing a lot quicker (amoeba growth probability = 25%). The "amoeba slow growth time" is set on a cave-by-cave basis, and is in seconds.

General Algorithm

procedure ScanAmoeba(in positionType positionOfAmoeba;
                     in integer anAmoebaRandomFactor;
                     in Boolean amoebaSuffocatedLastFrame;
                     inout Boolean atLeastOneAmoebaFoundThisFrameWhichCanGrow;
                     in integer totalAmoebaFoundLastFrame;
                     inout integer numberOfAmoebaFoundThisFrame) 
# Local variables
    directionType direction;
    positionType NewPosition;

    ASSERT(anAmoebaRandomFactor > 0);
    ASSERT(totalAmoebaFoundLastFrame > 0);
    ASSERT(numberOfAmoebaFoundThisFrame > 0);
    numberOfAmoebaFoundThisFrame++;

# If the amoeba grew too big last frame, morph into a boulder.
# kTooManyAmoeba = 200 for original Boulder Dash.
    if (totalAmoebaFoundLastFrame >= kTooManyAmoeba) then
        PlaceObject(objBoulder, attribStationary, positionOfAmoeba);
    else

# If the amoeba suffocated last frame, morph into a diamond
        if (amoebaSuffocatedLastFrame) then
            PlaceObject(objDiamond, attribStationary, positionOfAmoeba);
        else

# If we haven't yet found any amoeba this frame which can grow, we check to 
# see whether this particular amoeba can grow.
            if (not atLeastOneAmoebaFoundThisFrameWhichCanGrow) then
                foreach direction in (up1, left1, right1, down1) do
                    if (GetObjectAtPosition(GetRelativePosition(positionOfAmoeba, direction)) in {objSpace, objDirt}) then
                        atLeastOneAmoebaFoundThisFrameWhichCanGrow := true;
                    endif
                endforeach
            endif

# If this amoeba decides to attempt to grow, it randomly chooses a direction, 
# and if it can grow in that direction, does so.
            if (AmoebaRandomlyDecidesToGrow(anAmoebaRandomFactor)) then
                direction := GetRandomDirection();
                NewPosition = GetRelativePosition(positionOfAmoeba, direction);
                if (GetObjectAtPosition(NewPosition) in {objSpace, objDirt}) then
                    PlaceObject(objAmoeba, attribNone, NewPosition);
                endif
            endif
        endif
    endif 
endprocedure

####################

function AmoebaRandomlyDecidesToGrow(in integer anAmoebaRandomFactor):Boolean 
# Randomly decide whether this amoeba is going to attempt to grow or not. 
# anAmoebaRandomFactor should normally be 127 (slow growth) but sometimes is 
# changed to 15 (fast growth) if the amoeba has been alive too long.
    ASSERT(anAmoebaRandomFactor in {15, 127});
    return (GetRandomNumber(0, anAmoebaRandomFactor) < 4); 
endfunction

Web page design by Peter Broadribb