Beetlejuice (NES)/Game Mechanics and Techniques

From SDA Knowledge Base

Jump to: navigation, search

Animations

Movement mechanics

Time cost comparisons

Scares

Name Cost Shots Special ability Comments
Medusa.png Medusa head 100 1 Freezes "floating skulls" (found in some beetle holes)
Birdman.png Birdman 150 2 Increases jump height The jump ability allows for shortcuts and is very useful in a speedrun
Two-headed man.png Two-headed man 200 3 1-hit kills the sandworm on Saturn
Skeleton.png Skeleton 250 5 No damage from bees, 1-hit kills the beehives (both only found in level 1)
Umbrella.png Umbrella head 400 9 None? The manual hints about giving some sort of advantage against the octopuses in the sewer stage
Ogre.png Ogre 500 12 1-hit kills the cavern monsters in level 2 (Storm drains)
Ghost.png Ghost (called "spooksheet" in the game) 600 15 None? Only available in the graveyard level. The manual does not seem to hint about any special ability. It sounds more like it's an "all-purpose" scare with lots of shots.
Snake.png Snakeman 750 19 None? Same comments as for the ghost scare.


RNG

The RNG-addresses in RAM are $24-$27. They're calculated by various operations between themselves and take the result of the previous set of RNG and the global timer ($3BB) as seeds.

