Last week the satanic Dwemthy’s Array was released into the quiet, pious town of Java programming. { A, B } Both Java permutations used reflection to emulate some dynamic properties of the original, a recipe for sad exception handling if there ever was one. But it was helpful to be reminded of a few techniques to fight the clutter beast in Java code, even if defeating it is impossible.

The crux of the Ruby original is probably that method_missing can make an array act as one of its elements, which is the sort of thing Ruby is good at. An interesting topic to explore! But the game itself is cool, and after seeing the comment

# lettuce will build your strength and extra ruffage # will fly in the face of your opponent!!

it became pretty impossible not to translate it into the house favorite language, Scala.

There is no sense in imitating the dynamic typing pirouettes of the original using Scala, but this Dwemthy permutation will try to make up for the lost dynamic awesome with other kinds of awesome that Scala is good at, like functional programming and mostly painless typing.

And, Scala like Ruby allows you to define methods that look like operators, declare multiple base types in one file, and it has an interpreter. That way the player can load a single source and play within the interpreter, which is the real ultimate power of Dwemthy. The Java implementations, with their class source file ensembles and keyboard input loops, have shown up at the beach wearing business casual yet again.

// clock-seeded pseudorandom sequences are for sharing! object Random extends Random trait Creature { val life: Int val strength: Int val charisma: Int val name: String // abstract type to escape from square braces[][][][] type Copy <: Creature def copy(life: Int): Copy def rand(until: Int) = Random.nextInt(until) def hit(damage: Int) = copy( (rand(charisma) match { case p_up if p_up % 9 == 7 => printf("[%s magick powers up %d!]

", name, p_up) p_up / 4 case _ => 0 }) + life - damage match { case death if death <= 0 => printf("[%s has died.]

", name) death case l => l } ) }

A Creature is something that can be hit with damage and that has certain attributes. Note that these are immutable. The hit method returns a new copy of the Creature with a new life value, thus it requires an abstract method to produce this copy and an abstract type to say what that copy will be. Otherwise, the value returned by hit would simply be a Creature and we could no longer use the wonderful weapons that only the rabbit possesses. You can do the same thing with type parameters, but the abstract type is self-documenting and doesn’t clutter up the class/trait introduction with distracting symbols.

Pattern matching! If you want to know why it’s used here instead of a plain old if s, the answer is that match gives you a nicely scoped reference to its input object. That makes it easier to write functions that evaluate to a single expression instead of a series of expressions and a bunch of values for things that you need to use just twice. Although, it seems like there may be an even more awesome way to do this kind of thing; if you know one, please don’t keep it to yourself!

