Difference between revisions of "Dragon's Lair (NES)/Game Mechanics(ntscu)"

From SDA Knowledge Base

Jump to: navigation, search
m (The Lizard King)
(Movement and animations)
Line 58: Line 58:
 
* Chaining jumps together, chaining ducking and rising,  "corner landing" all have no additional impact on the animation times
 
* Chaining jumps together, chaining ducking and rising,  "corner landing" all have no additional impact on the animation times
 
<br />
 
<br />
 +
 +
===Dragon's Breath===
 +
The jump movements in this game don't rely on speed calculations, but instead follow pre-programmed movements and animations stored in look-up tables. In contrast to this, the section with the "Dragon's Breath" (DB) in the middle of the second level introduces different mechanics and complexity. It's not particularly intuitive from just playing the game and has therefore been analyzed in a bit more detail.<br /><br />
 +
 +
Once Dirk is above the pit with the DB, the jump mechanics will stop applying. So instead of checking in the "jump look-up table", the game will calculate the new y-position depending on the DB strength and how well Dirk floats in the upwind. With reference to RAM-addresses, the new y-position is calculated according to the following formula:<br />
 +
$392 = $392 + $574 + $576 + $579<br />
 +
* $392 - y-position (from top of the screen to bottom)
 +
* $574 - Strength of DB (0xFC - 0), lifting Dirk up
 +
* $576 - Downward pull (or speed component) that is countered by Dirk "flapping his arms and legs" (description from the manual) by mashing 'B'. Can either have a value of 2 (fast flapping), 3 (poor flapping) or 4 (no flapping).
 +
* $579 - Similar to $576. An incorrect, but conceptually acceptable (?), description could be to say that this works as a kind of sub-speed component to $576.
 +
 +
As can be seen from the formula above, the DB strength works as the upward component, while $576 and $579 pull Dirk down towards the pit. The next sections will describe these in more detail.<br /><br />
 +
 +
<u>Dragon's Breath (DB) strength</u><br />
 +
When the DB pit comes on screen, $572 starts to count up every 5 frames. When it resets after reaching 60/0x3C, the upwind starts and the timer in $572 is reset. In this phase, 1 is subtracted from $574 for a new value of 0xFF. $574 is the strength of the DB. When the timer resets after 10/0xA, 1 is again subtracted from $574 (new value 0xFE). This repeats until $574 contains a value of 0xFC and the DB is at its strongest. It keeps this value until the timer passes 40/0x28, at which point it reverses back to phase 0, one step at a time, and the cycle begins over again.<br /><br />
 +
 +
<u>Dirk's flapping mechanics</u><br />
 +
While the DB pushes Dirk upwards, it's not enough to balance the downward/gravity pull unless Dirk also flaps his arms and legs. Dirk's flapping status is tracked in $57F, which is used in the calculation of $576 and $579. The lower the value of $57F, the better Dirk flaps. When 'B' is pressed, the value is reduced by one and the timer in $57E is reset. Without further action, 1 will be added to $57F when the timer resets after reaching 0x10. This continues until the max value of $57F (fluctuating between 0x10 and 0x11) is reached or if 'B' is pressed again.<br /><br />
 +
 +
It's in theory possible to mash (up to 30fps) $57F down to the ideal value of 0. However, there is an additional mechanic making this difficult to do in practice. The value of $57F will only decrease if its value is bigger than the timer in $57E, else pressing B will increase $57F by one. So the lower the value of $57F, the faster the mashing is required to maintain (or increase) the flapping.<br /><br />
 +
 +
Before talking about how $57F is linked to $576 and $579, it's worth mentioning that if 'B' is held down, $57F will stay unchanged. So a short burst of rapid mashing (can even be done during the jump from the platform to the DB!) and then holding down 'B' will produce the same result as a continuous mashing.<br /><br />
 +
 +
Dirk's flapping (= the value of $57F) will update $575 and $576. The latter providing a direct downward pull, counteracting the effect of the DB's upwind. The former will add its value to $579. Whenever $579 loops, a downward pull of one will be added to the calculation. Hence the similarity with a sub-speed component to the downward pull. The code section that translates the "flapping" into a "floating property" will not be further described here, but is fairly straight-forward and the interested reader is referred to instruction $C690 and onwards in the ROM.<br /><br />
 +
 +
