BDCFF Object 0000: Boulder

Object number: $0000
Game class: Boulder Dash (by Peter Liepa)
Object name: Boulder

In this document:


Properties

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


Attributes

Attribute format: %00000000 0000000a

a: Flag indicating whether the Boulder is currently considered to be "falling" or "stationary". The flag is set (1) when falling, clear (0) when stationary. It is recommended that all boulders begin life as stationary boulders.


Graphics

Boulder graphic
This GIF shows the graphic of a boulder from the C64 implementation of Boulder Dash (hence the graphic is 8 double-width pixels wide and 16 pixels high). The boulder does not have an animation sequence: it looks the same all the time.


Interactions with other objects

The boulder interacts with the following objects:

Specification

The boulder, like the diamond, is an object which falls, rolls off some other objects, and can explode some other objects when it hits them.

Falling

Falling through magic wall

If a falling boulder hits a magic wall, then:
  1. A sound is played: the sound is as of a diamondhitting something. This sound is played regardless of what happens next.
  2. If the magic wall was Dormant (a global attribute), the magic wall is now considered to be On.
  3. If the magic wall is now On then
A stationary boulder sitting on top of a magic wall does not activate the magic wall or move in any way (not even rolling off it).

Rolling

Note that both stationary and falling boulders can roll.

If a boulder is discovered to have a stationary, rounded object (stationary boulder, stationary diamond, brick wall) below it, then the boulder will attempt to roll off the object below. Note that falling boulders and diamonds can roll off things too; they don't have to come to a halt first.

