Monday, September 14, 2009

Facebook Puzzles

Programming is like an art. If you don't practice you cannot evolve. I've been doing web applications for a few years now, with a little bit of actual software development in between. So, it was nice to have a challenge and try out a Facebook Puzzle. You can find them here. They're available in all different flavors, with a hierarchy of difficulty levels. I chose to try out dinoisland. Why not, right? Let's get into the good stuff, no need for the hors d'oeuvres.

To get setup, I had to install Thrift. That way, the actual code library could be compiled in, pretty much, whichever language I desire. Initially, I started with PHP, because that's what I've been using a lot lately, and I feel as if I've close to mastered it ;) I found difficulty with it because it seemed as though it lacked power, especially for a client that I knew would need to be threaded. After a day with PHP, I gave up, and switched over to Java. What a relief! Aside from the AI part of this puzzle, it felt like this project was meant to be programmed in Java. If I knew LISP, then I would have used that, but...meh, I'm busy right now with the puppy and work.

My approach for the Java application was to divide the solution up into different portions;
  • Client - connects to the server and creates an instance of our dinosaur, then threads it off to do it's own thing.
  • NPC - This would be our dinosaur, a non-player character. This guy handles it's own state, communicates with the server directly, and decides it's next moves. There is also a history object which contains all of it's recent actions, and path history.
  • ActionFactory - We are allowed 4 different actions in this puzzle; move, grow, look, and egg. Their is a handler for each of those actions, and the AF abstracts the process of handling those, and determining a result.
  • Action Handlers - The handler analyzes the result from the server, and returns the current state. It also determines a suggested next action, based on the results it receives.
  • ResultAction - a simple class created in order to store valuable info about the dino's actions.
  • Directions - Methods were added to help with navigation. For example, if my dino needed to turnLeft, turnRight, turnAround, or even go in a random direction.
  • History - keep track of our actions, and our movement history.
This is how the basic structure was. I had a grandiose idea in my head of creating a dino that would look, cache the results, and based off of those, decide which areas were the best to venture towards, or moveTo. Also, having the path history static would help new dinosaurs with their movement decisions.

As it turns out though!! None of that was necessary. While still testing, brute force, and strength in numbers seemed to be adequate enough. I had my dino's grow to level 2 instantly. This way, they could eat more plants, gain more calories, and be less susceptible to getting beat up. The only logical pieces implemented were;
  • if your movement returns false, turn to the right (if we hit a rock or big plant)
  • if we have n number of calories and are a size s, we should grow
  • if we have n number of calories, let's lay an egg
I was able to achieve a score of 124,750 with that simple bot. Honestly, just lay as many eggs as possible with enough calories to keep them alive. Of course the downside of this solution is that it is not consistent, and relies on probability. Many things must go right for it to succeed....and succeed it did!

No comments:

Post a Comment