trait Enemy extends Creature { // enemies beget enemies type Copy = Enemy // and hold one (1) weapon val weapon: Int }

Yep. In the Ruby version, rabbit has a weapon value that isn’t used in normal gameplay, so here in pedantic typing land we will just put that right in Enemy where it belongs. Also now the Copy type is set once and for all enemies with this trait.

case class Rabbit(rem_life: Int, bombs: Int) extends Creature { // and rabbits make... MORE RABBITS type Copy = Rabbit val life = rem_life val strength = 2 val charisma = 44 val name = "Rabbit" def fight(enemy: Enemy, weapon: Int) = if (life <= 0) { printf("[%s is too dead to fight!]

", name) (this, enemy) } else { // Attack the opponnent val your_hit = rand(weapon + strength) printf("[You hit with %d points of damage!]

", your_hit) val damaged_enemy = enemy hit your_hit //Retaliation println(damaged_enemy) ( if (damaged_enemy.life > 0) { val enemy_hit = rand(damaged_enemy.weapon + damaged_enemy.strength) printf("[Your enemy hit with %d points of damage!]

", enemy_hit) this hit enemy_hit } else this , damaged_enemy) } def copy(life: Int) = new Rabbit(life, bombs) // little boomerang def ^ (enemy: Enemy) = fight(enemy, 13) // the hero's sword is unlimited!! def / (enemy: Enemy) = fight(enemy, rand(4 + (enemy.life % 10) * (enemy.life % 10))) // lettuce will build your strength and extra ruffage // will fly in the face of your opponent!! def % (enemy: Enemy) = { val lettuce = rand(charisma) printf("[Healthy lettuce gives you %d life points!!]

", lettuce) Rabbit(life + lettuce, bombs).fight(enemy, 0) } // bombs, but you only have three!! def * (enemy: Enemy) = if (bombs <= 0) { println("[UHN!! You're out of bombs!!]") (this, enemy) } else Rabbit(life, bombs-1).fight(enemy, 86) } object Rabbit extends Rabbit( 10, // life 3) // bombs

(Ruffage is condensed roughage.) This is pretty self explanatory maybe. All case classes get a halfway decent automatic toString that prints their constructor values. The deal with fight and all the weapon-specifc methods is, they return a tuple made up of your guy and the enemy. We need this because both usually change in one turn, thanks to retaliation.

// the P is for ''''PRIME'''' case class EnemyP(life:Int, strength:Int, charisma: Int, weapon: Int, name: String) extends Enemy { // https://lampsvn.epfl.ch/trac/scala/ticket/321 grrr!!! def copy(life: Int): Enemy = EnemyP(life, strength, charisma, weapon, name) } // Critters are easy to define trait Critter extends Enemy { def copy(life: Int): Enemy = EnemyP(life, strength, charisma, weapon, name) }

Done! Now we can conjure ScubaArgentine.

object ScubaArgentine extends Critter { val life = 46 val strength = 35 val charisma = 91 val weapon = 2 val name = "Scuba Argentine" }

And have an interpretive fight.

scala> var play = Rabbit / ScubaArgentine [You hit with 5 points of damage!] EnemyP(41,35,91,2,Scuba Argentine) [Your enemy hit with 27 points of damage!] [Rabbit has died.] play: (Rabbit, Enemy) = (Rabbit(-17,3),EnemyP(41,35,91,2,Scuba Argentine))

Aw. You can see that toString is not ideal. We’ll get back to that, and the names. For now, replay the match until rabbit survives a round. play is the only variable in this game, so that it can be updated and reused with each turn.

scala> play = Rabbit / ScubaArgentine [You hit with 2 points of damage!] EnemyP(44,35,91,2,Scuba Argentine) [Your enemy hit with 0 points of damage!] play: (Rabbit, Enemy) = (Rabbit(10,3),EnemyP(44,35,91,2,Scuba Argentine))

Now we’re talking. And to play the next turn:

scala> play = play._1 % play._2

Or

scala> play = play match { case (r, e) => r % e }

And so on! (The interpreter’s input history is helpful.) Now for the evil DwemthysList.

// is-NOT-a-list-but-*has*-one and that will have to do class DwemthysList(head: Enemy, tail: List[Enemy]) extends EnemyP( head.life, head.strength, head.charisma, head.weapon, head.name) { override def copy(life: Int) = if (life <= 0) { if (tail.isEmpty) { println("[Whoa. You decimated Dwemthy's Array!]") head.copy(life) } else { printf("[Get ready. %s has emerged.]

", tail.head.name) new DwemthysList(tail.head, tail.tail) } } else new DwemthysList(head.copy(life), tail) } // but can-construct-as-a-list! implicit def list2dwemthy(list: List[Enemy]) = new DwemthysList(list.head, list.tail)

The awesome dynamicy implicit was J. I.’s idea.

That list2dwemthy will turn a regular list into a DwemthysList whenever one is required. And finally, code is data or whatever.

object IndustrialRaverMonkey extends Critter { val life = 46 val strength = 35 val charisma = 91 val weapon = 2 val name = "IndustrialRaverMonkey" } object DwarvenAngel extends Critter { val life = 540 val strength = 6 val charisma = 144 val weapon = 50 val name = "DwarvenAngel" } object AssistantViceTentacleAndOmbudsman extends Critter { val life = 320 val strength = 6 val charisma = 144 val weapon = 50 val name = "AssistantViceTentacleAndOmbudsman" } object TeethDeer extends Critter { val life = 655 val strength = 192 val charisma = 19 val weapon = 109 val name = "TeethDeer" } object IntrepidDecomposedCyclist extends Critter { val life = 901 val strength = 560 val charisma = 422 val weapon = 105 val name = "IntrepidDecomposedCyclist" } object Dragon extends Critter { val life = 1340 // tough scales val strength = 451 // bristling veins val charisma = 1020 // toothy smile val weapon = 939 // fire breath val name = "Dragon" } val dwlist = List(IndustrialRaverMonkey, DwarvenAngel, AssistantViceTentacleAndOmbudsman, TeethDeer, IntrepidDecomposedCyclist, Dragon)

Now you can attack the list.

scala> var play = Rabbit / dwlist

Maybe you will win—anything is possible! Hint, try not to forget the game is played in a programming environment. Dwemthy didn’t say anything about writing recursive functions, so, why not. Simple algorithms have been known to get to the dragon, but probably can’t beat him without overflowing int. Yeah it’s that serious.

And about that toString —lame. Ruby has a much nicer display of the attributes than the case class is giving, at least the way it’s used here. Lamer still is the fact that we’re naming the creatures with Strings instead of using type information, but, that’s harder than it looks. Can you even get that information at construction time? In a trait? Maybe a lazy val would work, but then the case class won’t output it? There has got to a way to improve the name and status printing without a bunch of uglycode. And since the source above is hosted at the new technically.us git node, you can totally clone and branch.

But whatever you do, do not put a variable in there or Dwemthy will personally show you a whole new world of hurt.