Tuesday, December 1, 2009

Why your next roguelike should be in a managed language

So I strongly believe that for new projects, the language of choice is important. It determines what platforms you can target. It can determine your license. It determines the type of code you write. It determines who would be interested in working with you. It determines how quickly your code can run, and how quickly you can write code and find bugs. It is one of the more important decisions you can make, since changing it requires a huge amount of work.

Now I'm going to divide languages into two groups, with a grouping I feel is pretty safe to make:

  • On one hand you have unmanaged languages. Those are ones that are generally considered "lower level". 
    • They almost always have pointers. 
    • They compile down to assembly (or are written in it). 
    • They are generally extremely fast when run, with little overhead when carefully programmed in. 
    • They are also very unsafe. You can scribble over memory almost anywhere. You can corrupt your stack and crash on returning from a function. You can many times walk off the end of arrays and lists and crash. I generally program in these at work, and some bugs can take days to sort out. 
    • Good examples include: C, C++, and assembly
  • On the other hand you have managed languages. The are the ones that are generally considered "high level"
    • They never have pointers, unless dealing with unmanaged code
    • They generally compile to a virtual machine or are interpreted
    • They are slower they the equivalent unmanaged code. How much depends on the language and what your doing
    • They are generally "safe". You get exceptions for doing incorrect things like walking off arrays and such. If you don't catch that exception, your program will still die, but you'll get a nice stack trace.
    • There are many example, the most common include Java, Python, Ruby, C#
When making your decision, you have to make tradeoffs in determining what language to use:
  • What languages you know - People generally lean towards languages they know for their "fun" projects. Others enjoy the chance to learn something new
  • Speed vs. Portability vs. Speed of Development 
    • All things being equal, C is the fastest and most portable. However, it's also the easiest to shoot yourself in the foot with. It also doesn't have a standard Graphics and Input Output library. 
    • Other languages come with portable graphics libraries, but may be too slow. Also note, that most roguelikes are turn based, so speed is in general less of a concern
  • Syntax and language - Sometimes the language itself is not suited for what you want to do with it or is hard to read and write.
  • Library - Sometime there is a library you really want to use for your roguelike, but it can only be used in a given language
    • Note, with many languages, it is possible and sometimes easy to call other languages. C# gives P/Invokes (see libtcod-net), and Java the JNI for example.
  • Ideological - Some people choose languages to write in based upon a philosophy or outlook.
    • Some people reject Java due to it being "too slow", with too slow based upon Java from the 90's on machines twice as slow as today
    • Some people reject C# due to distrust in Microsoft and fear of lawsuits, even though there is a open source implementation of it and the lawsuits could only matter if your using the interop libraries.
I wouldn't be honest in saying I don't have a preference. C# is in my opinion the nicest language to work with. It runs everywhere with mono, it is type safe and fast enough for what I'm working on, and the syntax is close enough to c++ that I picked it up easily. The bindings to libtcod make things nice as well.

However, Java is a good language as well, with many successful roguelikes written in it. Python is another language I enjoy to write in, and has multiple good toolkits to write roguelike in (libtcod, pygame, wcurses).

What I'm not saying here is that unmanaged languages are bad. C is the mothertongue of roguelikes. C++ is very popular as well. I use both at work daily. I'm just saying is that for turn based, and low graphic real time games, the benefits may not out weight the costs.


jice said...

Hehe as soon as I saw the title, I knew there was a potential troll feast :)
I agree with you on most points :
- java and C# are much cleaner languages than C or C++
- the speed difference does not matter for roguelikes
but I think you forgot a major aspect in the language choice : what prerequisite will have the end user before being able to play the game. To me, THIS is the major issue with managed languages. Nobody wants to download and install a 150MB JRE just to try a little roguelike. .net framework is even worse (something like 30 minutes to install version 3.5 on winXp...). Would you have such a framework already installed, there's a good chance you don't have the latest version. I have 3 versions of .net framework on my computer. I don't even want to know how many MB this represents...
If I was able to easily compile native .exe in a portable way with Java or C#, I would probably have dropped C++ for a long time. But solutions like gcj for Java don't seem mature enough (else most java projects would use it)...

donblas said...

I sure hope I wasn't trolling. :)

That is a good point. The .net 3.5 is 35 megs. Java now appears to be 15.9 megs. Both of these dwarf my program size. While you can hide this from the end user with an installer that bundles it in if you need it, it is annoying. The nice thing is that most new computers come with one/both, and the internet is getting fast enough that the download is quick for many people.

With python (and maybe ruby?) you can compile to an exe with no run time dependencies. That makes redistribution easy at least for python program.s

Mingos said...

As soon as Umbra is officially released, many people will realise that C++ is The Way :D. Speed loss can be a negligible fact when you deal with turn-based roguelikes with no fireworks on the screen. However, Umbrarum Regnum, although turn-based, had some really heavy rendering code, sucking one of my CPU cores almost dry.

Bottom line: choosing the correct language determines the amount of eye candy you can stuff in your game.

donblas said...

That is true. I am looking forward to seeing Umbra when it's released.

I would ask how often being CPU bound is based on doing things in a UI loop that should live elsewhere? I haven't so far run into many cases where I feel like I've been limited graphics wise based upon my language choice. However, I currently don't have too many graphics, so we'll have to see.

Jotaf said...

I definitely hit the CPU limit with multiple-lights in my RL -- Python can't handle such heavy calculations at once, not by brute force anyway. You gotta pull some tricks.

Only the player's FOV is redrawn. This may seem obvious, but in my C++ games I always redrawed the screen fully. There will be artifacts left behind if you don't redraw once more the tiles that leave the player's FOV; a common rookie mistake.

This works for dense levels (dungeons), but not if you want to have a wide FOV.

For now, this is enough for me. However, in the future I'm planning to use external C++ functions in a manner similar to Matlab's vectorized code, or functional programming -- basically compose functions together to get the desired effect, each function iterating over the whole 2D array and modifying it/returning an intermediary array. It might seem wasteful to a C++ programmer, but it works well in languages where iterating with your own code is slower, such as Matlab and Python.

As for what those functions may be, I'm checking out NumPy, but since Jice expressed interest in generalizing image and alpha operators in libtcod I'll just wait and see, I'm not in a hurry :)

donblas said...

On performance, wait for my next article. I'll talk about some issues I've run into so far, and how I've solved them. While I don't have multiple light sources, I have a lot so far and have good performance so far.

Right now, I'm updating and drawing less than a full screen but a bit more than the player's FOV. Feel free to check out magecrawl if you wanna see how I'm doing it.