Bot playing in Castlevania
What is it
CastlevaniaBot is a plugin for the NES Nintaco emulator that plays Castlevania. If you run it on the splash screen, the plugin will go through the whole game from start to finish. Or you can run it anywhere in the game so that it passes its part.
In this article, I will tell you how I created a bot capable of passing Castlevania, and how you can create something similar for any game on the NES.
Knowledge based structure
This project did not use machine learning. Rather, the development can be called "learning the machine." I know how to go Castlevania. The difficulty was to write my knowledge into a computer program. The result was a system that simulates the same decision-making process that I carry out with the controller in my hands. To create it, it was necessary to clearly state the detailed details of the physics that control the bit world of Simon Belmont, and all the tactics needed by an experienced vampire hunter.
CastlevaniaBot has access to a set of strategies to cope with a wide range of situations. Most of them are designed to work with a specific type of game objects. For example, there is a strategy to fight the skeletons, another one for fish people, for breaking candles, for gathering hearts, and so on.
CastlevaniaBot constantly monitors the state of the game and, if necessary, switches between different strategies. The decision-making process uses the fitness function, which ranks all the game objects on the screen. At the top of the list is the main goal, and when it changes, the bot changes its strategy. For example, CastlevaniaBot may be preparing to hit candles when a bat flies into the frame. Depending on the distance to the bat, CastlevaniaBot can react by switching from the candle strategy to the bat strategy. Having destroyed the bat, he will continue to work with the candles.
Before making a decision on switching, CastlevaniaBot considers the current goal and strategy. If he does not succeed, he can get stuck in an infinite loop, switching back and forth between two targets with equal or almost equal priority. To avoid this, when a new primary goal appears, which is only slightly higher in priority to the current goal, CastlevaniaBot may decide to continue the current strategy.
Some strategies automatically run when they hit a specific area. Usually they are intended for simultaneous processing of several game objects. For example, in the corridor with a bunch of flying heads of jellyfish, it’s best to just go ahead and not aim at each head individually.
Some strategies may vary depending on the current secondary weapons and the number of hearts collected, in particular, in battles with bosses. CastlevaniaBot is trying to make the best decision based on the tools it has and the current situation.
Making a plan for an 8-bit world
When working on such projects, I primarily strive to simplify the task. I imagined what Castlevania would look like if there were no enemies, candles and collected items on the levels. All that would be needed in that case is simply to go from the beginning to the end of the level. I wondered if I could teach a bot to do it, how difficult would it be to destroy several enemies along the way?
To teach the bot to move, I needed tile maps of backgrounds and an understanding of how levels are organized. The game consists of six levels, each of which ends with a boss.
Each level is divided into 3 or 4 stages. The stages are usually separated by wooden doors, which creak open and slam behind the player’s back.
Doors are control points (checkpoints). If a player is killed, he returns to the beginning of the stage, but only if he has not ended his life. If you continue the game after Game Over, the player is sent to the very beginning of the level.
The stage number indicates the total number of checkpoints completed since the beginning of the game. The last stage is number 18. But if you kill Dracula, the game starts from the very beginning in Difficult Mode, and the numbers of the stages continue to increase to 19 and further. If you go through the Difficult Mode, the third cycle of the game does not become more difficult, but the numbers of the stages still continue to increase.
Each stage consists of one or more background bands with horizontal scrolling, which I call “sub-steps.” If you go beyond the screen on the stairs leading up or down, the game moves from one sub-step to another, rather than scrolling vertically.
The game uses 3 bytes to track the game cycle number, stage number and substage number. The game loop in normal mode (Normal Mode) is set to 0; values of 1 and above indicate Difficult Mode. Regardless of the game cycle, the stages are always numbered from 0 to 18. And the sub-stages always have the value 0 or 1, because the stages never contain more than 2 horizontal stripes. CastlevaniaBot tracks these bytes to know where it is.
For my convenience, I recorded the background strip of each sub-step in a separate graphic file. If I needed to find out the exact coordinates of some object, then I could quickly find them out using a graphical editor. I recorded the files using the Nintaco’s built-in Map Maker tool. I turned it on, and then went through the whole game. Some of the resulting images contained several sub-steps joined together that were easy to break apart.
Having studied the images of the backgrounds, I realized that the only important tiles are platforms and stairs. Everything else can be considered empty space. Ladders are of two types: leading forward or backward (they can be represented as the left and right edge of an isosceles triangle). Sometimes the stairs end with a platform on which a player can walk.
There are only 5 important types of tiles, and at each level they have a different appearance. I copied and pasted them into separate graphic files of size 16 × 16. Then I wrote a program that compares each tile in each sub-step with a corresponding set of images. So I got a matrix of types of tiles for all sub-steps.
The matrices could be extracted directly from the ROM, but I could not find the documentation on how and where the data is stored. Since the ROM space is limited, these levels are usually compressed, resembling a vector graphics format. Each game uses its own format, so I did not consider it necessary to conduct research, because I had Map Maker. In addition, I still needed graphic images of sub-steps. If I had not captured the background bands, then I would have to write a program that generates images from the matrices.
Search for ways
Having created the matrices, I wanted to apply a pathfinding algorithm, namely the Floyd-Warshell algorithm , which yields a table containing the shortest paths between each of the pairs of vertices of the oriented graph with weighted edges. The idea was to pre-compute the tables and write them into files, and then load them during the execution of the game. With tables in memory, a bot can search and instantly recognize the shortest path between any two platform tiles.
The graph consists of edges and vertices. If platform tiles are vertices, then edges are only those operations that Simon can perform to move from one platform to another. Operations performed within one tile are prohibited. For example, on a plane from tiles, Simon can move only one tile to the left or one tile to the right.
Similarly, if Simon is on the stairs, he can move one tile in one of two possible directions.
These are valid operations. But such actions as moving from the middle point of a tile to the edge of a tile are too fractional, because they do not correspond to the transition from one vertex of the graph to another.
In addition to walking left-right, descending-raising the stairs, Simon can jump to another tile. And he can jump left or right, starting from any of the 16 pixels of the tile surface. To reduce the number of edges in the graph (and the size of the lookup table), I considered only five possible points of repulsion:
Adding the “do nothing” operation, I received 15 operations. All of them are simple enough so that the bot can easily determine the sequence of keystrokes needed to execute them during the execution of the game.
To build a complete graph, I created a very simple simulation of Simon’s physics of the world. In this simulation, all 15 operations are performed starting with each platform tile. The graph is built by simply observing where Simon will be. More specifically, when specifying the initial coordinates and operations, the simulation gives the final coordinates at the output. If there are no end coordinates, for example, when Simon tries to go into a wall or into a pit, then the program returns that the operation is invalid and this edge is not part of the graph.
To create this simulation it took careful study of Simon Belmont. Unlike other classic platformers, where the player can accelerate from walking to running, Simon, when moving horizontally, always moves exactly 1 pixel per frame. This is true for walking, jumping, climbing stairs and even when throwing back when attacking enemies.
Limiting the horizontal speed greatly simplifies the recognition of barriers. The game checks if there is a wall in one pixel in front of the character, and if necessary, stops the movement. The check is performed below head level, which allows the head to pass under low ceilings without interfering with horizontal movement.
With vertical movement, things are a little more complicated. If Simon comes off the edge of the platform, instead of gradually accelerating, he instantly falls down at a speed of 8 pixels per frame. Since each tile has a height of 16 pixels (which is a multiple of 8), ground recognition is simplified. At the same time, the player maintains a horizontal speed of 1 pixel per frame in the direction immediately before the fall.
Simon's sprite width is 16 pixels, and nevertheless, it can hang over a block a maximum of ± 4 pixels from its midpoint. If you move a little more, it will fall below.
Interestingly, if it goes off the platform and drops exactly 1 tile at a speed of 1 horizontal and 8 vertical pixels per frame, it will not exactly stand on the block when landing. One of his legs will remain inside the wall at a depth of 2 pixels.
After that, he will be able to get out of the wall, but not go into it.
During the jump, Simon cannot change his direction. After pressing the button A, he makes a fixed path along a parabola.
At the top point, Simon rises 36 pixels, which allows him to jump onto platforms with a height of 2 tiles. And the top of the “parabola” is surprisingly flat. It seems that it hangs in space for 9 full frames, perhaps in order to simplify blows with a whip in the air. If Simon has nothing to land on, then the parabola continues until he returns to the original height. After that, it begins to fall at a speed of 8 pixels per frame, that is, with the same constant speed of falling from the platform.
When there is a platform directly above the character’s head, no jumps are allowed.
Otherwise, it partially “jumps” into platform tiles.
As mentioned earlier, if Simon touches more than the top of the head, he stops moving horizontally. This is quite annoying at the end of the first stage of level 4, when the player tries to get out of the cave.
Ladders allow you to freely move vertically between platforms.
In one case, Simon climbs the stairs, passing through the platform tile. Being on the stairs, he can freely pass through the wall.
On level 4 mobile platforms, a player usually ducks under low-hanging stalactites. However, you can climb and rest on them. In such a situation, the game restricts horizontal movement, quickly dragging Simon into a water trap.
A physics simulator that generates directed graphs considers Simon to be a rectangle. The movement of this rectangle is limited by the movement rules described above. So that the bot did not jump from place to place like a rabbit, the ribs of the count's jumps were assigned a higher cost than the edges of walking and walking along stairs.
The table generated by the pathfinding algorithm contains the shortest distance for each initial and final tile (total cost of the path) and a description of the first step of the path. This description includes the first operation that must be performed on this path, and the tile on which the character will be after its execution. The entire path can be recreated by re-searching the table, each of which gives a subsequent step in the direction of the final tile.
In some sub-steps, the graphs are not fully connected. For example, at level 4, the only way to cross the chasms are platforms. In such sub-steps, the table contains ways to move around each of the islands, but not between them.
Some destructible blocks contain hidden objects. And the destruction of blocks changes this graph. To circumvent this problem, an algorithm for finding paths with and without breakable blocks was applied to the substeps. At runtime, CastlevaniaBot monitors the states of the blocks being split and uses the appropriate lookup table.
CastlevaniaBot integrates into Nintaco through its API . It registers the implementation
FrameListenerto get a return in each frame. Since the emulator runs at about 60 frames per second, this listener must be returned on time; lengthy calculations or downtime will slow down or block the emulator. In a short period of time, CastlevaniaBot reads the state of the game, determines its main goal, switches strategies if the goal has changed and executes the current strategy.
CastlevaniaBot reads the current state of Simon Belmont directly from the processor's RAM. But I can not determine how other game objects are represented in memory. Therefore, CastlevaniaBot reads directly from the memory object attributes (Object Attribute Memory, OAM) - the area that stores the list of displayed sprites.
This technique works and is generally applicable to other games, but has many drawbacks. The order of sprites in OAM is constantly changing. If there are several instances of the same type of enemy on the screen at the same time, then the only way to track them is to determine their proximity, to compare the last coordinates of the sprite with the coordinates from the previous frame.
Some game objects consist of repetitive sprites, such as bone towers.
Mobile platforms consist of one sprite repeated 4 times.
To sort both of these cases, additional logic is required, which is easy to implement. Secondary weapon upgrades and some types of secondary weapons use the same sprites. Worse, at level 5, the knights borrow the sprites of Simon's secondary weapon.
Fortunately, with the exception of holy water, CastlevaniaBot uses secondary weapons only where upgrades are usually not available, for example, in boss fights. And the sprite upgrade of holy water is different from the sprite used when throwing it.
Some game objects blink when they are created, such as crystal balls at the end of boss fights, Death Scythe and Dracula’s body. Flashing sprites appear and disappear from OAM, so additional logic is required to track these objects.
It is also worth noting that due to hardware limitations, NES can only display 8 sprites per raster line. Since the priority of sprites depends in part on their indices in OAM, the order in each frame is randomly shuffled to avoid a shift that makes one sprite invisible all the time. Several sprites blink in turn, gradually changing their priority. This blinking does not affect the reading of OAM sprites. The data still remains there, but the emulated hardware does not display it. This is different from the situation described above with sprites flashing when created. In addition, Nintaco has an option that significantly reduces hardware blinking.
Finally, a small portion of the game state is read from the PPU name tables — a memory area containing all the background data. This includes checking destructible blocks and tracking the positions of the “crush” level 2.
Heuristic state machines
Strategies are state machines. CastlevaniaBot defines them as an abstract class with methods
step. The method
initis invoked when CastlevaniaBot switches to the appropriate strategy, allowing the state machine to reset to its original state. And the method
stepperforms the strategy. For example, the
stepstrategy method for people-fishes checks whether a person-fish is within the range of a whip strike, and if so, the bot hits the whip. Otherwise, it checks whether it is possible to reach the strike distance with a jump, and if so, the bot jumps. And finally, if the bot is too close to the enemy, it moves away from him. With these simple rules, CastlevaniaBot defeats people-fishes.
To make writing strategies as simple as possible, I created a library of possible actions to be performed. For example, instead of pressing and releasing the A button for a jump, the bot simply calls the jump method from the library. And before that, he asks the library whether Simon is on the platform and can jump.
Approximation and removal from the target are standard actions performed using operations from the table created by the pathfinding algorithm. For example, the candle strategy uses the library method
routeAndFacewhich not only directs Simon to any specified coordinates, but also turns him to the left or to the right after hitting them. In addition, depending on the height of the candles, the strategy performs a jump or a squat before a blow with a whip. The object falling out of the candles will be created in the air and will fall or slowly fall to the ground. The elevation strategy directs Simon to the nearest tile directly below him, before the object touches the ground.
To move away from enemies, the library needs to know how to move left or right without falling into the pits. In general, this is done by searching for paths to the left or right edges of the sub-step. But in some areas the shortest path to the left edge initially requires moving to the right, and vice versa. When similar problems arose, I added logic specifically for the substeps, directing Simon to the left and right edges of the current platform.
In this section, I will describe in detail the strategies used by CastlevaniaBot, commenting on the entire walkthrough.
The game begins in the courtyard in front of the castle. The objects in the frame are ranked to select the main target, which in this case is a column with a flame. The strategy for working with columns orders the bot to approach the column and use the whip when it is within reach.
After the blow of the whip and the destruction of the column, an object is created. The priority of all items is higher than that of columns with a flame. Therefore, CastlevaniaBot responds to this using the collection strategy of the item that has appeared, before moving on to the subsequent columns.
When ranking objects, CastlevaniaBot always takes into account a long-term goal - passing a level before time runs out. When creating a list of potential targets, the door to the next level is always added to it. Doors are assigned a low priority, but after the destruction of all columns and the collection of all items, it becomes a priority. With only one exception: CastlevaniaBot knows how to uncover all the hidden treasures, and jumps over the entrance to the castle to create a flashing bag of money.
After entering the castle CastlevaniaBot sees ghosts and candles. Candles and created items have a higher priority until the ghosts get closer.
It often seems that a whip destroys enemies without touching them. I found in the ROM of the game a table of collision rectangles, so CastlevaniaBot knows for sure when something is within the range of the whip. And since collision rectangles are often slightly protruded beyond sprite boundaries, the whip can strike an “invisible part.”
In most cases, when destroying candles, CastlevaniaBot jumps vertically, not forward. This is a risk avoidance tactic. Since it is impossible to change the direction of movement while in the air, a crowd of approaching enemies may make it difficult to land safely or make it impossible. In addition, with a vertical jump, CastlevaniaBot remains on the same block; he does not need to check whether the jump will lead to a fall on the lower platform or the bottom of the pit.
When there are no candles being destroyed or objects collected, CastlevaniaBot begins to haunt the ghosts. But the "strategy of the panther" orders him to stand still, waiting for the enemy to fall within the limits of the blow of the whip.
Besides the fact that candles serve as sources of hearts and other objects, they guide the player along the way through the stage. For example, in the image below, the candle in the upper right corner “invites” the player to climb the stairs. However, in order to climb up the stairs, the player initially needs to pass to the left, because of which the candles disappear from the screen. Since CastlevaniaBot solutions are based on prioritizing the items visible on the screen, this situation can lead to an infinite loop where the bot alternately chooses the shortest path to the candles (left) or the shortest path to the exit door (to the right).
Similar problems can be solved in several ways. For example, CastlevaniaBot can be equipped with memorization of objects, understanding that objects continue to exist, even if they are not visible. But for this, they still need to be initially seen. If the candles were even more to the right, then after their discovery one would have to go back even further.
With this in mind, I added incentives pushing CastlevaniaBot to research areas of the stage that he would normally ignore. These incentives work similarly to exit doors, attracting CastlevaniaBot to where it needs to go. In addition, I added rules that cause him to ignore candles and objects that are too far away (by distance, and not in a straight line).
After raising the stairs and destroying the candles, holy water is created - the most valuable of all secondary weapons. CastlevaniaBot chooses him by exchanging a dagger for him.
As in the case of a money bag at the beginning of the game, CastlevaniaBot knows about all destructible blocks with hidden objects, and he uses a strategy similar to that for candles to destroy blocks with a whip.
Upon further movement of CastlevaniaBot, you will notice that it begins to use holy water to destroy ghosts and candles. This may seem redundant, but serves an important purpose. Castlevania rewards players for using double and triple secondary weapons. In other words, CastlevaniaBot grindite upgrades of secondary weapons.
After pressing button B, there is a delay of 16 frames before hitting the whip. The whip remains long for an additional 10 frames, but is valid only in the first of these ten. CastlevaniaBot uses this fact to improve aiming. In particular, it tracks the speed of all objects in the frame, assuming that the main goal will continue to move along a linear path. He then presses button B for 16 frames before the target is to meet the blow of the whip. The enemy can always change direction during these 16 frames, but usually this simple heuristics works.
However, after passing through the door, CastlevaniaBot meets red bats. Like the jellyfish heads, red bats fly across the screen, flying through a sine wave through platforms and stairs. To predict where the red bat will be after 16 frames, I recorded the movement of one of them in the table. During the execution of the game CastlevaniaBot tracks bats and waits for peaks or minima of the trajectory, where the vertical speed changes its sign. Then he is able to compare the coordinates with the values in the previously created table. This allows the appropriate strategy to hit the red bat with the whip, to lean or jump over it.
During the high-speed passing (speedranes) of Castlevania, players perform maneuvers that make the game as deterministic as possible. For example, they found that if, at the end of level 1, to destroy a block and pick up a weapon upgrade in a certain time sequence, then the boss will behave in accordance with the desired pattern, allowing it to be defeated quickly.
No matter how experienced people may be, they cannot fully tame the random number generator. However, since CastlevaniaBot can control button presses with frame accuracy, it can bring the concept of high-speed transmission to its limit, each time passing the game in exactly the same way. If he did, it would be no better than passing TAS. Therefore, CastlevaniaBot arbitrarily adds errors and delays to its actions using an external random number generator, in order to avoid deterministic gameplay. For example, when he strikes a high candle with a whip, he deliberately adds a delay to the jump and strike for a random number of frames. Such tiny changes significantly affect the passing game.
Although CastlevaniaBot seeks to avoid determinism, it still borrowed one concept from speedrunning: damage boosts . In 50% of cases, CastlevaniaBot completely avoids passing the dungeon of human fish by jumping back onto the red bat, which throws it onto a platform that is otherwise unattainable.
In the other half of the cases, CastlevaniaBot chooses to fight with fish people. Their fireballs have high priority and CastlevaniaBot hits them with a whip, dodges or bounces depending on the situation.
Due to the unpredictability of the creation of enemies and their fireballs, most players usually run a part with fish people. But CastlevaniaBot spends time on them, gathers all the hearts and even the hidden treasure in the rightmost edge. The bot knows exactly what items are in each candle, and since he prefers to use holy water, he skips the candles, which are hidden chronometers. However, if you stay in this part and fight with people-fishes, then sometimes you can inevitably choose a chronometer.
Stages are often completed with crosses, destroying all enemies on the screen. In case you are curious, I will say - crosses cannot kill bosses at the end of a level. In fact, crosses are sometimes created even during boss fights. For example, in a battle with Medusa, crosses sometimes appear when killing snakes. But these crosses can only kill other snakes.
After passing through the door CastlevaniaBot again meets with ghosts. In the screenshot below, he wants to jump onto the lower platform, but ghosts prevent him from moving. When the table created by the pathfinding algorithm orders CastlevaniaBot to jump, it studies the space around the target platform. If it turns out that he will land on enemies, then the jump is not performed. In this case, this mechanism causes CastlevaniaBot to wait until the ghosts make room for him.
This rule “check the presence of enemies before a jump” illustrates one of the principles of the structure of CastlevaniaBot: it should be governed by simple, as generalized rules as possible. In some parts of the game you need to use one-time strategies that solve very specific problems. But in most of the game, the bot's actions are controlled by reusable heuristics. I did not write a command that made him stop at that particular point and wait for the ghosts to go astray. This behavior originated as a result of heuristics.
CastlevaniaBot completes the level by killing Phantom Bat with triple holy water. But his attack strategy is determined by his secondary weapon. In fact, if he had no secondary weapons, he was ready to kill the boss with one whip. A particularly interesting case is the killing of Phantom Bat with an ax. Similar to the case of the red bat, I recorded in the table the movement of the ax along a parabola. During the execution of the game, CastlevaniaBot performs a table offset, matching it with each of the floor tiles. This allows you to calculate the optimal point for killing the boss with an ax.
Immediately before picking up a crystal ball, CastlevaniaBot throws the secondary weapon in different directions, knowing that it will freeze in the air after it touches the ball. Then he randomly jumps repeatedly and hits his whip, hoping to stand in a strange pose.
At the beginning of level 2, CastlevaniaBot avoids the first candles in which the boomerang is hidden. The strategy of working with a knight spear campaign on the strategies of ghosts or fish people, but this is the first enemy, for the murder of which two blows are needed. A black bat slumbers until you approach it, after which it takes off and moves linearly enough to be killed with a whip using the simple heuristics mentioned above.
Having destroyed the bricks of the wall, in 50% of cases CastlevaniaBot seems to leave the room without lifting the crown. But is it? In fact, in such cases, he picks up the crown, taking advantage of the game's bug. Since the end of the upper ladder coincides horizontally with the location of the crown, the player, when passing upwards and beyond the screen, is momentarily below. If you listen to the sound or look at the glasses, you can see that the bot actually takes the crown.
At level 2, enemies do not attack a player when he is on a mobile platform. CastlevaniaBot just has to wait until the platform comes, go to the platform, wait until it reaches the other side, and then leave it. There is a slight variation for platforms that do not touch tiles on the other hand. In such cases, CastlevaniaBot does not step down, but jumps off the platform.
The door leads to a corridor filled with flying heads, and CastlevaniaBot reacts to this by moving forward. As in the case of mobile platforms, CastlevaniaBot knows that this strategy should be applied based on its position, and not on the prioritization of game objects on the screen. However, as soon as all the heads of the jellyfish fly, he again switches to this technique in order to choose the strategy that will be used later.
Another strategy, depending on the position, is triggered after raising along the next ladder leading to the area filled with heads of jellyfish. In 50% of cases, CastlevaniaBot intentionally jumps on the jellyfish head to get a damage boost, pushing it onto the upper platform next to the door leading to the next stage. These are the only two damage boost that CastlevaniaBot knows about. Unlike speedrunners, it doesn’t do it to save time, it’s just another contribution to non-determinism passing.
Passing through the "crush" is an interesting position-based strategy, repeated three times. CastlevaniaBot waits until the closest “crush” to its left reaches the desired position, then runs through it. After its passage, it stops, turns, hits the candles with a whip, picks up the created object and repeats the operation with subsequent “crush”. One of the items could potentially be holy water, so it always destroys these candles.
After the "crush" for the first time there are ghosts and bone towers. The ghosts are very easy to aim, but to kill them you need a few hits. It is even easier to aim at the bone towers, because they do not move. For their fireballs, the same strategy is used as for the people-fish balls.
Level 2 usually ends with CastlevaniaBot instantly killing Medusa with an endless stream of holy water. However, he is ready to work with any other type of secondary weapon.
At level 3 jumpers appear. CastlevaniaBot reacts to them by waiting for them to jump into the limits of the whip. If the jumpers jump the player, then CastlevaniaBot moves in the opposite direction and hits them with the whip before they touch the ground.
Further white skeletons appear. They have a very random pattern. In addition, they throw bones. At level 3, CastlevaniaBot tries to avoid them. But I found that at subsequent levels the bones only distract, and it will be more effective to simply ignore them. The strategy of CastlevaniaBot for white skeletons - just beat them.
CastlevaniaBot waits for the crows to fly. Then, based on the height of the crow relative to the player, he accurately calculates when to hit the whip after the jump.
After moving to the next stage, CastlevaniaBot independently strikes candles, from which a chronometer appears, and then waits until it disappears. A little ahead and behind the screen is a raven. The bot destroys the candles before raven battle, to reduce the risk of accidentally striking them and receiving unwanted secondary weapons.
Right before the place where the mummies appear, CastlevaniaBot goes to the left on the platform to bring about a hidden money bag. He does it just for the sake of interest, because he cannot raise it in any way.
Further, CastlevaniaBot deliberately strikes candles, from which a dagger falls out. As is the case with the chronometer, he does this so as not to pick it up randomly during subsequent actions.
Finally, the mummies are cast down by rain from the holy water.
To fight all the bosses CastlevaniaBot is ready to use any secondary weapon. In fact, the strategies for using secondary weapons completely change if, for some reason, a block containing a piece of pork is destroyed. Without this block it is impossible to climb the upper platform, because of which you have to fight on the lower level.
At level 4, moving platforms are returned. And this time there is a chance that red bats will appear on the way. To reduce the likelihood of their attack, he waits for the arrival of the platform to coincide with the destruction of the red bat. Since red mice appear at fixed intervals, this gives CastlevaniaBot enough time to cross the waterhole without bats. He is ready to deal with bats and randomly appearing human fishes while he is on the platform, but this makes jumping to and from the platform very dangerous. The strategy used by CastlevaniaBot increases the likelihood of its success.
The same strategy is repeated in the middle of the stage. This time the jump to the mobile platform is much longer, so it is crucial to destroy the red bat before the jump.
As shown in the screenshot above, the candles are always located at a distance of 64 pixels from each other. Perhaps this is an artifact of the fact that the level data is presented in ROM in a vector-like format that saves space. But for some reason, the designers decided to align the candles not with the centers, but with the edges of the tiles. In this case, the candles are aligned with both ends of the platform. Therefore, after hitting them, an object that appears may fall directly into the abyss below them.
I think that at some stage the designers realized this problem. But by that time, the displacement of the entire series of candles on all the finished levels, in order to align them with the centers of the tiles, could have caused other problems. Instead, they decided to randomly shift the candles one pixel to the right or left of the place of their creation. Therefore, after hitting the candles on the right side of the screenshot, there is a 50% chance that the holy water contained in them will fall on the platform. In the rest of the cases, it falls into the water.
CastlevaniaBot usually completely avoids these candles, because it rather successfully saves holy water. But if he needs it, he rises very close to these candles in order to guarantee the holy water that has fallen from them.
Next CastlevaniaBot meets a bunch of jumpers. Axes often appear in this area after killing jumpers. CastlevaniaBot avoids them, because holy water turns out to be especially useful in fighting the boss.
When going to the last stage, the level of CastlevaniaBot completely ignores the bone dragon.
But he gets rid of the next two with quick blows of the whip.
The monster of Frankenstein and Igor are destroyed by a constant stream of blows with a whip and holy water. As is the case with other bosses, CastlevaniaBot can handle other secondary weapons, or even without them. However, the chances of survival without holy water are reduced.
At level 5, CastlevaniaBot again deals with white skeletons. But this time, he uses variations of strategies that are rarely seen at level 3. Depending on where they appear, CastlevaniaBot throws holy water and then moves back to attract skeletons to the flame. Next to the stairs, he passes under the skeletons to direct them to where they should be.
At level 5, resurgent red skeletons appear for the first time. CastlevaniaBot keeps track of the time of the last blow to them, to know when you can safely walk on the red bones.
The first room of stage 14 is fully processed by one huge strategy. CastlevaniaBot kills the jumper first. Then he waits for the lower knight to throw an ax, hits the ax with a whip and slowly rises along the lower stairs. This pushes the lower knight off the screen, which causes it to disappear. Then he waits until the upper region is free from the axes, hits the candles and collects the objects that appear. Then he approaches the base of the ladder leading to the upper knight. When the top knight throws the ax high, CastlevaniaBot runs after him. This pushes the upper knight to the left and almost completely off the screen, but does not destroy him. CastlevaniaBot bends under the returning ax, and possibly under the second abandoned ax, and then finally approaches the stairs to the next sub-step. Hooray!
After passing a few stairs, CastlevaniaBot again meets a knight with an ax. He uses holy water to stun him, and then finishes him off with a whip. If there is no holy water, he continues to beat the whip, chasing the knight until he dies.
Moving along level 5 stairs, CastlevaniaBot often has to wait for the red skeleton to move away from either the top or bottom of the stairs. Towards the end of the level, the bone tower makes this task even more difficult. Depending on how the skeletons decide to move, CastlevaniaBot goes up and down the stairs until it can pass.
To process groups of red skeletons, additional logic is required so that the bot does not fall into an infinite loop. If CastlevaniaBot hits them with a whip separately, at such intervals that the first hit has time to be reborn, he will fall into a cycle, where he will continue to destroy the endlessly resurgent skeletons. To avoid this, CastlevaniaBot will not hit the whip of the red skeleton standing next to the pile of red bones. This rule allows the red bones to be reborn next to the still-living red skeleton, giving the opportunity to hit the two of them simultaneously. Without the interval between their destruction, the cycle will not be created.
To avoid the jellyfish heads in the long corridor leading to Death, the bot never stops, stunning the knights that usually appear in the path. He takes advantage of the fact that a player can pass through enemies stunned by holy water without taking damage.
If there is no holy water, then right in front of the corridor CastlevaniaBot can take a boomerang. With the best of luck, he uses it to destroy the knights, as well as to obtain weapon upgrades.
CastlevaniaBot stuns Death with holy water before she starts throwing spit, quickly killing her. He can also defeat Death with a triple boomerang, but this usually requires several attempts.
The principal strategy of CastlevaniaBot for passing the bridge at the beginning of level 6 is to keep moving. He strikes a whip of huge bats from above to stun them, and then jumps over the huge bats that appear from below. In addition, from time to time he needs to evade fireballs thrown by bats, or beat them with a whip.
Passage over the bridge is not guaranteed. It all depends on how friendly the huge bats will be.
In the next sub-step, CastlevaniaBot uses the chronograph received on the bridge two or more times in order to pass through eagles and jumpers. Without a chronograph, he tries to make his way with a whip.
When CastlevaniaBot reaches Dracula's tower, he can climb and descend the stairs several times to create candles again, which allows him to collect at least 20 hearts.
The rightmost candles in the chambers of Dracula give holy water, which is necessary to fight the second form of Dracula.
To defeat the first form of Dracula requires 16 blows to the head. CastlevaniaBot comes up to Dracula several times, waits for him to fire balls of fire, and then jumps over the balls and hits Dracula on the head with a whip.
The second form of Dracula, called Cookie Monster, is stunned by the bot with holy water and several times strikes the head with a whip. From time to time, Cookie Monster jumps to the player, while CastlevaniaBot dodges. Also, the Cookie Monster throws fireballs, which can usually be destroyed with holy water and a whip. Sometimes you can get a weapon upgrade. And double holy water catches Cookie Monster in a constant stunning cycle leading to a quick victory.
CastlevaniaBot does not know how to go through the Difficult Mode, which begins after the final credits. However, after restarting the game in the courtyard of the castle, he drops the byte of the game cycle to zero, switching it to Normal Mode. This allows CastlevaniaBot to play forever.
src- source tree.
CastlevaniaBot.jar- compiled binary file.
lgpl-2.1.txt- license free software.
- Nintaco - NES emulator.
Castlevania (U) (PRG1) [!].nes- ROM games.
- Launch Nintaco and open
Castlevania (U) (PRG1) [!].nes.
- Open the Run Program window by selecting Tools | Run Program ...
- Enter the file path in the JAR field or select it by clicking on the Find JAR ... button.
- Click Load JAR to load it.
- Click Run.
|Copyright © 2018 meatfighter.com
This project is free software. You can redistribute it and / or modify it under the terms of the LGPLv2.1 license.