In this document:
aa: Initial "facing" direction:
Fireflies are considered to be facing in one of four directions (up, down, left, right) although visually you can't tell which direction a firefly is currently facing by looking at it. Fireflies always like to turn to their left if possible (going round and round in circles if possible), failing that they will go forward, or finally they will turn to their right if they can't move forward.
In BoulderDash I (on the C64), fireflies always begin "facing left", meaning that they will make their first movement down if possible (because fireflies always try to turn left when possible). The C64 cave format allows you to specify the initial direction of each firefly individually, however all caves in the C64 BoulderDash I have their fireflies facing left to begin with. It is recommended that all fireflies begin life facing left.
The way a firefly works is this:
if (space to the firefly's left is empty) then
turn 90 degrees to firefly's left;
move one space in this new direction;
} else if (space ahead is empty) then
move one space forwards;
} else {
turn 90 degrees to the firefly's right;
_do not move_;
}
The key thing to note is that if a firefly is forced to turn against its
"preferred direction", it does not actually move for that frame.The result is that when a firefly can make a left turn, it will do so "instantly", but if forced to make a right turn, it will pause for one frame before doing so. If forced to turn around (180 degrees), it will pause for two frames before going back the way it came.
Because the check is made before the fly moves, you may momentarily see the fly next to an amoeba/Rockford for one frame before the explosion happens. Note that (unusually), the firefly will also explode if next to a "Rockford, scanned this frame". By "scanned this frame" I mean that Rockford has already moved once during this scan frame, and it is marked as such so that if the same Rockford is come across again in the same scan frame (because Rockford moved down or right) then the player won't have the opportinity to move Rockford again.
procedure ScanFirefly(in positionType positionOfFirefly;
in directionType directionOfFirefly)
# Local variables
positionType NewPosition;
directionType NewDirection;
# First check whether the firefly will explode by being next to Rockford,
# Rockford-scanned-this-frame or amoeba but not amoeba-scanned-this-frame.
if (FlyWillExplode(positionOfFirefly)) then
Explode(positionOfFirefly, explodeToSpace);
else
# Failing that, attempt to move turn left and move there if possible
NewPosition = GetNextFlyPosition(positionOfFirefly, directionOfFirefly, turnLeft);
if (GetObjectAtPosition(NewPosition) == objSpace) then
NewDirection = GetNewDirection(directionOfFirefly, turnLeft);
PlaceFirefly(NewPosition, NewDirection);
PlaceSpace(positionOfFirefly); # ie old position
else
# Failing that, attempt to move straight ahead
NewPosition = GetNextFlyPosition(positionOfFirefly, directionOfFirefly, straightAhead);
if (GetObjectAtPosition(NewPosition) == objSpace) then
PlaceFirefly(NewPosition, directionOfFirefly); # ie keep same direction
PlaceSpace(positionOfFirefly); # ie old position
else
# Failing that, turn to the right but do not move
NewDirection = GetNewDirection(directionOfFirefly, turnRight);
PlaceFirefly(positionOfFirefly, NewDirection); # old position, new direction
endif
endif
endif
endprocedure
##
function FlyWillExplode(in positionType aPosition):Boolean
# Check the four directions around a fly at a given position to see whether
# it will explode. Returns true if so, false if not.
# Local variables
Boolean ExplodedYet;
# Check the four directions to see whether the fly will explode
ExplodedYet := CheckFlyExplode(GetRelativePosition(aPosition, up1));
if (not ExplodedYet) then
ExplodedYet := CheckFlyExplode(GetRelativePosition(aPosition, left1));
endif
if (not ExplodedYet) then
ExplodedYet := CheckFlyExplode(GetRelativePosition(aPosition, right1));
endif
if (not ExplodedYet) then
ExplodedYet := CheckFlyExplode(GetRelativePosition(aPosition, down1));
endif
# Return function result
return ExplodedYet;
endfunction
##
function CheckFlyExplode(in positionType aPosition):Boolean
# Check the given position to see whether it contains an object which a
# fly will explode if it is in contact with (ie Rockford or Amoeba).
# Returns true if so, false if not.
return (GetObjectAtPosition(aPosition) in {objRockford, objRockfordScanned, objAmoeba});
endfunction