Aug 29, 2009

Ruby Warrior

Here's an interesting programming puzzle (thanks Nige). The challenge is to write a (stateless?) control function for a warrior, and have it fight its way up the stairs to the next level. This is the level I'm stuck on:

Level 6

The wall behind you feels a bit further away in this room. And you hear more cries for help.

Tip: You can walk backward by passing ':backward' as an argument to walk!. Same goes for feel, rescue! and attack!.

 --------
|C @ S aa|
--------

> = Stairs
@ = groo (20 HP)
C = Captive (1 HP)
S = Thick Sludge (24 HP)
a = Archer (7 HP)


Available Abilities:

warrior.walk!
Move in given direction (forward by default).

warrior.rest!
Gain 10% of max health back, but do nothing more.

warrior.feel
Returns a Space for the given direction (forward by default).

warrior.health
Returns an integer representing your health.

warrior.rescue!
Rescue a captive from his chains (earning 20 points) in given direction (forward by default).

warrior.attack!
Attack the unit in given direction (forward by default).


Give it a shot.

Why Groovy? Why Not Ruby?

I was talking to an old friend and telling him that I was coding a lot in Groovy in my spare time. He asked me why I wasn't coding my project in Ruby. I really didn't have a good answer for him.

In fact I just looked back at some old Ruby code of mine and it does in fact look very similar to the Groovy code I've been writing. Hmm.

Aug 15, 2009

Opening Ports to a Virtualbox VM

If you want to be able to connect to a service running on your Virtualbox VM, this is how to go about it. (global means it applies to any Virtualbox VM you run)

$ VBoxManage setextradata global "VBoxInternal/Devices/pcnet/0/LUN#0/Config/serviceName/Protocol" TCP
$ VBoxManage setextradata global "VBoxInternal/Devices/pcnet/0/LUN#0/Config/serviceName/GuestPort" portInVM
$ VBoxManage setextradata global "VBoxInternal/Devices/pcnet/0/LUN#0/Config/serviceName/HostPort" portExposedAs
See the full documentation for more info.

Setting Up Telnetd

Every couple of years I want to setup telnetd on my linux box again. Each time I get telnetd installed and then try and figure out why it's not started. So this time around this is what I needed to do:

sudo apt-get install telnetd
This included openbsd-inetd for me. However:
sudo /etc/init.d/openbsd-inetd restart
reported:
Not starting internet superserver: no services enabled.
The missing step was to include this line in /etc/inetd.conf:
telnet  stream tcp nowait root /usr/sbin/tcpd in.telnetd

Aug 5, 2009

Start the Day Laughing

On my way in to work I walked past a corporate van for a company called Conejo something or rather. I bet the founders knew "conejo" meant "rabbit", yet probably not that it means something else as well!

Aug 4, 2009

An Internal DSL in Groovy

There's an approach to robotic control called Reactive Action Packages. It's a way of specifying what to what, when, in what sequence, and with what taking priority over what. All of it specified in a robust manner and driven by external sensors. Anyway, I've coded my take on RAPs a number of times and never really been happy with the result. This time though my solution really feels right. Groovy builders work so well here:


this.brain = new NodeBuilder()
.code {
when('lost') {
explore()
}
when('score < 1000') {
go('somePlace')
someAction()
}
}
The basic idea is that this DSL can be evaluated each time my robot needs to take an action. DSL statements are evaluated in sequence until one provides an action. So, if it's lost it explores. If it's not lost and it's score is under 1000 and it's already at somePlace then it does someAction. Sweet!

The only gotcha to evaluating the NodeBuilder result is that closure('aString') statement1 ; statement2 } evaluates to a Node whose value() is ['aString', node1, node2]:
this.eval = { code ->
if (code instanceof Node) {
return evalNode(code)
}
def iterator = code.iterator()
def result = null
while(!result && iterator.hasNext()) {
def node = iterator.next()
result = eval(node)
}
return result
}
this.evalNode = { node ->
def result = actions[node.name()](node.value())
return result
}
actions are defined easily enough:
this.actions = [
when: { args ->
if (shell.evaluate(args[0])) {
return eval(args[1,-1])
}
return false;
},
explore: { "EXPLORE" },
go: { to ->
def loc = shell.evaluate("loc")
if (loc == to) {
return false
}
def direction = navigator.directionTo(loc, to)
return "DIR $direction"
},
someAction: { "SOME_ACTION" }]
The last piece of the puzzle is setting up the GroovyShell with it's context and evaluating the DSL code:
this.act = {
shell = new GroovyShell()
shell.setVariable("loc", loc)
shell.setVariable("score", score)
def action = eval(brain.value())
if (action) {
// do magic
} else {
println "No action chosen!"
}
}
To those who made builders a part of Groovy: thanks so much!

Aug 2, 2009

Git At Home

Setting up your own git server at home is easy enough. Once you have sshd running (or Remote Login enabled), your friends for interacting with the remote repository are:

git clone username@machineIP:path
git remote add remoteRepoNickname username@machineIP:path
git push remoteRepoNickname branchName
git pull remoteRepoNickname branchName


I got started using Pragmatic Version Control Using Git. There's also an online book: Pro Git.

Above and beyond 'there is no server', the main thing I needed to get my head around was that git has the concept of 'staging' commits. For example:

  • git add file will stage file's deltas.
  • git status will show you your staged changes.
  • git commit -m 'comment' will then commit your staged changes.
  • git push remoteRepoNickname master then pushes your committed changes to another machine.