OCaml and me

I have a few recurring test projects I do with new languages and environments. One of them is to put together the rudiments of a simulation featuring characters who get AI ticks, have characteristics and statuses, can be described in text, etc. Usually this gets far enough that I can task one character to chase another one around in circles, and then it's time to move on.

This weekend I did the first few strokes of this project in OCaml, a language that's interested me for a decade or so. In the last few years, the quality of documentation has improved a lot (check out the sweet website), it's picked up some industry support (notably Jane Street), and a nascent English-speaking community (OCaml's principal development has always been in French) resulting from the recently enlarged profile of statically-typed functional languages.

OCaml resembles Haskell in a number of ways. It's a direct descendant of ML, which Haskell was heavily influenced by. Both languages use a form of Hindley-Milner type inference, and the syntax generally feels similar.

Unlike Haskell, though, OCaml is strict (versus Haskell's laziness) and impure (functions can have side effects and contain imperative code; no IO monad necessary). It permits mutable variables, arrays, strings, and maps, all explicitly declared. It even has a neat object-oriented programming facility built in as a first-class participant in the type system and which works seamlessly with functional code. It's explicitly a multi-paradigmatic language, which appeals to me a great deal. The community still strongly encourages writing pure functional code, but in general I've found them to be less fanatical on the topic than Haskellers. There's also less of a math/PLT focus in the community, and idiomatic OCaml is less terse and symbolic than Haskell.

What I worked up is here. Once I've spent a bit more time fleshing it out, I'll write more about it. For this project, I'm trying out Batteries, which is one of several competing alternative standard libraries for OCaml. (What it means to have alternative standard libraries, and why such a thing has happened, is a subject for yet another post to come.) On other projects, and on the OCaml exercises at Exercism, I've been using Core from Jane Street. Core is also what's covered by the book Real World OCaml, which has been a fantastic resource.

Learning OCaml has been an exciting process so far. Ruby is very dear to me, and I've done a lot of work I'm proud of with it, but I think it's good for a programmer to stay flexible on the tools they use. OCaml provides a number of strong contrasts to Ruby (compiled, functional, statically typed) while retaining elements that I appreciate (object oriented features, a multiparadigmatic approach). I can imagine using it for future projects where the type system would come in handy, where I need high performance, or where I'm looking to deliver a compiled binary. And sometimes it's just fun.

So here I am again

I am notoriously terrible at keeping up on any kind of blog, even though I’m usually up to something. Before too long we’re going to be doing a group blog at work, and hopefully I’ll actually be able to stick to that under the ancient principle that it takes a measure of competition to get me off my ass.

Right now I’m working on a new game. I haven’t given up on the Christmas Hack, although at this point it looks like it’ll eventually be a Summer Hack or a Halloween Hack. It’s one of three ideas I’m really interested in right now.

The one I’m working on is much simpler: kind of an arcade game. I’m working on it in Ruby, using a simple game engine and the Chipmunk physics library. I’m doing everything I can to just focus on delivering a fun, enjoyable game.

The game is called Unfunky UFO.

Image

This screenshot is of my latest build, with debug visuals (the red boxes, which indicate collision shapes) enabled. The name is derived from a Parliament song on the legendary Mothership Connection album.

In Unfunky UFO, you control a wayward spaceship visiting Earth. You are low on biofuels, and need to accumulate enough to break orbit and set off toward home. Luckily, the planet below has a lot of cheerful, smiling, ambulatory fuel pods for you to pick up and convert into alien biodiesel with your trusty tractor beam.

Your ship is always moving; you spend a little fuel to change direction. The tractor beam only switches on when you’re close enough to the ground. When little dudes are caught in it, they slowly float up to the UFO, flailing wildly all the while. Collecting a little dude gains you golden points (trademark Tracy Jordan) and also fuel, to keep you from crashing. The trick is to limit the number of moves you need to make to pick up the most squishy, delicious humans in a row.

Each level has a finite number of humans (and probably cows and cars and such), and it’s possible to accidentally kill them by letting the tractor beam break. You can also smash into the ground. Later levels will have more complicated terrain to avoid, and probably faster, more evasive critters.

I’m developing this as a keyboard-controlled PC game, but my idea is mostly for mobile phones. You swipe over the UFO, and it jots off in that direction. To be honest, I originally conceived it when discussing Flappy Bird with some coworkers. I was fascinated by how the limited, frustrating controls of such a half-assed game led to it being appealing to players. Unfunky UFO is my attempt to make a simple, appealing game based around predictable but difficult controls, except hopefully with some more depth to it. I don’t intend to follow after the model of that highly profitable game, though. My intent is to port it (by hand, using the native APIs) to both Android and iOS, and release it for free. That’s about as much as I could reasonably expect for a game with graphics I made myself! What I want is the joy of having made a game, and the education of making it.

I do have ideas for a follow-up, it is true… but let’s see about getting this done first!

Christmas Hack Day Zero: The Plan

I’m going to start working on my game idea tomorrow. I have a pretty good idea of the mechanics of a single level. I’ve picked a language (C, with prototyping in Ruby), a networking library (ZeroMQ), a graphics library (SDL 2.0). I’ve created a skeleton project on GitHub.

My plan is to get at least an hour of work in every day, but hopefully a lot more. I do have social plans throughout the holidays — spending time with two different friends over this weekend, time with family on Christmas Eve and Christmas, a holiday party with friends later this week, and possibly some New Year’s stuff. I also have committed to getting out of the house every day and making sure I keep up on my chores around the house. These are the kind of things you have to commit yourself to when you’re a chronic depressive.

Tomorrow I’ll be pretty busy cleaning up my house and spending time with a friend, but I’m hoping to at least start doing some concrete design. I hope to have basic graphics rendering by Monday, recognizable gameplay by the end of the day on Christmas, working netplay by the 28th, and a beatable single level by Monday the 30th. I’ll be making at least one status post every day.

I know nobody’s reading this but me, but I’m hoping to be able to look back on what I did and learn more about how I think and work.

Here goes!

CH ZeroMQ experiments

I’m doing some experimental work to figure out whether the netplay design I have in mind would be feasible using ZeroMQ. I’m working in Ruby at the moment because it’s the most natural language for me to work in. The ZMQ guide has Ruby examples using ffi-rzmq, which maps pretty closely to the underlying API. Whatever design I prototype in Ruby should work equally well in another language.

I’m thinking about the networking requirements in tandem with my concurrency requirements, which is something ZMQ kind of encourages you to do. You’re encouraged to rely on using ZMQ in-process communication instead of mutexes, condition variables, etc. to coordinate between your threads. This is worth trying out, although I don’t necessarily know how well it will play with whatever graphical toolkit I end up using.

So the way I’m envisioning this right now is that each player has an outgoing event queue and an incoming event queue. Messages can be received and delivered asynchronously. Successful delivery counts on TCP’s retry mechanisms, and there’s no acks in the protocol. Each of these queues lives in its own thread. An additional thread is responsible for running the simulation. It reacts to events fed into it from the incoming event queue and emits events for the outgoing event queue. It also listens for input from the UI thread (i.e., whatever the user is doing). Finally, it ticks the game logic around 60 times per second so that objects can move, AI can operate, etc.

What you end up having is the simulation thread using input from the current player, events from the other player, and the current state of the arena to 1) set up the next state of the arena so it can be displayed and 2) emit events for the other player’s arena.