In order for a boulder or diamond to roll, not only must the object below be a brick wall, stationary boulder or stationary diamond, but the objects to the left and diagonally left/down (or right and diagonally right/down) must both be space. Preference is given to rolling to the left over rolling to the right. If these criteria are satisfied, the boulder or diamond is moved one space immediately to the side (not diagonally down) and is changes state to be falling (if it wasn't already).

If the boulder is not able to roll, it remains where it is, and changes state into a stationary boulder (if it wasn't already).

Causing explosions

If a falling boulder hits an explosive object (firefly, butterfly, Rockford), then that object explodes, consuming the boulder in the explosion. The boulder itself does not explode.

General Algorithm

procedure ScanStationaryBoulder(in positionType boulderPosition) 
# Local variables
    positionType NewPosition;
    objectType theObjectBelow;

# If the boulder can fall, move it down and mark it as falling.
    NewPosition := GetRelativePosition(boulderPosition, down1);
    theObjectBelow := GetObjectAtPosition(NewPosition);
    if (theObjectBelow == objSpace) then
        PlaceObject(objBoulder, attribFalling, NewPosition);
        PlaceObject(objSpace, attribNone, boulderPosition);
        RequestSound(boulderSound); # yes, even when it starts falling. This applies to diamonds too (requests diamondSound).
    else

# Failing that, see if the boulder can roll
        if (CanRollOff(theObjectBelow)) then

# Try rolling left
            NewPosition := GetRelativePosition(boulderPosition, left1);
            if ((GetObjectAtPosition(NewPosition) == objSpace) and (GetObjectAtPosition(GetRelativePosition(boulderPosition, down1left)) == objSpace)) then
                PlaceObject(objBoulder, attribFalling, NewPosition);
                PlaceObject(objSpace, attribNone, boulderPosition);
            else

# Try rolling right
                NewPosition := GetRelativePosition(boulderPosition, right1);
                if ((GetObjectAtPosition(NewPosition) == objSpace) and (GetObjectAtPosition(GetRelativePosition(boulderPosition, down1right)) == objSpace)) then
                    PlaceObject(objBoulder, attribFalling, NewPosition);
                    PlaceObject(objSpace, attribNone, boulderPosition);
                endif
            endif
        endif
    endif 
endprocedure

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

procedure ScanFallingBoulder(in positionType boulderPosition;
                             in/out magicWallStatusType magicWallStatus) 
# Local variables
    positionType NewPosition;
    objectType theObjectBelow;

# If the boulder can continue to fall, move it down.
    NewPosition := GetRelativePosition(boulderPosition, down1);
    theObjectBelow := GetObjectAtPosition(NewPosition);
    if (theObjectBelow == objSpace) then
        PlaceObject(objBoulder, attribFalling, NewPosition);
        PlaceObject(objSpace, attribNone, boulderPosition);    # ie old position

# If the object below is a magic wall, we activate it (if it's off), and 
# morph into a diamond two spaces below if it's now active. If the wall 
# is expired, we just disappear (with a sound still though).
    elsif (theObjectBelow == objMagicWall) then
            if (magicWallStatus == kMagicWallOff) then
                magicWallStatus := kMagicWallOn);
            endif
            if (magicWallStatus == kMagicWallOn) then
                NewPosition := GetRelativePosition(boulderPositon, down2);
                if (GetObjectAtPosition(NewPosition) == objSpace) then
                    PlaceObject(objDiamond, attribFalling, NewPosition);
                endif
            endif
            PlaceObject(objSpace, attribNone, boulderPosition);
            RequestSound(diamondSound); # note: Diamond sound
        endif

# Failing that, we've hit something, so we play a sound and see if we can roll.
    else
        RequestSound(boulderSound);
        if (CanRollOff(theObjectBelow)) then

# Try rolling left
            NewPosition := GetRelativePosition(boulderPosition, left1);
            if ((GetObjectAtPosition(NewPosition) == objSpace) and (GetObjectAtPosition(GetRelativePosition(boulderPosition, down1left)) == objSpace)) then
                PlaceObject(objBoulder, attribFalling, NewPosition);
                PlaceObject(objSpace, attribNone, boulderPosition);
            else

# Try rolling right
                NewPosition := GetRelativePosition(boulderPosition, right1);
                if ((GetObjectAtPosition(NewPosition) == objSpace) and (GetObjectAtPosition(GetRelativePosition(boulderPosition, down1right)) == objSpace)) then
                    PlaceObject(objBoulder, attribFalling, NewPosition);
                    PlaceObject(objSpace, attribNone, boulderPosition);

# The boulder is sitting on an object which it could roll off, but it can't 
# roll, so it comes to a stop.
                else            
                    PlaceObject(objBoulder, attribStationary, boulderPosition);
                endif
            endif

# Failing all that, we see whether we've hit something explosive
        elsif (ImpactExplosive(theObjectBelow) then
            Explode(NewPosition, GetExplosionType(theObjectBelow));

# And lastly, failing everything, the boulder comes to a stop.
        else
            PlaceObject(objBoulder, attribStationary, boulderPosition);
        endif
    endif 
endprocedure

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

function CanRollOff(in objectType anObjectBelow):Boolean 
# If the specified object is one which a boulder or diamond can roll off, 
# return true otherwise return false.

# First of all, only objects which have the property of being "rounded" are
# are ones which things can roll off. Secondly, if the object is a boulder
# or diamond, the boulder or diamond must be stationary, not falling.

# We're going to assume that GetObjectProperty() automatically returns "true"
# for objBoulderStationary, objDiamondStationary, objBrickWall, and returns "false"
# for everything else (including objBoulderFalling and objDiamondFalling).

    return (GetObjectProperty(anObjectBelow, propertyRounded));
endfunction

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

function ImpactExplosive(in objectType anObject):Boolean 
# If the specified object has the property of being something that can
# explode, return true otherwise return false.
# ImpactExplosive objects are: Rockford, Firefly, Butterfly.
    return (GetObjectProperty(anObject, propertyImpactExplosive)); # true/false
endfunction

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

function GetExplosionType(in objectType anObject):explosionType;
# Assuming that the specified object is in fact explosive, returns the type
# of explosion (explodeToSpace or explodeToDiamonds)
# Explosive objects are: Rockford, Firefly, Butterfly.

    ASSERT (Explosive(anObjectBelow));
    
    return (GetObjectProperty(anObject, propertyExplosionType));
endfunction

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

Web page design by Peter Broadribb