On Sat, May 2, 2009 at 6:17 PM, Nicolas Martyanoff <khaelin@gmail.com> wrote:
Hi,

I don't think I already presented myself; I'm Nicolas, a 23y french
student, trying to learn and use haskell.

I've been using C for years, for all sort of tasks, and am quite
comfortable with it. I'm also using it 40h a week in my internship for
network systems, so I kind of know how to use it.

I discovered Haskell some monthes ago, bought `Real World Haskell',
quickly read, and enjoyed it.

So now I'd want to use it for a small project of mine, a simple
multiplayer roguelike based on telnet. I wrote a minimal server in C, and
it took me a few hours. Now I'm thinking about doing the same in Haskell,
and I'm in trouble.

I don't really know how to map my ideas in haskell code. For example, a
character can cast spells, so I'd have something like this in C:

   struct hashtable spells;

   struct character {
       int n_spells;
       struct spell **spells;
   };

I thought I could do something like this in haskell:

   spells = Data.Map.Map Int Spell

   data Character = Character { charSpells :: [Int] }

But now I don't know how to dynamically add new spells (new spells can be
created in my gameplay). Since I can't assign a new value to the `spells'
variable (Data.Map.insert returns a new map), I just don't know where to
go.

I'm not sure I understand how your C version and Haskell version are similar?
Wouldn't the character just have a list of Spells (since this is what the C version seems to do)? That global spells variable should probably be put in some sort of "game state" data type that encapsulates the game world.

Then consider writing updates as a function that takes the old value, and produces a new value. Indeed, consider letting the following function be your main "update" for the game state.

gameTick :: Time -> PlayerInput -> GameState -> GameState

That function would update all parts of your game state, and if you want to change some property of a character, you simply compute a new character from the old one with the field you want to change updated. Because values are immutable, any data you don't touch will just refer to the old stuff so it's actually quite efficient.

You main loop could then be something like:

gameLoop oldTime gameState = do
  time <- getTime
  let dt = time - oldTime
  input <- processInput gameState 
  gsNew <- gameTick dt input gameState
  renderGame gsNew
  gameLoop time gsNew
   

I just wanted a 2d array to store a zone, for example, dead simple in C,
but this kind of link
http://greenokapi.net/blog/2009/03/10/rough-grids-in-haskell make me
shiver.

Try a list of lists, or better yet just an Array. Make sure you update the grid "in bulk" though, as modifying just a single element at a time is slow with immutable arrays.


Point is, I'd like to use haskell, but I don't know how, it seems totally
alien.

How did you manage to change the way you map ideas to code, from
imperative to pure functional ?

Massive brain-rewiring. Keep at it, don't think in terms of modifying state, think of it as computing new values from old values. I find that the payoff of learning to think ,like this is massive, as it's usually much easier to reason about.

If you really do lots of "state" in a program, consider using a state monad like someone else already mentioned, but honestly I'd try to stay away from it and stick to a more "functional" style as far as possible.

--
Sebastian Sylvan
+44(0)7857-300802
UIN: 44640862