Dwemthy’s Array in Java - Refactored
By Clinton Begin  June 15, 2008

Dwemthy's Array is text based adventure game with a build-in coding challenge that is particularly suited to implementation with a dynamic language such as Ruby. What caught my attention was Adrian Kuhn's implementation in Java. Despite my love-hate (or like-hate) relationship with Java, I'm always up for a coding challenge, especially when it's Java vs. Ruby.

For the record, I'm curently a full-time Ruby on Rails developer and loving every minute of it. But I've been a Java developer for 10 years as well, and so I find it compelling to compare the two languages.

Now with MOAR Meta!

Java is not known for its meta-programming capabilities, nor is it a dynamic language. In fact, Java is one of the most strictly typed and type safe languages there is (despite its poor implementation of generics). Java is also known to be a bit more verbose and "chunky" than most other languages. That said, I think that much of this has to do with habits that are known as "best practices" in the Java community. While there are some things that we can't avoid (like checked exceptions), there are a lot we can do away with (JavaBeans and a bunch of unnecessary design patterns). With some of the dogma removed, Java can be quite terse and feature rich. Adrian demonstrated this in his implementation.

While I think Adrian did a good job in general, I think there's a lot more opportunity to be "more meta"...did I just say that? Oh well, let me explain.

The magic that Ruby has (that Java doesn't) is a little feature called "method_missing". This is quite simply an impossible feature for Java to ever have, as it is a statically typed and [fully] compiled language. There will never be a way to call someObject.someMethodThatDoesNotExist() in Java, as there's simply no interface (be it a class or an interface) to compile to. Ruby on the other hand is dynamic. You can call whatever you want on any object (i.e. send any message you want to any object) and Ruby will accept it. By default its catch-all implementation of method_missing behaves much like Java -- it throws an exception. However, when overridden, this method becomes powerful and allows for some interesting behavior.

In the case of Dwemthy's Array, it basically allows an Array to behave as though it were one of the items it contains. This is not easily accomplished with Java.... at least not if you approach it as if Java were Ruby.

In his implementation, Adrian sort of side stepped the issue. He found a common hook point that was conveniently called exactly when it needed to be to yield the same behavior as the ruby implementation. This happened to be the alive() method.  Note that the Ruby implementation didn't have an alive() method, it just checked "life <= 0" directly.

#Ruby 
def method_missing( meth, *args )
answer = first.send( meth, *args )
if first.life <= 0
shift
if empty?
puts "[Whoa. You decimated Dwemthy's Array!]"
else
puts "[Get ready. #{ first.class } has emerged.]"
end
end
answer || 0
end

//Java -- not meta programming, just programming.
public boolean alive() {
    if (life > 0) return true;
    if (array.length == 0) {
        puts( "[Whoa.  You decimated Dwemthy's Array!]" );
        return false;
    } else {
        life = array[0].life;
        strength = array[0].strength;
        charisma = array[0].charisma;
        weapon = array[0].weapon;
        name = array[0].name;
        array = Arrays.copyOfRange(array, 1, array.length);
        puts( "[Get ready. %s has emerged.]", this.name );
        return true;
    }
}


While this was convenient for this particular application, not every application would roll over for a belly scratch so easily. So what I'm going to demonstrate here, is how to implement this in Java, by making excessive use of strong, static typing.  I also wasn't terribly excited about Adrian's use of Strings and Maps where Classes could be used, so I've made changes to make it more type safe and object oriented.

The result will be closer to the Ruby implementation and a more generally applicable design overall.

Creature Features

Java isn't dynamic. So what? Ruby isn't static! :-P  So how can we leverage the features of Java to allow it to more closely resemble the design of the Ruby implementation? How can it yield benefits similar to that of the Ruby program design? How do we not skirt around the fact that Java doesn't have the method_missing feature?

Specifically, we're going to make use of:

    * Annotations,
    * Dynamic Proxies,
    * Interfaces, and
    * Inner classes

Let's start from the highest level, the Creature class -- the central class of Dwemthy's Array. I think the goal of this exercise should not be to cut lines of code or show off obscure features of the language (although it may do that). I think the goal should be to build an API (or perhaps a DSL, to use the term loosely) for creating a Creatures. You see, in a nutshell, Dwemthy's Array is basically Pokemon for Programmers. You instantiate two or more Creatures and have them duke it out. You generally control one creature, while the other creature responds programmatically. Afer a round or two of character stats plus some random numbers banging around, a victor emerges.

The star of the show is the Rabbit. He's your creature. Love him. Pet him. Look at his code in Ruby and Java...

#Ruby
class Rabbit < Creature
traits :bombs

life 10
strength 2
charisma 44
weapon 4
bombs 3

# little boomerang
def ^( enemy )
end

# the hero's sword is unlimited!!
def /( enemy )
end

# lettuce will build your strength and extra ruffage
# will fly in the face of your opponent!!
def %( enemy )
end

# bombs, but you only have three!!
def *( enemy )
end
end

//Java
public class Rabbit
  extends Creature.Base {

  {
    bombs = 3;
    life = 10;
    strength = 2;
    charisma = 44;
    weapon = 4;
  }

  private int bombs;
  @Trait public int bombs() {
    return bombs;
  }

  // little boomerang
  @Command('^') public void boomerang(Creature enemy) {
  }

  // the hero's sword is unlimited!!
  @Command('/') public void sword(Creature enemy) {
  }

  // lettuce will build your strength and extra ruffage
  // will fly in the face of your opponent!!
  @Command('%') public void lettuce(Creature enemy) {
  }

  // bombs, but you only have three!!
  @Command('*') public void bomb(Creature enemy) {
  }
}

The classes here look almost identical.  I deleted the method bodies, as they were identical.  Skeptics can download each version and check, but it's not what we're interested in here. 

I think both do a good job of describing the Rabbit in a fairly concise and descriptive way.  While the Java code is noisier, I think it documents itself better.  Indeed, the comments are mostly redundant in the Java code, while the Ruby code would leave the reader guessing if the comments were deleted.   Notice the approach to implementing "traits" in each.  Also notice how the command keys are implemented.  The commands are: ^/%* These are the characters you enter on the command line to instruct your Rabbit on how you would like him to maim the opponent. 

Speaking of Opponents

Above you saw advanced definitions of creatures, including user key commands and custom traits.  Simple creatures, like our opponents ("oh snap!"), should be simple to define.  Here you can see a few:

#Ruby
class IndustrialRaverMonkey < Creature
life 46
strength 35
charisma 91
weapon 2
end

class DwarvenAngel < Creature
life 540
strength 6
charisma 144
weapon 50
end

//Java
private static class IndustrialRaverMonkey
  extends Creature.Base {
  {
    life = 46;
    strength = 35;
    charisma = 91;
    weapon = 2;
  }
}

private static class DwarvenAngel
 
extends Creature.Base {
  {
    life = 540;
    strength = 6;
    charisma = 144;
    weapon = 50;
  }
}


The noise is a little more apparent here, but it's not outrageous.  It's Java.

Reversing the Advantage

So far, other than some squiggly brackets, everything looks very similar and this is becoming a really long and boring trudge through tedium.  So where do we see the difference?  When do we show that Ruby sucks and Java rules?  Well, there is no sucking here.  There's only different approaches.  The differences lie in the Creature base classes themselves, and in the Array.  The point to take away here is that these implementations are very different, but yield very similar resulting API as we've seen in the consumer examples above.

So here we go.  The following is the Creature base class/interface.


#Ruby
class Creature
def self.metaclass; class << self; self; end; end

def self.traits( *arr )
return @traits if arr.empty?
attr_accessor *arr
arr.each do |a|
metaclass.instance_eval do
define_method( a ) do |val|
@traits ||= {}
@traits[a] = val
end
end
end

class_eval do
define_method( :initialize ) do
self.class.traits.each do |k,v|
instance_variable_set("@#{k}", v)
end
end
end

end

traits :life, :strength, :charisma, :weapon

def hit( damage )
#...game logic
end

# This method takes one turn in a fight.
def fight( enemy, weapon )
#...game logic
end

end

//Java
public interface Creature {
  @Trait int life();
  @Trait int strength();
  @Trait int charisma();
  @Trait int weapon();

  void hit(int damage);
  void fight(Creature enemy, int weapon);
  void command(Character op, Object... args);

  public static class Base implements Creature {
    protected int life, strength, charisma, weapon;
    protected Map<Character, Method> COMMANDS = new HashMap<Character, Method>();

    public Base() {
      Class type = this.getClass();
      for (Method m : type.getMethods()) {
        Command command = m.getAnnotation(Command.class);
        if (command != null) {
          COMMANDS.put(command.value(), m);
        }
      }
    }

    @Trait public int life() {
      return life;
    }
    @Trait public int strength() {
      return strength;
    }
    @Trait public int charisma() {
      return charisma;
    }
    @Trait public int weapon() {
      return weapon;
    }

    public void hit(int damage) {
      //...
    }
    public void fight(Creature enemy, int weapon) {
       //...
    }
    public void command(Character op, Object... args) {
      try {

        COMMANDS.get(op).invoke(this, args);
      } catch (Exception e) { throw new RuntimeException(e); }
    }

  }

  @Target(ElementType.METHOD)
  @Retention(RetentionPolicy.RUNTIME)
  public @interface Trait {
  }

  @Target(ElementType.METHOD)
  @Retention(RetentionPolicy.RUNTIME)
  public @interface Command {
    char value();
  }

}


The Java creature class is a lot longer, but most of the length difference can be credited to Ruby's shortcuts for defining properties (or attributes as Ruby calls them).  The Java code actually ends up defining:  two annotations, an interface and a base class.  Thus the excessive typing I promised you earlier. Despite its length, I think it's actually quite readable and you get a sense of where we're going with some of the annotations and meta-programming here.  Whereas the Ruby class spends its time dynamically defining classes, the Java class spends finding all of the Command annotations and sets them up in a Map so that we can look up their corresponding methods.  Again, while the code is longer, the advantage over the Ruby program is that the method name and the command are separated, which is both more readable and a more universally applicable design.  In a larger application, nobody would suggest writing a Ruby app this way.  But in the case of the Java app, we're not really breaking any horrible rules (except maybe for stuffing all of these entities into a single class definition for the sake of this example -- the design stands though).  The biggest disappointment to me was that @Trait needs to be repeated because of the way that some of the reflection works here.  Lastly, you'll notice that we had to implement our own command() method to act as equivalent to Ruby's built-in send() method.

Disclaimer:  I did leave out a couple of Java methods like Adrian's awesome toString() method and my autoCommand() runner which were added strictly to make the Java game fun to play.  They are not pertinent to the discussion, nor part of the original design.  And I also left out the game logic in the fight() and hit() methods, as they are quite identical, and again not what we're interested in here.

Enter the Dragon... into the array.

With our creatures well described, we now come to the actuall challenge part of the application.  This is where the original Ruby authors challenged the rest of the world to implement Dwemthy's Array, knowing full well that method_missing was an ace up their sleeve.  But we pulled a fast one, and turned strong typing into an advantage.  While we can't intercept "missing methods", we can intercept ALL methods.  And by tagging our Traits we're able to intercept specifically the access of the traits of our Creature.

#Ruby
class DwemthysArray < Array
alias _inspect inspect
def inspect; "#<#{ self.class }#{ _inspect }>"; end






# This space intentionally left blank to line up the methods







def method_missing( meth, *args )

answer = first.send( meth, *args )
if first.life <= 0
shift
if empty?
puts "[Whoa. You decimated Dwemthy's Array!]"
else
puts "[Get ready. #{ first.class } has emerged.]"
end
end
answer || 0
end
end


//Java
public class DwemthysArray extends ArrayList<Creature>
    implements InvocationHandler {

  private Creature current;

  private DwemthysArray(Creature... creatures) {
    addAll(Arrays.asList(creatures));
    nextCreature();
  }

  public static Creature asCreature(Creature... creatures) {
    Creature creature = (Creature) Proxy.newProxyInstance(
        Creature.class.getClassLoader(), new Class[]{Creature.class}, new DwemthysArray(creatures));
    return creature;
  }

  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      return method.invoke(current, args);
    } finally {
      Creature.Trait trait = method.getAnnotation(Creature.Trait.class);
      if (trait != null && current.life() <= 0) {
        nextCreature();
      }
    }
  }

  private void nextCreature() {
    if (size() == 0) {
      puts("[Whoa.  You decimated Dwemthy's Array!]");
    } else {
      current = remove(0);
      Kernel.puts("[Get ready. %s has emerged.]", current.getClass().getSimpleName());
    }
  }
}