<u>Conclusion observations</u><br />
 +
* The Dragon's Breath goes through 8 phases. Phase 0 is no upwind. Phases 1-3 build up the strength of the upwind step-wise. In phase 4, the DB strength is at its max. Phases 5-7 are the reverse of 1-3.
 +
* The faster Dirk flaps (pressing 'B'), the better he will float in the upwind. This is only about button mashing (up to 30fps). There is no pattern or rhythm that provides a better result. Remember to start mashing during the jump from the platform to the DB!
 +
* Holding down 'B' locks Dirk's flapping pace. So a short mashing burst, followed by holding down 'B' will give the same result as continous mashing.
 +
* The DB is only strong enough for Dirk to rise in phases 3-5. At best 2 pixels/movement frame (mf) in phase 4 and 1 pixel/mf in phases 3 and 5. In phase 1 (and 7), the DB is not strong enough to support Dirk, even with perfect mashing and he will (at best) float down at a rate of 1 pixel/mf. In phase 2 (and 6), perfect mashing will only be able to keep Dirk level, but will in real-time result in slowly descending. The best strategy is therefore to wait a bit for the strength to build up before jumping into the upwind as jumping into the DB too early will only result in a longer climb.<br /><br />
  
 
==Energy==
 
==Energy==

Revision as of 08:47, 1 November 2022

Dragon's Lair (NES)

Items

  • D - daggers, deal 1 HP of damage, 3 can be on screen at the same time
  • A - Axes, deal 2 HP of damage, 2 can be on screen at the same time
  • F - Fireballs, deal 3 HP of damage, 1 can be on screen at the same time
  • E - restore 16 energy
  • C - restore candle
  • G - Add one gold to the inventory
  • L - Extra life
  • P - Points

Hidden item locations

The list below comes from searching with save states, but hasn't been verified by address watching, so it's possible that there are still hidden items to be found.
Level 1 (in order of appearance)
A - right before the first two gateways
P - right after the first two gateways
F - after the third prisoner
A - before the second set of two gateways
F - after the last prisoner

Level 2 (in order of appearance)
C - in the opening in the roof between the first two moving blocks
P - two blocks to the right of the hidden C
P - after the first set of two moving blocks
A - before the first pit
L - after Singe's Dragon's Breath

Level 3 (in order of appearance)
P - under the second arc from the start
A - under the third arc from the start
G - before jumping on the ledge of the first pendulum
E - after the first set of two pendulums
L - after the axes
F - before the second ghost
E - right before the 3rd G
P - before the visible daggers
A - over the first floor support after the visible daggers
E - after the hidden axes
P - under the second arc after the big skull guarding a big pit
P - under the same archway as the above P

Level 4 (in order of appearance)
There doesn't appear to be any hidden items in this level.

Movement and animations

