Ruby Warrior is a super fun game where you write Ruby code to move your knight character and win levels. After finishing Ruby Monk Primer and Codecademy’s Ruby track, I played the first 5 levels of Ruby Warrior. I’m going to walk through my thought process and code for each level.
Level 1 – Walk
Level 1 is pretty simple. There is already a method defined for us called play_turn which takes a warrior as a parameter. We want the knight to walk to the stairs. Every turn, we call the walk method on the warrior. He will walk forward one space at a time until he reaches the stairs.
Level 2 – Sludge!
Level 2 introduces little green sludge monsters. Our knight can only perform one action every turn, so he can either walk or fight. We want to first check whether there is a monster in the next space. If there is, we want to fight. If not, we simply take a step forward.
Poor little sludge fades away after 2 attacks.
Level 3 – MORE Sludge
Level 3 ups the sludge levels. If we run our code from level 2, our poor warrior runs out of health quickly and we fail the level. Our warrior needs rest to get back his health before fighting more sludge. The warrior can’t rest if there’s sludge in front because he will get attacked (remember we can only perform one action per turn), so the only time he can rest is if there’s no sludge in the space ahead.
There are two questions to ask:
1. Is there an empty space ahead? -> no: fight, yes: move to question 2.
2. Is my health ok? -> no: rest, yes: walk.
I set a constant of 15 for minimum health levels, but it can actually be 7. Each sludge attack is -3 damage. A sludge is killed after 2 warrior attacks, so the maximum damage you get from a sludge is -6. If the space in front is empty, then check if the warrior’s health is at least at minimum health. If so, go on ahead. If the health is less than minimum, the warrior will rest for that turn.
Level 4 – Add Archers!
Level 4 introduces these archers with nice and lush hair. Once the sludge is gone and no longer obstructing their view, they start shooting arrows at you! If your warrior is taking damage from the archer, you must charge ahead and not be a standing target. We want to add on to the logic from above.
The scenario: there is an empty space in front -> warrior health is not ok. If we run the same code from Level 4, the warrior just rests while the archer attacks. In this level we want to add some code so if the warrior is under attack, we want to walk. If the warrior is not under attack, we can rest. How do we know if we are under attack? We can compare the warrior’s current health level with the previous level to see if there was any damage.
I set an instance variable of health. When it’s the player’s turn, we first set the health variable to the warrior’s health. (Note that line 6 only runs during the very first turn, since from then on @health is not nil.) We set a local variable of under_attack that is a boolean. It returns true if the warrior’s health is less than the stored health variable value.
We use a boolean operator to check two things: whether the warrior’s health is good and if the warrior is under attack. If either one of these is true, the warrior should walk. This of course needs an || (or) operator. If neither of these are true, then the warrior gets to rest. At the end of the turn we store the warrior’s health in the @health variable for reference during the next turn.
Level 5 – Rescue me!
Level 5 introduces some captives locked in small cages. Their eyes look so sad. This was a fairly simple level. If we look at our code, we attack whenever the space in front is not empty. But we don’t want to attack captives! When the space ahead is not empty, we will check if there is a captive. If there is a captive, the warrior will rescue the captive. If not, then attack the enemy! (Lines 16 to 20)
The great thing about Ruby Warrior is that after you successfully clear a level, you can still play around in the editor and rerun your code. This gives you a way to test different things out. I added a private method to determine if the warrior should_walk?, it checks the health and under attack status of the warrior. Both of these values are booleans, and are evaluated with an OR operator.
If should_walk? returns true, warrior walks. If not, warrior rests. The should_walk method accepts a warrior parameter. On line 6 I also changed “if @health.nil?” to “unless @health”. This means that if @health has a value, then the line will not run. “Unless” is equivalent to saying “if not x”.
Level 1-5 of Ruby Warrior was really fun. I found Level 4 to be the most challenging as I got stuck on getting an error because health was initially nil. Drawing out “yes/no” flow charts on paper really helped me work out the logic! I can’t wait to see what Level 6 will bring.