About · Knowledge-based Design · Mapping an 8-bit World · Pathfinding
Game State · Heuristic State Machines · Playthrough · Download · Run
CastlevaniaBot is a plugin for the Nintaco NES emulator that plays Castlevania. If you launch it during the title screen, it will play through the entire game from start to finish. Or you can intermittently start and stop it at any point in the middle of a game and let it complete a section.
In this article, I describe how I created a bot that’s able to beat Castlevania and how you can do the same for other NES titles.
This project does not involve machine learning. If anything, its development might be called “machine teaching”. I know how to play through Castlevania. And the challenge was to capture my knowledge into a computer program. The result is a system that simulates the same decision-making process that I perform when I have a controller in hand. Creating it involved articulating in elaborate detail the physics that govern Simon Belmont’s 8‑bit world and all the tactics required to be an expert vampire killer.
CastlevaniaBot has access to a catalog of strategies for handling a wide range of situations. Most of them are designed to handle a particular game object type. For instance, there is a strategy for dealing with skeletons, another for fishmen, another for whipping candles, another for collecting hearts, and so on.
CastlevaniaBot constantly monitors the game state and it switches between the available strategies as it deems necessary. The decision process uses a fitness function to rank all the onscreen game objects. The top rank is the primary target and when the primary target changes, it switches strategies. For example, CastlevaniaBot might be about to strike some candles when a bat flies into frame. Depending on how close it is to the bat, CastlevaniaBot may respond by switching from the candles strategy to the bat strategy. After whipping the bat, it can resume handling the candles.
CastlevaniaBot considers the current target and strategy before deciding to switch. If it failed to do so, it could get stuck in an infinite loop, switching back and forth between 2 targets with equal or nearly-equal ranks. To prevent this from happening, if a new primary target is only marginally better than the current target, CastlevaniaBot may choose to stay on its current course.
Some strategies are triggered automatically when the player enters a specific region. These are usually designed for handling multiple game objects collectively. For instance, in a hallway full of flying medusa heads, the best strategy is to keep walking as opposed to targeting each head individually.
A few strategies change depending on the current subweapon and the number of collected hearts, particularly the boss fights. CastlevaniaBot will make a best effort with the tools it has on hand in a given situation.
When I approach a project like this, the first thing I try to do is to simply the problem. I imagined what Castlevania would be like if the stages were absent of enemies and candles and items to collect. All you would have to do is to walk from the start of the stage to the end of the stage. I figured, if I could get a bot to do that, how hard it could be to whip some enemies along the way?
To get a bot to navigate, I needed background tile maps and an understanding of how stages are organized. The game consists of 6 levels, each ending in a boss.
Each level is partitioned into 3 or 4 stages. The stages are usually separated by wooden doors that creek open and slam shut behind you.
Doors act as checkpoints. If the player is killed, he’s returned to the start of the stage. That is, unless the player runs out of lives. Continuing from Game Over sends the player all the way back to the beginning of the level.
Stage number indicates the total number of checkpoints passed since the very beginning of the game. The final stage is 18. But, if you defeat Dracula, the game starts over in Difficult Mode and the stage number increments to 19 and beyond. If you beat Difficult Mode, the third loop of the game isn’t any harder, but stage number keeps going up and up.
Each stage is composed of one or more horizontally-scrolling background strips that I call “substages”. If you walk offscreen via an up or down staircase, the game jumps from one substage to another instead of scrolling vertically.
The game uses 3 bytes to keep track of the game loop number, the stage number and the substage number, respectively. Game loop 0 is Normal Mode; 1 and above is Difficult Mode. Stage always ranges from 0 to 18 regardless of the game loop. And substage is either 0 or 1 since, by design, stages never contain more than 2 horizontal strips. CastlevaniaBot monitors those bytes to determine exactly where it is.
I captured each substage background strip into a separate image file for reference purposes. If I ever needed to know the exact coordinates of something, I could quickly work it out using an image editor. I did this using Nintaco’s built-in Map Maker. I enabled it and then I played through the entire game. Some of the resulting images contained multiple substages chained together, which were easy to break apart.
After studying the background images, I realized that the only relevant tiles were platforms and staircases. Everything else could be considered empty space. Staircases come in 2 types: forward and back (think of forward slash and backslash). Sometimes staircases are capped by a platform that the player can walk on.
There are only 5 relevant tile types and they are skinned differently on each level. I copied and pasted them into separate 16×16 image files. Then, I wrote a program that compared every tile in every substage against the relevant set. That produced tile-type matrices for all the substages.
The matrices could have been extracted directly from the ROM, but I couldn’t find documentation on how and where that data is stored. Since ROM space is limited, level data is usually represented in a compressed format resembling vector graphics. Each game uses its own proprietary format and I decided that it was not worth the research effort since I had the Map Maker. Besides, I needed visual representations of the substages anyway. Had I not captured the background strips, I would have been forced to write the opposite program that generated images from the matrices.
With the tile matrices in hand, I wanted to apply a pathfinding algorithm, particularly the Floyd-Warshall algorithm, which outputs a table containing the shortest paths between every pair of vertices in a directed, edge-weighted graph. The idea is to precompute the tables into files and then load them at runtime. With the tables in memory, the bot could do a lookup and instantaneously know the shortest route between any 2 platform tiles.
A graph consists of edges and vertices. If the platform tiles are the vertices, then the edges are limited to the operations that Simon Belmont can do to get himself from one platform tile to another. Operations that act exclusively on the same tile are not permitted. For example, on a flat plane of tiles, Simon can step one tile left or one tile right.
Similarly, if Simon is on stairs, he can move diagonally by 1 tile in 2 possible directions.
Those are valid operations. But doing something like walking from the midpoint of a tile to an edge of a tile is too granular because it fails to transition from one graph vertex to another.
Aside from walk-left, walk-right, go-up-stairs and go-down-stairs, Simon can jump to another tile. And he can jump left or right starting on any of the 16 pixels capping a tile. To reduce the number of edges in the graph (and the size of the lookup table), I only considered 5 possible launch points:
Including do-nothing, I ended up with 15 operations. All of them are basic enough that the bot could easily work out the button sequences required to execute them at runtime.
To construct the complete graph, I created a very basic physics simulation of Simon’s world. Within that simulation, all 15 operations are executed starting from every platform tile. The graph is constructed by simply observing where Simon winds up. Specifically, given starting coordinates and an operation, the simulation will output the ending coordinates. If there are no ending coordinates, such as when Simon attempts to walk into a wall or into a pit, then it returns that the operation is invalid, and that edge is not part of the graph.
Creating that simulation required a careful study of Simon Belmont. Unlike other classic platformers where the player can accelerate from walking to running speed, whenever Simon moves horizontally, he always advances by exactly 1 pixel per frame. This holds true while walking, jumping, climbing staircases and even while being thrown back after a hit.
The horizontal speed limit makes barrier detection particularly easy. The game checks if there is wall 1 pixel ahead and halts movement when necessary. It does this from about his nose down, permitting the top of his head to graze low ceilings without impeding horizontal movement.
Vertical motion is a bit more complex. If Simon walks off the edge of a platform, he immediately plummets 8 pixels per frame rather than gradually accelerating. Since each tile is 16 pixels tall (a multiple of 8), this presumably makes detecting the ground easier. The player simultaneously maintains a horizontal velocity of 1 pixel per frame in the direction that he was traveling just prior to the fall.
Simon’s sprite is 16 pixels across; however, he can only hang off a block by at most ±4 pixels from his midpoint. More than that and he’ll plunge to the ground below.
Interestingly, if he walks off a platform and drops down exactly 1 tile, then, at 1 horizontal and 8 vertical pixels per frame, he won’t fully clear the block when he lands. One of his feet will remain inside a wall, 2 pixels deep.
Afterwards, he’s able to walk away from the wall, but not deeper into it.
When jumping, Simon cannot change direction midair. Instead, the A button is a commitment to a fixed parabolic path.
Simon peaks at 36 pixels, enabling jumps onto platforms 2 tiles high. And the apex of the “parabola” is unusually flat. He appears to hang in space for 9 full frames, possibly to make whipping in midair easier. When there is nothing to land on, the parabolic motion will continue until Simon returns to his starting height. After that, he falls 8 pixels per frame, the same constant rate that happens when the player walks off a platform.
When there is a platform directly overhead, jumping is not permitted.
Otherwise, he can leap partially into platform tiles.
As mentioned, if he grazes more than the top of his head, Simon will stop moving horizontally. This often occurs, quite annoyingly, at the end of the first stage of level 4 when attempting to climb out of the cave.
Staircases permit free vertical movement through platforms.
In one instance, Simon walks upstairs into solid brick. Once there, he can freely walk out of the wall.
On moving platforms in level 4, the player normally ducks low hanging stalactites. However, it is possible to stand up into them. The game inhibits horizontal movement in that situation, rapidly dragging Simon into the watery pit.
The physics simulator that generates the directed graphs treats Simon as a rectangle. Movement of that rectangle is restricted based on the laws of motion described above. To prevent the bot from hopping from place-to-place like a bunny rabbit, jump graph-edges were assigned a higher cost than walk and stairs graph-edges.
Given any starting tile and any ending tile, the table generated by the pathfinder provides the shortest distance between them (the total path cost) and a description of the first step of the journey. That description includes the first operation to execute along the path and the tile that you’ll end up on after executing that operation. The entire path can be reconstructed through repeated lookups, each providing a successive step toward the ending tile.
In some substages, the graphs are not fully connected. For example, in Level 4, the moving platforms are the only way to cross the chasms. For those substages, the table provides a way to navigate within each island, but not between them.
Hidden items are often concealed within blocks that can be broken. And breaking blocks alters the graph. To get around this, the pathfinding algorithm was applied to the substages with and without broken blocks. At runtime, CastlevaniaBot observes the states of the breakable blocks and uses the appropriate lookup table, accordingly.
CastlevaniaBot integrates with Nintaco through its API. It registers an implementation of FrameListener to receive a called back once per frame. Since the emulator runs at approximately 60 frames-per-second, that listener needs to return in a timely manner; long computations or sleeps will slowdown or lockup the emulator. In its brief sliver of time, CastlevaniaBot reads the game state, it identifies the primary target, it switches strategies if the primary target changed, and it advances the current strategy.
CastlevaniaBot reads Simon Belmont’s current state directly from CPU RAM. But I couldn’t figure out exactly how all the other game objects are represented in memory. Instead, CastlevaniaBot reads directly from Object Attribute Memory (OAM), the region that stores the displayed sprite list.
That technique works and it’s generally applicable to other games, but it has a lot of shortcomings. The order of sprites in OAM is constantly changing. If there are multiple instances of the same enemy type onscreen, the only way to track them is through proximity, by matching up the latest sprite coordinates with the coordinates on the prior frame.
Some game objects are constructed out of repeating sprites, such as the bone towers.
Moving platforms are composed of the same sprite repeated 4 times.
Sorting both cases out requires additional logic, which isn’t that difficult. On the hand, subweapon upgrades and some of the subweapons themselves use common sprites. Even worse, in level 5, knights borrow Simon’s subweapon sprites.
Luckily, aside from holy water, CastlevaniaBot only uses subweapons where upgrades are generally unavailable, such as boss fights. And the holy water upgrade sprite is not the same one used while throwing it.
A few game objects flash as they spawn, such as the crystal balls that appear at the end of boss fights, the sickles manifested by Death and Dracula’s body. Flashing sprites keep appearing and disappearing from OAM, requiring extra logic to track those objects.
On a side note, due to hardware limitations, the NES can only display 8 sprites per scanline. Since sprite priority is determined in part by its index in OAM, the ordering is deliberately scrambled each frame to avoid any bias that would consistently make the same sprite invisible. Instead, multiple sprites flicker as they each take turns being low and high priority. That flicking has no effect on reading sprites from OAM. The data is there, but the emulated hardware doesn’t to display them. It’s unlike the situation with the flashing-on-spawn sprites discussed above. Also, Nintaco provides an option that can greatly reduce the hardware flickering.
Finally, a tiny bit of game state is read from the PPU nametables, the region of memory containing the background data. This includes checking breakable blocks and observing the position of the crushers in level 2.
Strategies are state machines. CastlevaniaBot defines them as an abstract class with init and step methods. The init method is invoked when CastlevaniaBot switches to that strategy, enabling the state machine to reset to its starting state. And the step method advances the strategy. For instance, the step method of the fishman strategy checks if a fishman is in whip range and if so, it whips. Otherwise, it checks if jumping would put it into whip range and if so, it jumps. Finally, if it’s standing too close to a fishman, it moves away from it. With those simple rules, CastlevaniaBot defeats fishmen.
To make writing strategies as easy as possible, I created a library of actions that they can carry out. E.g., instead of asserting and releasing the A button to jump, it simply calls the library’s jump method. And prior to that, it will ask the library if Simon is currently on a platform and capable of jumping.
Moving toward or away from a target are common actions that work by executing the operations in the table produced by the pathfinding algorithm. For example, the candles strategy uses a library method called routeAndFace that not only directs Simon to some specified coordinates, it faces him left or right after getting there. And once there, depending on the height of the candles, the strategy may jump or kneel before whipping. The item released by the candles will spawn midair and drop or float to the ground. The strategy designed to get items directs Simon to the nearest tile directly underneath it even before the item touches down.
For moving away from enemies, the library needs to know how to go leftward or rightward without falling into pits. This is generally done by pathfinding to the left or right edges of the substage. But in certain regions, the shortest path to the left edge might initially involve going right or vice versa. When those issues cropped up, substage-specific logic was introduced to direct Simon to the left and right edges of the current platform.
In this section, I detail all the strategies used by CastlevaniaBot by providing commentary for a full playthrough.
The game starts in the courtyard in front of the castle. The objects in frame are ranked to select a primary target, which, in this case, is the nearest fire column. The strategy for handling fire columns instructs it to approach the column and to use the whip when in range.
Whipping a column destroy it and releases an item, all of which are ranked higher than fire columns. Consequentially, CastlevaniaBot responds by employing the strategy to collect the released item before advancing to the successive columns.
In ranking objects, CastlevaniaBot always keeps in mind the long-term goal of getting through the level before time expires. It’s list of potential targets is always seeded with the door to the next stage. The door is assigned a low rank, but when all the fire columns are destroyed, and all the items are collected, it will take priority. Well, with one exception here: CastlevaniaBot is aware of how to trigger all the hidden treasures and it will hop over the castle entrance to release the flashing money bag.
Upon entering, CastlevaniaBot is greed by ghouls and candles. The candles and released items will take priority until the ghouls get near.
Often, the whip appears to destroy enemies without making contact. I located the table of collision boxes in the game ROM and CastlevaniaBot uses it to know exactly when something is in whip range. And, since the collision boxes often extend slightly beyond the bounds of the sprites, the whip can strike invisibly.
In most cases, CastlevaniaBot jumps vertically when whipping candles instead of leaping forward. This is a risk aversion tactic. Since it’s impossible to change direction midair, an approaching crowd of enemies could make landing safely difficult or impossible during a forward leap. In addition, by jumping vertically, CastlevaniaBot remains on the same block; it doesn’t have to perform checks to see if the jump would set it back on a lower platform or at the bottom of a pit.
When there are no candles to whip or items to collect, CastlevaniaBot will chase down ghouls. But the panther strategy directs it to wait in place with the expectation that the enemy will run into whip range.
Besides providing hearts and other items, candles are arranged to lead the player on a path through the stage. For example, in the image below, the candles in the upper-right corner invite the player up the staircase. However, to go upstairs, the player initially needs to walk left, which scrolls the candles offscreen. Since CastlevaniaBot’s decisions are based on prioritizing the objects it can see, this situation could lead to an infinite loop where it alternates between the shortest path to the candles (leftwards) and the shortest path to the exit door (rightwards).
There are several ways issues like this could have been resolved. For instance, CastlevaniaBot could have been equipped with object permanence, the understanding that objects continue to exist even when they cannot be seen. But that still requires it to see them in the first place. Had the candles been further to the right, it would have to backtrack even more after discovering them.
With that in mind, I introduced incentives to encourage CastlevaniaBot to explore areas of a stage that would normally be ignored. The incentives work just like the exit doors, attracting CastlevaniaBot to where it should go. In addition, I added rules that cause it to ignore candles and items that are too far away (by walking distance, not straight-line distance).
After proceeding upstairs, whipping a candle releases holy water, which is more valuable than the other subweapons. CastlevaniaBot will choose to exchange the dagger for it.
Like the flashing money bag in front of the castle, CastlevaniaBot is aware of all the breakaway blocks that conceal items and it will execute a strategy similar to the one that handles candles to whip the blocks.
As CastlevaniaBot advances forward, you’ll notice that it starts using holy water to destroy candles and ghouls. This might seem excessive, but it serves an important purpose. Castlevania rewards players for using subweapons with double and triple shots. In other words, CastlevaniaBot grinds for shot upgrades.
When the B button is pressed, there is 16 frame delay before the whip strikes. The whip appears extended for an addition 10 frames, but it’s only effective for the first of those 10. CastlevaniaBot uses this fact to improve targeting. Specifically, it tracks the velocities of all the objects in frame with the assumption that the primary target will continue a linear trajectory. Then, it will assert the B button 16 frames ahead of when the target is expected to encounter the whip strike. An enemy can always change direction within those 16 frames, but generally this simple heuristic works.
However, after passing through a door, CastlevaniaBot encounters red bats. Like medusa heads, red bats fly across the screen, bobbing sinusoidally through platforms and staircases. To project where a red bat will be 16 frames in the future, I recorded the motion of one into a table. At runtime, CastlevaniaBot tracks the bats and waits for crests or troughs, when the vertical velocity switches direction. Then, it’s able to line up the coordinates with the values in the prerecorded table. This enables the red bat handling strategy to whip, duck or jump over flying red bats.
When speedrunners play through Castlevania, they perform maneuvers that make the game as deterministic as possible. For example, at the end of Level 1, they discovered that if they break the block and collect the shot upgrade with a particular timing sequence, then the boss will respond with a favorable pattern, resulting in a quick win.
No matter how skilled they are, humans cannot fully tame the RNG; however, since CastlevaniaBot can control button presses at frame granularity, it could take that speedrunning concept to the extreme by playing exactly the same game during each run. If it did, it would hardly be better than a TAS recording. Instead, CastlevaniaBot deliberately introduces minute errors and delays into its actions using its own external RNG to avoid deterministic gameplay. For instance, when it whips a high candle it intentionally delays the jump and the whip strike by a few random frames. Tiny changes like that have a significant effect on how the game plays out.
While CastlevaniaBot tries its best to avoid determinism, it did borrow one concept from speedrunning: damage boosts. 50% of the time, CastlevaniaBot will avoid the fishmen dungeon entirely by jumping backwards onto a red bat and getting thrown back onto a normally unreachable platform.
The other half of the time, CastlevaniaBot deals with the fishmen. Their fireballs are ranked high and CastlevaniaBot will whip, duck or jump them as the situation demands.
Most players tend to run through the fishmen section due to the unpredictable nature of the spawning enemies and their fireballs. But CastlevaniaBot takes it time, collecting all the hearts and even the hidden treasure at the very right. It knows the exact item contained within each candles and, since it prefers holy water, it chooses to skip the candles concealing the stopwatch. However, by sticking around and fighting the fishmen, sometimes obtaining the stopwatch is unavoidable.
Stages often end with crosses, which destroys all onscreen enemies. If you were ever curious, crosses cannot kill end bosses. In fact, sometimes the crosses spawn during boss fights. For example, while fighting Medusa, whipping snakes sometimes release crosses. And those crosses are limited to killing other snakes.
After passing through the door, CastlevaniaBot encounters more ghouls. In the screenshot below, it wants to jump onto the lower platform, but its movement is constrained. Whenever the table provided by the pathfinding algorithm instructs CastlevaniaBot to jump, it examines the space around the target platform. If it’s going to land into enemies, it won’t carry out the jump. In this case, that mechanism causes CastlevaniaBot to wait until the ghouls walk out of the way.
This check-for-enemies-before-jumping rule illustrates one of the philosophies behind CastlevaniaBot’s design: it should act through simple rules that are as generic as possible. In some parts of the game, one-time-use strategies had to be written to address very specific scenarios. But, for most of the game, its actions are dictated by reusable heuristics. I did not instruct it to pause at this particular point to wait for the ghouls to move out of the way. Rather, this behavior emerged as a result of the heuristics.
CastlevaniaBot completes the level by killing the Phantom Bat with triple holy water. But its attack strategy is determined by its subweapon. In fact, if it has no subweapon, it’s prepared to kill the boss with its whip alone. Killing the Phantom Bat with the axe is particularly interesting. Like the red bat, I recorded the parabolic motion of the axe into a table. At runtime, CastlevaniaBot offsets the table, aligning it with each of the floor tiles. This enables it to compute the optimal spot to axe the boss.
Just prior to collecting the crystal ball, CastlevaniaBot tosses it’s subweapon around, knowing that it will freeze midair as soon as the crystal ball is touched. Then, it repeatedly jumps and whips randomly, hoping to get frozen in a strange pose.
At the start of level 2, CastlevaniaBot avoids the first candles, which contains the boomerang. The strategy for the spear knight is like the ghouls or fishmen; however, it’s the first enemy that requires 2 hits to die. The black bat is dormant until approached, then it flies linearly enough to be whipped with the aforementioned simple heuristic.
After breaking the wall bricks, 50% of the time CastlevaniaBot appears to leave the room without collecting the crown. Or, does it?! In those cases, it actually collects the crown by taking advantage of a bug in the game. Since the end of the upper staircase aligns with the crown below it, the player momentarily wraps around as he walks up and off screen. If you listen for the collect-treasure sound or if you pay attention to the score, you’ll see that the crown is indeed acquired.
In level 2, enemies do not attack the player while on a moving platform. CastlevaniaBot simply needs to wait for the platform to arrive, walk onto the platform, wait for it to move to the other side and then walk off the platform. There’s a slight variation for platforms that do not bump up against the tiles at either end. In those cases, CastlevaniaBot jumps, rather than walks, on and off the platform.
A door leads to a hallway full of flying medusa heads and CastlevaniaBot responds by walking forward. Like the moving platforms, CastlevaniaBot knows to employ this strategy based on its location rather than through the prioritization of the onscreen game objects. However, as soon as the medusa heads pass, it switches back to that technique to decide which strategy to use next.
Another location-based strategy happens after walking up the next staircase into a medusa heads infested region. 50% of the time CastlevaniaBot intentionally jumps into a medusa head to get a damage boost that springs it up to the platform above, close to the door leading to the next stage. This is the only other damage boost that CastlevaniaBot knows about. Unlike the speedrunners, it doesn’t do this to save time. Instead, it’s just another contributor to the nondeterminism.
Walking through the crushers gauntlet is an interesting location-based strategy that is repeated 3 times over. CastlevaniaBot waits for the crusher immediately to its left to get into position, then it makes a run for it. It stops after it passes through, turns around, whips candles, collects the released item, and it repeats with the successive crushers. One of the items is potentially the valuable holy water; so, it always goes after those candles.
Ghosts and bone towers make their first appearances after the crushers. Ghosts are easy to target, but they require multiple hits to take out. Bone towers are even easier to target since they don’t move. And the same strategy that is used for the fishmen’s fireballs is recycled for theirs.
Level 2 usually ends with CastlevaniaBot swiftly taking out Medusa after stunning her with an endless stream of holy water. However, it’s prepared to work with any of the other subweapons.
Level 3 introduces the fleamen. CastlevaniaBot responds by waiting for them to jump into whip range. If the fleamen happen to jump over the player, CastlevaniaBot will move in the opposite direction and whip them before they hit the ground.
White skeletons come next. They have a very random pattern. In addition, they throw bones. In level 3, CastlevaniaBot tries to avoid getting hit by them. But in successive levels, I found that the bones are a distraction and it’s more efficient to ignore them. For white skeletons, CastlevaniaBot’s strategy is to charge them.
CastlevaniaBot waits for ravens to approach. Then, based on the raven’s height relative to the player, it calculates exactly when to deploy the whip after jumping.
After entering the next stage, CastlevaniaBot deliberately whips candles that release a stopwatch and then it waits for the stopwatch to vanish. Slightly ahead and just off screen is a raven. It takes out the candles prior to engaging the raven to reduce the risk of accidentally hitting them during the fight and inadvertently acquiring a subweapon that it doesn’t want.
Just before the mummies, CastlevaniaBot walks left into a platform to trigger a hidden money bag. It does this just for fun since there is no way to acquire it.
Next, CastlevaniaBot intentionally whips candles that release a dagger. As with the stopwatch, it does this to avoid inadvertently doing so during its subsequent actions.
Finally, the mummies succumb from raining holy water.
As with all bosses, CastlevaniaBot is prepared to use whatever subweapon is available. In fact, its subweapon strategies will completely change if, for whatever reason, the block containing the pork chop is broken. Without that block, it’s impossible to climb to the upper platform, forcing it to fight on ground level.
Moving platforms return in level 4. And this time red bats like to get in the way. To reduce the odds of getting hit, Castlevania bot waits for the arrival of a platform to coincide with whipping a red bat. Since red bats appear at a fixed period, this provides CastlevaniaBot with the time required to traverse the water pit bat-free. It’s prepared to deal with bats and the randomly appearing fishmen while on the platform, but they make jumping on and off platforms extremely dangerous. The strategy that CastlevaniaBot carries out puts the odds in its favor.
The same strategy is repeated in the middle of the stage. This time, the leap to the moving platform is much wider, making it critical to take out the red bat prior to the attempt.
As illustrated in the screenshot above, candles are always spaced 64 pixels apart. This might be an artifact of the way level data is represented in the ROM, in a vector-graphics-like format that saves storage space. But for some reason, the designers chose to lineup candles with tile edges instead of tile centers. In this case, the candles lineup with both ends of a platform. Consequentially, when whipping them, the released item can drop straight through unsupported into the water pit below.
I believe that at some point, the designers recognized this problem. But by then, offsetting the entire train of candles on all the existing levels to align them with tile centers may have introduced other issues. Instead, they chose to randomly stagger candles one pixel left or right when they spawn. As a result, when the candles on the right in the screenshot are whipped, there is a 50% chance that the holy water within will land on the platform. The other half the time it drops into the water pit.
CastlevaniaBot usually avoids those candles entirely since it is rather successful at holding onto holy water. But if it needs it, it will position itself very close to those candles before whipping to guarantee that the released holy water is successful acquired.
Ahead, CastlevaniaBot takes on gobs of fleamen. In this region, killing fleamen tend to release axes. CastlevaniaBot avoids them since holy water is especially useful for the boss.
CastlevaniaBot completely ignores the bone dragon as it enters the final stage of the level.
But it takes out the next 2 through rapidly whipping.
Frankenstein’s Monster and Igor are obliterated with a constant barrage of whipping and holy water. As with all bosses, CastlevaniaBot can work with the other subweapons or no subweapon at all. However, it’s odds of survival are reduced without holy water.
In level 5, CastlevaniaBot deals with white skeletons, once again. But this time it uses some strategy variations rarely seen in level 3. Depending on where they show up, CastlevaniaBot tosses holy water and then walks away to draw the skeletons into the flames. Near staircases, it walks under them to direct them to where they need to be.
The resurrecting red skeletons make their debut in level 5. CastlevaniaBot tracks the time since they were last hit to know when it’s safe to cross the path of red bones.
The first room of stage 14 is handled entirely through one colossal strategy. First, CastlevaniaBot takes out the fleaman. Then, it waits for the lower knight to toss an axe. It whips the axe and then it slowly walks up the lower staircase. This pushes the lower knight off screen, causing it to despawn. Next, it waits for the upper region to be free of axes. Then, CastlevaniaBot hits the candles and collects the released item. Afterwards, it approaches the base of the staircase leading to the upper knight. When the upper knight tosses a high axe, CastlevaniaBot makes a run for it. This pushes the upper knight left and mostly off screen, but it won’t despawn there. Instead, CastlevaniaBot ducks under the returning axe and potentially under a second tossed axe before it finally heads up the staircase into the next substage. Phew!
CastlevaniaBot encounters an axe knight again after traversing some staircases. It uses holy water to stun it before whipping it into oblivion. If holy water were unable, it would keep whipping, chasing down the knight until it was dead.
When navigating stairs in level 5, CastlevaniaBot often must wait for a red skeleton to move away from either the top or bottom of the staircase. Toward the end of the level, a bone tower at the top makes the job even more difficult. Depending on how the skeletons decide to wander about, CastlevaniaBot bobs up and down the stairs until it’s clear to proceed.
Handing red skeleton groups requires a bit of extra logic to prevent an infinite loop. If CastlevaniaBot whipped them individually such that interval between the whips was long enough to enable the first-whipped to reanimate, then it will enter a cycle where it keeps destroying endlessly reanimating skeletons. To prevent this, CastlevaniaBot will not whip a red skeleton that is standing close to a pile of red bones. That rule allows the red bones to reanimate near the existing red skeleton, providing the opportunity for them to be whipped together. Without an interval between their destruction, a cycle won’t form.
To avoid the medusa heads in the long hallway leading to Death, it never stops walking, stunning the knights that would normally get in the way. It takes advantage of the fact that the player can walk straight through enemies stunned by holy water without taking a hit.
If holy water is unavailable, CastlevaniaBot can pick up the boomerang just before the hallway. With some luck, it can use it to defeat the knights in addition to acquiring shot upgrades.
CastlevaniaBot stuns Death with holy water before he can start throwing sickles, rapidly taking him out. It can also beat Death with the triple boomerang, but that usually requires several attempts.
CastlevaniaBot’s principal strategy to get across the bridge at the start of level 6 is to keep on walking. It whips giant bats above once in attempt to stun them. And it jumps over giant bats that swoop in from below. It also occasionally needs to dodge or whip fireballs thrown by the bats.
Making it across the bridge is not guaranteed. It all depends on how friendly the giant bats want to be on a given attempt.
In the following substage, CastlevaniaBot uses a stopwatch acquired on the bridge 2 or more times to get past the eagles and fleamen. Without the stopwatch, it tries its best to whip its way through.
When CastlevaniaBot arrives at Dracula’s tower, it may go up and down the stairs multiple times to regenerate the candles, enabling it to collect at least 20 hearts.
The right-most candles in Dracula’s chambers yield holy water, which is required for Dracula’s second form.
Dracula’s first form requires 16 hits to the head. CastlevaniaBot repeatedly walks in front of Dracula, waits for him to shoot fireballs, then it jumps up and over the fireballs and strikes Dracula’s head with the whip.
Dracula’s second form, a.k.a. Cookie Monster, is stunned momentarily with holy water and repeatedly whipped in the head. Cookie Monster occasionally jumps toward the player and CastlevaniaBot dodges accordingly. Cookie Monster also throws fireballs which the holy water and whipping usually take out. Doing so sometimes produces a shot upgrade. And double holy water will trap Cookie Monster in permanent stunlock, leading to a rapid win.
CastlevaniaBot is not able to play through Difficult Mode, following the credits. However, after restarting in the castle courtyard, it resets the game loop byte to zero, switching it back to Normal Mode. This enables CastlevaniaBot to seemingly play perpetually.
The .zip contains:
Copyright © 2018 meatfighter.com