This section looks at the cost of performing various actions. If nothing else is stated, it's compared to walking in a straight line.

  • First shot - 35 frames
  • Subsequent shots - 20 frames/shot
  • Small jump - 30 frames
  • Big jump - 35 frames
  • Small vertical jump - 95 frames
  • Big vertical jump - 120 frames
  • Dropping down "1 height" - 35 frames (meaning that it's 5 frames faster to jump off ledges than drop down from them)
  • Duck and rise - 70 frames
  • Go straight into ducking position after a jump - saves 15 frames compared to performing jumping and ducking separately
  • End-of-level gold countdown screen (1 gold) - 157 frames
  • Countdown for each additional gold - 24 frames
  • Chaining jumps together, chaining ducking and rising, "corner landing" all have no additional impact on the animation times


Dragon's Breath

The jump movements in this game don't rely on speed calculations, but instead follow pre-programmed movements and animations stored in look-up tables. In contrast to this, the section with the "Dragon's Breath" (DB) in the middle of the second level introduces different mechanics and complexity. It's not particularly intuitive from just playing the game and has therefore been analyzed in a bit more detail.

Once Dirk is above the pit with the DB, the jump mechanics will stop applying. So instead of checking in the "jump look-up table", the game will calculate the new y-position depending on the DB strength and how well Dirk floats in the upwind. With reference to RAM-addresses, the new y-position is calculated according to the following formula:
$392 = $392 + $574 + $576 + $579

  • $392 - y-position (from top of the screen to bottom)
  • $574 - Strength of DB (0xFC - 0), lifting Dirk up
  • $576 - Downward pull (or speed component) that is countered by Dirk "flapping his arms and legs" (description from the manual) by mashing 'B'. Can either have a value of 2 (fast flapping), 3 (poor flapping) or 4 (no flapping).
  • $579 - Similar to $576. An incorrect, but conceptually acceptable (?), description could be to say that this works as a kind of sub-speed component to $576.

As can be seen from the formula above, the DB strength works as the upward component, while $576 and $579 pull Dirk down towards the pit. The next sections will describe these in more detail.

Dragon's Breath (DB) strength
When the DB pit comes on screen, $572 starts to count up every 5 frames. When it resets after reaching 60/0x3C, the upwind starts and the timer in $572 is reset. In this phase, 1 is subtracted from $574 for a new value of 0xFF. $574 is the strength of the DB. When the timer resets after 10/0xA, 1 is again subtracted from $574 (new value 0xFE). This repeats until $574 contains a value of 0xFC and the DB is at its strongest. It keeps this value until the timer passes 40/0x28, at which point it reverses back to phase 0, one step at a time, and the cycle begins over again.

Dirk's flapping mechanics
While the DB pushes Dirk upwards, it's not enough to balance the downward/gravity pull unless Dirk also flaps his arms and legs. Dirk's flapping status is tracked in $57F, which is used in the calculation of $576 and $579. The lower the value of $57F, the better Dirk flaps. When 'B' is pressed, the value is reduced by one and the timer in $57E is reset. Without further action, 1 will be added to $57F when the timer resets after reaching 0x10. This continues until the max value of $57F (fluctuating between 0x10 and 0x11) is reached or if 'B' is pressed again.

It's in theory possible to mash (up to 30fps) $57F down to the ideal value of 0. However, there is an additional mechanic making this difficult to do in practice. The value of $57F will only decrease if its value is bigger than the timer in $57E, else pressing B will increase $57F by one. So the lower the value of $57F, the faster the mashing is required to maintain (or increase) the flapping.

Before talking about how $57F is linked to $576 and $579, it's worth mentioning that if 'B' is held down, $57F will stay unchanged. So a short burst of rapid mashing (can even be done during the jump from the platform to the DB!) and then holding down 'B' will produce the same result as a continuous mashing.

Dirk's flapping (= the value of $57F) will update $575 and $576. The latter providing a direct downward pull, counteracting the effect of the DB's upwind. The former will add its value to $579. Whenever $579 loops, a downward pull of one will be added to the calculation. Hence the similarity with a sub-speed component to the downward pull. The code section that translates the "flapping" into a "floating property" will not be further described here, but is fairly straight-forward and the interested reader is referred to instruction $C690 and onwards in the ROM.

Conclusion observations

  • The Dragon's Breath goes through 8 phases. Phase 0 is no upwind. Phases 1-3 build up the strength of the upwind step-wise. In phase 4, the DB strength is at its max. Phases 5-7 are the reverse of 1-3.
  • The faster Dirk flaps (pressing 'B'), the better he will float in the upwind. This is only about button mashing (up to 30fps). There is no pattern or rhythm that provides a better result. Remember to start mashing during the jump from the platform to the DB!
  • Holding down 'B' locks Dirk's flapping pace. So a short mashing burst, followed by holding down 'B' will give the same result as continous mashing.
  • The DB is only strong enough for Dirk to rise in phases 3-5. At best 2 pixels/movement frame (mf) in phase 4 and 1 pixel/mf in phases 3 and 5. In phase 1 (and 7), the DB is not strong enough to support Dirk, even with perfect mashing and he will (at best) float down at a rate of 1 pixel/mf. In phase 2 (and 6), perfect mashing will only be able to keep Dirk level, but will in real-time result in slowly descending. The best strategy is therefore to wait a bit for the strength to build up before jumping into the upwind as jumping into the DB too early will only result in a longer climb.

Energy

The player energy is tracked in memory addresses 332 (big energy, BE) and 6A5 (small energy, SE). When the small energy loops, the big energy is reduced by 1. A life is lost when the big energy hits 0. Below are some observations about the energy.

  • E block - +16 BE
  • Getting hit by a bat, skull, the Lizard King or a bubble - -4 BE
  • Shoot - -16 SE
  • Start energy - 39 BE
  • If the player's BE is 2, 3 or 4, getting hit by an enemy brings you down to 1 BE and whatever you had left of small energy, instead of killing you if it had inflicted the normal 4 damage.
  • If an E is collected when player energy > 23, you'll end up with 39 BE and whatever you had left of small energy.


Note: There is a bug that can occur with the Lizard King. If you bump into him in the vicinity of where the first serpent was supposed to appear, you'll take damage continuously. In a speedrun setting (so walking to the right without stopping), that means a damage of 12 BE. If you stop moving while taking damage, even more energy will be lost.

Enemies

  • Serpent - 3 HP
  • Red bat - 3 HP
  • Baby dragon - 4 HP
  • All other regular enemies have 1 HP
  • Dragon under the drawbridge - 10 HP
  • Mine cart troll - 10 HP (each)
  • Grim Reaper - 16 HP
  • Singe - 40 HP


The RAM addresses containing the bosses' health tend to vary a bit, depending on which object index they're loaded in memory. A few examples are: $3B2, $3C4, $3FA, $3E8, $BB2 and $40C. It's easy enough to find these addresses when needed, so no further attempt has been made to investigate if there are other possible addresses.

The Lizard King

The Lizard King guards the gold of the castle. As soon as you have collected/stole some of its gold, a random check will occur every movement frame (=5 actual frames). An outline of the RNG check that is performed to determine if the Lizard King appears or not is as follows:

  1. Call the RNG-function starting at $C000
  2. If the accumulator is >= #$FB, then branch (instruction $DAB1), else abort
  3. Call the RNG-function starting at $C000
  4. If the accumulator is <= #$20, then branch (instruction $DAB9), else abort
  5. $718 is loaded and will start to count down for the Lizard King to appear

Each check therefore has a 1/51 * 1/16 = 1/816 ~ 0.12% to spawn the Lizard King. It's difficult to see how the RNG calculation behind the Lizard King's appearence can be manipulated in real-time, but some observations can still be made:

  • The RNG check that triggers the Lizard King is only done in certain areas of the game. The check isn't done in the middle section of stage 2 (before and after the dragon's breath pit) and the whole stage 3. Also, the checks aren't started at the very beginning of each stage and they are stopped a little before and under the boss fights.
  • If you have no gold, no check is done and the Lizard King won't appear. In a casual playthrough, where one might be tempted to kill the Lizard King, it will therefore continuously appear until it has bumped into you and retrieved its gold.
  • Since a speedrun spends roughly the same amount of time between attempts in each level, it's possible to estimate the probability of a Lizard King spawn in each level.
