ANN: Roguestar 0.6.0.0

Roguestar 0.6.0.0 is now up on hackage.  You can install and run with:

$ cabal install roguestar roguestar-glut roguestar-engine
& ~/.cabal/bin/roguestar

The latest version brings:

  • New monsters: Hellions and Dust Vortexes
  • Underground dungeons
  • Power-ups (hidden in the aforementioned dungeons) that serve to level-up the player’s character.
  • Improved walking animation.
  • It’s no longer possible to spawn with zero sight range.
  • Fixed some of the worst of the user interface glitches.

Under the hood, I’ve also split RSAGL into a few topic-specific libraries and implemented value recursion in rsagl-frp.  There is an experimental GTK-based client, but I don’t recommend it just yet, which is why it isn’t on hackage.

I’ve also migrated the project to github, which includes source code, the manual, and the issue tracker.

Posted in Uncategorized | Leave a comment

The One Function per Typeclass Rule

After about five years programming in Haskell, I think we need a rule:  Only put one function in a typeclass.

Why?  Because inevitably someone comes along with a data type for which one or the other function of a typeclass is perfectly suited, and yet another function of the same typeclass is not implementable.

Here are some examples of consequences of breaking the rule:

  1. The Infamous Set Monad, which requires splitting Monad in half. (Monad)
  2. All of the abstract ways to construct Nothing: fail (Monad), mempty (Monoid), mzero (MonadPlus), empty (Alternative).  Not surprisingly, all of these typeclasses are subtly related.
  3. The natural numbers, which have a minBound, but not a maxBound (Bounded) . . .
  4. . . . and which support addition and multiplication, but aren’t closed under subtraction and for which the concept of a sign does not exist (Num).
  5. My own memoizable message type, which would like to implement Applicative, but needs a monadic computation to implement pure. (Applicative)

It’s a little extra typing to write multiple “class . . . where” clauses for each type that needs to implement a large number of type-indexed functions, but it’s quite easy to combine related typeclasses when appropriate, as follows:

class Foo a where
    foo :: a -> b

class Bar a where
    bar :: a -> b

class (Foo a,Bar a) => FooBar a where
    {this space intentionally left blank}

In conclusion, you should definitely follow this rule if I have convinced you that it is a good idea to follow it.

Posted in Haskell | 2 Comments

But does it crawl?

Roguestar is officially a dungeon crawl now, as it actually has dungeons:

An Androsynth visits the dungeon.

An Androsynth visits the dungeon.

For the moment I’m ok with the empty black pits, but I want to do something with the skylights.  Maybe slant them at an angle?  I’ll probably also change the dungeon lighting to some kind of red-orange shining up with the camera light at half-brightness.

I have a lot less free time now than I used to, so I’m trying to focus on specific game features and spend less time fiddling with stuff (like FRP semantics) under the hood.

Posted in Roguestar | Leave a comment