In Weeks 3 – 6 at Flatiron School, the focus has been on learning both the Sinatra and Rails web frameworks. Understanding the paradigms has been crucial in spinning up web applications “the right way”.
However, it’s important to remember the foundation on which these frameworks are built – the Ruby language. With only 6 weeks of Ruby knowledge under my belt, I want to continue understanding the principles of abstraction, modeling, and scope.
Enter the realm of Artificial Intelligence (AI).
I’ve had the honor and pleasure of working with AI concepts in the Scheme programming language. I wanted to explore this realm in Ruby, and it turns out there’s a great venue. Before I get into that, let me define two common terms used in AI:
Agent: an autonomous entity which observes through sensors and acts upon an environment using actuators and directs its activity towards achieving goals.
Heuristic: a function that ranks alternatives in various search algorithms at each branching step based on the available information in order to make a decision about which branch to follow during a search.
Here’s a cool image that will make these definitions clearer:
Now with that background, onto Ruby Warrior.
Here’s a quick overview:
Every turn, the
play_turn method is called in
player.rb file – this and any other files can be used, as long as
play_turn calls one and only one action.
For this post, my goal is to share how I’ve applied my Ruby skills to the first 4 levels. Here’s a quick legend regarding level layouts:
Legend: Tower Level Symbols
Here is the representation of Level 01:
This level is pretty straightforward. Having only one action available [
warrior.walk!], the logic here is simple:
Level 01 was completed and I achieved maximum points.
Here is the representation of Level 02:
This level introduced the first monster. I realized I needed to add logic to check to see if a monster was in front of me based on my available actions. Still pretty straightforward.
Level 02 was completed now completed.
Playerclass is being initialized one time, with
play_turnbeing called in a loop. Take advantage of the
Here is the representation of Level 03:
Four (4) monsters. Oh snap son.
As I began writing my code, I realized I didn’t want to do annoying amounts of nested logic. Projecting into the future, I felt the need to begin splitting parts of the agent into logical methods in an organized structure. I also needed to figure out when was the right time to rest, to keep moving forward, and when to attack.
Overall, I was really happy with my code – beat this level with no issues. Even though it grew in size, the
play_turn method is readable and tells me exactly what the Warrior is to do at any given point in time.
warrioras a parameter.
Given all the negatives, there was going to be some heavy-duty refactoring in Level 04. All in all though, I was fairly certain that the logic in the code was ‘just going to work’.
I couldn’t have been more wrong.
Here is the representation of Level 04:
Enter the dreaded Archer – umm… f*ck.
This unit can attack from multiple spaces away. With my current logic, I’d rest when the space in front of me was empty and I wasn’t in combat. BUT I WAS IN COMBAT, since my health was decreasing by 1HP even though I was resting (rest = +2HP, attack = -3HP).
This now forced new state logic into my methods, along with some well-needed refactoring.
Awesome! This now gets around the ‘distance attack’ issue. If I’m being attacked from afar and the space in front of me is empty, do not rest and continue walking until you find and slay the offending monster.
class Playeris getting huge.
Interestingly enough, your Agent can always be “more intelligent”.
I have a long way to go to reach the top of the Beginner tower, but this has been a tremendous learning experience. I’ve been able to apply Ruby principles to the challenging yet fun problem space of Artificial Intelligence.
A few things I’m thinking about going forward:
I’m convinced that my upfront work will help prevent the following from happening:
Slowly but surely, I will become the Ruby Warrior I’m destined to be.
A shoutout to my boy Dan Friedman for working on this with me.
There’s still much learning to do and more levels to conquer. Onward and upward!