- Level 1 is ~ 50%.
- If no encounter in level 1, the first section of level 2 has ~25% encounter rate (if the Lizard King already took the gold in level 1, it will not appear at the start of level 2). There is also a short section before the bosses, where the check is done. Since there is forced gold before this section, it can always appear here. However, the probability is only around 1/15, due to how short the section is.
- The Lizard King check isn't done in level 3 and encounter is therefore not possible.
- Roughly 75% chance of an encounter in level 4
  • While there are benefits with getting a Lizard King encounter (losing the gold, but also despawning enemies), it's on average far from being worth waiting for the Lizard King to appear. However, if someone were willing to put in enough attempts, it's clear that there could be time to save by trying to wait for the Lizard King in strategic places (in particular in level 4).


Singe

Singe's puffs are blown at regular intervals, but their height is based on RNG that is unlikely to ever be possible to manipulate in real-time. The branch operator in $A26F determines if the puff will be high or low, based on if the accumulator is even or uneven. Input to this calculation are the addresses $6A1 and $6A2, which change value every frame according to an RNG calculation that appears to be random for real-time considerations. Without a deeper analysis, Singe's puffs are therefore not possible to manipulate and with equal chance generating a high puff as a low puff. There doesn't appear be any kind of "equalizing" factor built into the code such as "if too many puffs of one type, increase the chance of the other kind".

Personal tools