The RNG-function is called by various events that require a new set of RNG. This can result in the RNG being calculated from several times per frame to every few frames or not all (if nothing loaded in memory requires RNG-values.

There is no indication that the RNG-values would be possible to manipulate in real-time. In TAS-conditions, the RNG can be manipulated to a certain extent by performing actions that trigger the RNG-function to be called. Beetlejuice's movements don't directly impact the RNG-function, but e.g. throwing a potion (in the overhead section) will create additional calls of the RNG-function.

Enemies and objects

1st boss (Level 1)

1st boss.PNG

  • $5E9/$5E8 - Small/Sub x-position of shots
  • $5EC/$5EB - Small/Sub x-speed of shots
  • $535/$536 - x/y boss
  • $5E7 – Shot flag


When the shot flag is not set, the RNG function is called every 16 frames, based on the global timer ($3BB). One of the results is compared with 0x46 (instruction $C8F9). If it's less, the boss will shoot a puff of bug spray. Since the player neither knows the global timer, nor the RNG values, shots can be considered random and outside player control with a probability of (1/16)*(72/256) ~ 1/57 per frame.

The speed of the puff is either 1 or 2 pixels/frame and with a sub-speed that is a multiple of 0x40 (a sub-speed >0 slows down the puffs). The speed of both components (main and sub) directly depends on $24 (the first RNG-address) and should therefore be equally distributed with no possibility to predict in real-time.

2nd boss (Level 2)

2nd boss.PNG
This boss works in essentially the same way as the first one, but with a few different parameters. The ball speed is always 1 pixel/frame (instruction $C95D). When the shot flag is not set, the boss will kick a ball based on a check every 16 frames (based on the global timer in $3BB) with a 50% chance (instruction $C93C).

3rd boss (Level 3-4)

3rd boss.PNG

  • $537 - Magic timer


If the boss isn't already casting magic, the game calls the RNG function every second frame. The check that follows has a 5/256 ~ 1/51 chance to pass (instruction $C85A), resulting in the boss casting magic. The duration of the spell is always 22 or 24 frames.

Delia's art pieces

Art piece1.PNG Art piece2.PNG Art piece3.PNG
The following description refers to the art pieces' x-position, the y-position works in an analog way. The description is applicable to both the objects in room 0xC and 0xF (from $55).

Every 16th frame, the RNG function is called and through various calculations updates [$5CA+X]. This address has double purposes. First it determines a base movement of the object for the next 16 frames. This base movement is either move left or stand still. Then through logical manipulations, it adds a number to [$5D0+X] every frame (always the same number during the 16 frames). The new x-position (5AC+X) is then calculated by taking ”move left or standstill” plus if there was a carry in the calculation of the new [$5D0+X].

Several steps have been skipped in the description above, but the end result and conclusion are that the game achieves something similar to a sub-pixel movement. During 16 frames, the art piece will move 0 or 1 pixel every frame, depending on how often the carry is produced in the calculation of [$5D0+X].

With the art pieces' movement at the core relying on RNG, it's difficult to see how any manipulation would be possible.

Beetles (side view levels)

Beetle (side view levels).PNG

  • $41X - positions and objects occupied
  • $42F+X - Beetle type (0 – 10, 1 – 25, 2 – 50, 3 – 75)


Every 4 frames, the RNG function is called and a result is compared with 0x32 (instruction $A835). If it's smaller, another check is done with a 1/4 chance of passing per active beetle hole on screen (instruction $A83F). A beetle will then spawn from the corresponding hole.

The type of bug is again determined by running the RNG function. The result is this time compared with 0x50 (instruction $A875). If it's smaller, a red beetle (worth 10 vouchers) will spawn. If it's greater, another check is done with equal probability of the remaining 3 types (instruction $A879).

In summary, as long as the three available beetle memory addresses aren't filled, the probability of one of the 3 more valuable types spawning per second and per hole is 15*(48/256)*(1/4)*(166/256) ~ 46%.

Beetles (overhead levels)

Beetle (overhead levels).PNG

  • $60C – Beetle flag
  • $611/$60E/$60D – Big/Small/Sub x-position
  • $610/$60F – Small/Sub x-speed
  • $619/$616/$615 – Big/Small/Sub y-position
  • $617/$618 – Small/Sub x-speed


There is a 75% chance that an enemy drops a beetle (instruction $9E8C, when enemy health goes to 0). Same for all enemy types. There can however only be one beetle at a time (controlled by the beetle flag).

The speed is recalculated every second frame as the current speed and an addition based on a result from calling the RNG function (see e.g. Instruction $BD50).

Cavern monsters

Cavern monster.PNG

  • $5E9/$5E8 - Small/Sub x-position of shots
  • $5EC/$5EB - Small/Sub x-speed of shots
  • $5EF/$5EE - Small/Sub y-position of shots
  • $5F2/$5F1 - Small/Sub y-speed of shots
  • $5F4 – Shoot timer


The shoot timer counts down from 0x3F. When it reaches 0, the current shot disappears and a new one appears. The speed (0-4 pixels/frame + sub-pixel speed) depends on Beetlejuice's position and the RNG. The x- and y-speeds are calculated independently. The monsters will always fire in the direction of Beetlejuice. However, when the main x-speed is 0, the sub x-speed can make the shots fly in the opposite direction from Beetlejuice. Those shots will therefore always be slow, while shots in Beetlejuice's direction can be faster.

A full disassembly of the direction of shots hasn't been done, but a preliminary investigation did not find any manipulation possibilities.

Cloud elevators

Cloud elevator.PNG

  • $463 - Elevator counter
  • $5D - y-position of the elevator currently on screen, an offset of $463


$463 runs in the background when entering the house (level 1). When a switch is flipped, the corresponding elevator will teleport to wherever in the cycle $463 is and starts to move from there.

"Fish in cauldron"

Fish in cauldron.PNG

  • $5B2+X - y-position
  • $5A6+X - y-speed


Every 16 frames, the game calls the RNG function and calculates a number between 0 and 7. If the number is in the range 0-4 (instruction $AC82) and the corresponding fish is in its cauldron (instruction $AC85), it will initiate a jump of that fish with a set trajectory.

Flies (overhead sections)

Fly.PNG

  • $5AC/$5B2+X – x/y-position (relative to the window position)
  • $5BE/$5C4+X – x/y-speed (relative to the window position)


The flies get a 1 pixel/frame speed change every 4 frames (instruction $A1CB and onwards). The speed is capped at 3 pixels/frame in both directions. The calculation is only based on the RNG. It's therefore difficult to see how their movement could be possible to manipulate in real-time. It's worth noting that the speed is relative to the window position. When Beetlejuice is hit, the flies will only follow the screen during the invincibility period, which can allow for free hits by aligning flies with the swatter. The RNG is updated before each speed calculation, so each fly moves independently of the others.

Flowers

Flower.PNG
Not yet fully understood. However, their blooming and fading are presumed to be entirely based on RNG. The addresses $6B-$6F appear to be linked to the flower cycle, but the exact relationship has not been described.

Purely based on empirical observations, the flowers seem to bloom roughly every 8-9s and each blooming lasts for around 2s on average. It can be worth mentioning that if the RNG addresses are frozen, the flowers will bloom every 256 frames.

Footballer's legs

Legs.PNG
Same mechanics as the sweepers, but with 4 (iso 2) consecutive direction changes towards the player every 64 frames. As a result, any random movement changes are more likely to be cancelled and replaced by movements homing in on Beetlejuice. As a result, the legs follow Beetlejuice more closely around than the sweepers do.

Lights

Light.PNG
$62B increases by one every 2 or 4 frames (not fully understood what determines the delay). Every 4 increases of $62B, $628 changes value (0->1->3->7->0xF->0xE->0xC->8->0). The leftmost light is lit when $628 equals 0 and is unlit when it equals 0xF. The other lights are shifted by one and two, respectively, in the cycle.

Mouse

Mouse.PNG

  • $62D/$63B - x/y-position
  • $673 - Movement direction (x or y)


The mouse always starts in the same position in the right side of room 0x18 (see $55) and always starts moving up when entering the room. A new movement direction is then calculated (or keeping the current) every time the global timer in $3BB is divisible by 32. If the mouse hits a wall, it will continue in the opposite direction until the next direction calculation is due. Input to the calculation of a new direction comes directly from the RNG-addresses in $24-$27, meaning real-time manipulation is not possible.

The best (/fastest) scenario occurs when the mouse enters the narrow corridor and moves towards the left room. Given the fairly stiff mechanics of the mouse movements, this is not always immediately possible. A more detailed description of how the mouse can enter the narrow corridor can be found in https://tasvideos.org/6440S.

Octopus

Octopus.PNG
When Beetlejuice has a scare equipped, he can with a 50% chance jump through an octopus without dying by using the invincibility frames. The invincibility ($1AD) decreases every 4 frames, depending on the global timer ($3BB).

  • If the first decrease of the invincibility timer is after 2 frames, Beetlejuice will take damage from the octopus and die before jumping past it.
  • If the the first decrease is after 4 frames, Beetlejuice will be outside the octopus's hitbox before the invincibility wears off.

Since there is no indication of value of the global timer, it's in practice random in a real-time attempt if Beetlejuice can jump through the octopus or not.

Potions

Potion.PNG Potion scare.PNG

  • $585/$588 - x/y.position
  • $58D - Potion timer – starts at 0x14 and decreases when the operation AND(global timer in $3BB, 0xF) results in 0
  • $58E – Movement direction (1 - NE; 3 - SE; 5 - SW; 7 - NW)


The initial movement direction when throwing a potion is determined entirely by the RNG, with equal probability of the four possible movement directions. Once the initial direction has been calculated, the potion will continue in that direction until hitting an obstacle. It will then bounce according to ”everyday logic/physics”. A part from the initialization, the rest of the trajectory is therefore deterministic. By throwing potions in locations where the 4 possible trajectories have been tested beforehand, one can therefore to some extent control the movements of the potion.

Shops

Shop.PNG
Some shops have different sets of inventory. Which set is loaded depends on which x-pixel the shop is entered on. This is hard-coded and therefore possible to predict.

Spiders

Spider.PNG

  • $7DF/$7DC/$7D9+X - Big/Small/Sub x-position
  • $7E8/$7E5/$7E2+X - Big/Small/Sub y-position
  • $7EB+X - Determines movement direction and speed


The game calls the RNG-function every second frame to first do a 4/32 check (instruction $8E57) and then selects a number in the range 0-3 based on the global timer in $3BB. If the result is 0-2 (instruction $8E61) and the corresponding object index is not already occupied (instruction $8E67), a spider spawns.

The spider's initial x- and y-positions are found through look-up tables, while the address for movement direction and speed is calculated based on the RNG-addresses and the global timer ($3BB).

Sweepers

Sweeper.PNG

  • $5BE/$5AE+X – Big/Small x-position
  • $5C4/$5B2X – Big/Small y-position
  • $5D0+X – Movement direction, x
  • $5D6+X – Movement direction, y
  • $59A+X – Health


The RNG-function is called every 4 frames for a a 1/32 probability of a random movement direction change (instruction $9CC6).

There is also a check every 8th frame which only depends on the global timer ($3BB) and the object index of the sweeper (instruction $9C5F). When this comparison branches, a new direction is calculated towards the player. Skipping the code details, the end result is that each sweeper gets two consecutive (8 frames apart) direction changes every 64 frames and they will be in the direction of the player.

When Beetlejuice has been hit and the invincibility timer ($1AD) runs, the sweepers movements are inversed.

The object index dependence and the random direction changes (calculated independently for each sweeper) ensure they move independently of each other.

"Urn with bouncing smiley"

Urn and smiley.PNG

  • $5F9/$5F8 – Small/Sub y-position of smiley
  • $5FC/$5FB – Small/Sub y-speed of smiley

The smiley starts moving when entering the house and then follows a set pattern. However, when it falls back into the urn, it will only bounce back out wih a 1/8 chance every frame, based on a check of the RNG-function (instruction $A36F). The position is therefore largely random when reaching the top of the house. A statistical analysis could probably reveal positions that are more likely, depending on in which platform cycle Beetlejuice has reached the top of the house, but this has not been attempted.

Buffered inputs

Glitches

Screen warping in the overhead levels (TAS-only)

Softlocks

  • The second door in room 0x15 (see $55) did not open, despite having destroyed all art pieces (reported by 'ktwo' on console, no recording available)


Additional game mechanics

Free scare at the cavern monsters

If Beetlejuice doesn't have any scares when the screen is locked around a cavern monster, an umbrella head scare will spawn to the right of it within 64 frames (check done at instruction $9A9C), based on the global counter ($3BB). This is likely to avoid soft-locking the game since the game locks the screen around the monster and it's not possible to escape the fight.

Open locked doors without killing all enemies

Doors in the overhead levels that are unlocked by killing all sweepers in the room, will open after a set amount of time. The room timer in $675/$674 is reset upon entering a new room. When it has cycled 14 times ($675 = 0xE), the door will automatically unlock. This is likely to avoid soft-locking the game since the sweepers can only be damaged by potions, which are in limited supply.

This game mechanic is unlikely to find any use in a speedrun since it will be much slower than killing the sweepers in the rooms where this applies.

Open questions

Toilet paper

This item is found at the top of room 0xF (see $55). Upon collection, the game hints about some kind of secret use for it. However, there doesn't seem to be any claims on the internet of people having found any use for this item.

Brick

This item is found at the top of room 0x10 (see $55). Upon collection, the game hints about using it against the football players. There are footballer's legs in that room, but there doesn't appear to be any evidence of the brick actually doing anything to the legs.

Additional scares with special abilities

A few of the scares don't appear to give Beetlejuice any special abilities. Intentional or could there be secret abilities yet to be discovered? The descriptions in the game manual could be read as hints about special abilities for some of these scares.

Selection of known RAM-addresses

Personal tools