Setting up a minimal version of this design in Ruby was easy. In essence, the app works like a chat system — you type in text, hit enter, and the message is relayed to the local simulation thread. The simulation thread adds identifying information and its current tick to the message (so you can see it’s working) and passes it on to the output queue. The other instance of the app receives the message in its input queue, passes it into the simulation thread, and displays it.

Here’s one side of the exchange:

% ruby duplex_msg.rb 5555 5556 right 
are you there 
HEARING >> left: 132: are you there? I AM HERE! 
holy shit dude 
HEARING >> left: 705: holy shit dude? NO KIDDING RIGHT! 
cannot believe this works 
HEARING >> left: 1090: cannot believe this works? ME NEITHER!

And the other side:

% ruby duplex_msg.rb 5556 5555 left
HEARING >> right: 100: nothing? are you there!
I AM HERE
HEARING >> right: 586: I AM HERE? holy shit dude!
NO KIDDING RIGHT
HEARING >> right: 1003: NO KIDDING RIGHT? cannot believe this works!
ME NEITHER

Note the increasing tick number, which goes up in real time. This stands in for the local game logic. The last message sent is incorporated into the reply in order to simulate a change to the game state from the incoming event.

The implementation is pretty simple — 80 lines of Ruby. I’ve created a Gist for it. I’m pretty confident at this point that ZMQ will be useful for my purposes. This design seems to work acceptably for much higher volumes than I expect to require, too: piping ‘yes’ to both ends churns out a great deal of output and eats up a lot of CPU but proceeds diligently without any weird behavior.