Once again we see some Java noise, but it's mostly construction logic, which is the price we pay for using a Dynamic Proxy in Java.  But that's a fixed cost.  Once implemented, if you compare the actual logic between the Ruby code and the Java code, while quite different (almost opposite), they are about the same length and achieve a very similar result.

The way the Java version works is that it proxies the Creature interface, then delegates all method calls to the first object in its collection.  It also catches any Trait methods and implements the special event logic that manages the death of creatures and possibly the ultimate demise of Dwemthy's Array!

And finally, we can see how the game is played...


#Ruby
r = Rabbit.new

dwarr = DwemthysArray[IndustrialRaverMonkey.new,
DwarvenAngel.new,
AssistantViceTentacleAndOmbudsman.new,
TeethDeer.new,
IntrepidDecomposedCyclist.new,
Dragon.new]

# Ruby's awesome, so it
# can act like an operator!

r ^ dwarr

//Java
Creature rabbit = new Rabbit();

Creature dwemthy = DwemthysArray.newInstance(
    new IndustrialRaverMonkey(),
    new DwarvenAngel(),
    new AssistantViceTentacleAndOmbudsman(),
    new TeethDeer(),
    new IntrepidDecomposedCyclist(),
    new Dragon()
);

// Java uses command line stdio
while (rabbit.life() > 0 && dwemthy.life() > 0) {
  puts(rabbit);
  rabbit.command(getChar(), dwemthy);
}

Just so you're not surprised, you won't win.  Your Rabbit will die over and over while you enjoy the twisted darkness of it all.  :-)

So now what?

I'm not sure really.  This was quite possibly the biggest waste of time in my coding career, but it was ridiculously fun!  I'm an RPG fan and this is probably the closest I'll ever come to actually writing a game... so for that I'm grateful.  I hope in your case you take away a little creative insight into how Java can look when it's not weighed down by a GoF book and a JEE Spec. 

So now go get the code and play the game!  I've included a few sample battle classes, the two main battles are BattleOfDwemthysArray and BattleOfGrottoOfSausageSmells.  But to demonstrate the flexibility of the design, I've included BattleOfTwoRabbits and within each I've included a couple of comments to show you how to alter the behavior, including letting 1000 Rabbits take on Dwemthy's Array and how you can play as Scuba Argentine.


References and Thanks:



Cheers,

Clinton Begin 
June 15, 2008