Christmas Hack

I tend not to take long periods of time off without something planned, but the use-it-or-lose-it nature of some of my PTO has led me to take the entire week of Christmas off. I’m expecting to spend Tuesday and Wednesday (that is, Christmas Eve and Christmas) at least partially with family, but that leaves me with three and four days off in a row.

I’d like to spend at least some of that time physically working on projects or chores around the house, but I would also like to use the time to get some concentrated effort in on an educational project.

So what I’ve decided to do is to identify a fairly clearly defined project outside of my comfort zone and attempt to complete it, with daily updates here. What I am currently looking at is writing a game with local netplay capability using SDL 2 and Objective-C. All of these are things I’ve been interested in working with or on, and none of them have much to do with what I do on a daily basis.

I’ve previously found building a little game (and game toolkit) to be useful in learning other languages, like Go. My web work relies a lot on the Internet, but it’s been a long time since I did any low-level networking code, and I might even be able to sneak in learning something like ZeroMQ.

SDL 2 has pretty shitty documentation right now, unfortunately — even the official site guides you to third-party tutorial content. I’ve worked with SDL 1.2 in the past, though.

Objective-C is currently kind of a wasteland outside the Apple compound, and I think that’s a shame. It’s an interesting language and it always has been the object-oriented C variant I preferred. I’ve been doing some work with C recently and I would really like to be able to take advantage of some of ObjC’s richer abstractions while still working in a relatively low-level, compiled language. ObjFW and clang are probably my best bet in Linux-land. If I really can’t get it to work, I’ll either look at Rust or resort to C, depending on my timeline.

My goal is to start first thing in the morning Saturday, December 21st and have something worth looking at by mid-day on Sunday, December 29th. I’ll create the repo and start writing code then, but I will be planning things (doing some basic sanity checks with ObjFW + SDL, coming up with a design document for the game, etc.) in advance.

The need to know

A challenge I have encountered as I progress in my work is trying to find the right value to place on knowledge. Software developers are in the class of workers referred to as “knowledge workers”, and the culture certainly places a premium on practical knowledge. Job postings list languages and systems that you need to be an expert in, and news sites like Hacker News fixate on the growth, continuing relevance, and decline of particular technologies.

In my experience, though, raw knowledge seems to be only one of many valuable traits in a developer, and in many cases it is less useful than others. In no particular order, the best developers I have worked with exhibit the following qualities.

They are resourceful and flexible in the tools they use, while still being forthright and assertive when the tools available fall short. This applies to hardware, to development tools, to languages, to deployment environments, to everything. A great programmer might be able to make do with an eeePC with dialup in a broom closet, but they won’t fall prey to the macho inclination (or managerial pressure) to pretend that it doesn’t cut into their productivity.

A great developer has to be socially competent. As a person who suffers from social anxiety, I am painfully aware of how often I fall short in this regard. It is tempting to attempt to hide in the dark back room, sheltered by layers of code and the social expectation that a programmer is terse, grumpy, and avoidant. The genuinely brilliant can get away with this to a certain extent — we all know this type of person, famous and obscure — but it is ultimately limiting, and it is not a path many can follow.

The best developers I have known have been able to maintain friendly, open communication both within and without their teams. They are willing and able to explain, promote, and defend their ideas both in pure technical terms and on a practical basis to management and other stakeholders. They don’t rely on the expectation that a programmer’s voice is the Word of God. Someone who relies on nobody else in the room having any idea what it is they do is ultimately in for a rude awakening.

When the necessity arises, a great programmer is knowledgeable, but is because they have refined the process of learning and investigation. When faced with a new tool, they are good at training themselves to use it. When they encounter a new system, they are unafraid to investigate and discover how it works. Nobody can read unreadable code, but given enough time it is possible to at least discover what the code does, which is sometimes more useful than knowing what it is supposed to do.

Knowledge of tools is useful, but tools rust. Knowledge of systems is indispensable, but systems change. The best programmers I have worked with have not been the ones who write the cleanest, fastest, or cleverest code. They’re the ones who can land in a situation with imperfect tools, imperfect requirements, and imperfect people and make them all a little better. As I struggle to refine and improve myself professionally, I try to keep in mind that my limited technical ability is only one of the many factors that may contribute to my success in the long term.