
On Fri, May 27, 2011 at 2:06 PM, Yves Parès
Hello,
For the purposes of a simple strategy game, I'd like to build an EDSL that expresses missions. A mission could be represented as a state machine. With basic bricks such as actions (MoveTo, ShootAt...) or tests (EnemiesAround, LowHealth...), I could (ideally dynamically) build some strategic behaviors for the units. I will take the example of a patrol. Applied to a unit (or a group of units), it dictates : go from point 1 to point 2 and then go back and repeat. But when you detect an enemy near, leave the patrol path, destroy it and then resume your patrol where you left it.
So if I consider my mission as a monad: data Mission = MoveTo Point | ShootAt Unit
patrol = do MoveTo point1 MoveTo point2 patrol
So far so good, but there, the only advantage to use a monad instead of a list of MoveTo's is the do-notation. And I lack the expression of tests. Using a GADT it could be:
data Mission a where MoveTo :: Point -> Mission () ShootAt :: Unit -> Mission Bool -- If we have destroyed it or not EnemiesAround :: Mission [Unit] -- The enemies that are maybe in sight LowHealth :: Mission Bool -- If I should retreat ...
-- (Monad Mission could be nicely expressed using Heinrich Apfelmus' operational package)
patrol = do MoveTo point1 MoveTo point2 enemies <- EnemiesAround mapM_ ShootAt enemies patrol
Aaaaaaaand... here comes the trouble: the actions are done sequentially. My units will move and then look at enemies, they will not monitor their environment while they move. So I need a way to say: A is your action of patrolling. B is your action of surveillance. Do both in parallel, but B is preponderant, as if it successes (if enemies are there) it takes over A. So, it is as if I was running two state machines in parallel. Moreover, the last line (the recursive call to patrol) is wrong, as it will restart the patrol from the beginning, and not from where it has been left. But this could be corrected by addind a test like "which point is the closest".
Could this be expressed using a new verb in your language?
data Mission a where MoveTo :: Point -> Mission () ShootAt :: Unit -> Mission Bool -- If we have destroyed it or not EnemiesAround :: Mission [Unit] -- The enemies that are maybe in sight LowHealth :: Mission Bool -- If I should retreat . . . Tasks :: [Mission ()] -> Mission () -- goals to be achieved concurrently Options :: [Mission ()] -> Mission () -- pick one of these
You'd then need to analysis and interpretation tools to correctly do the right thing with it. If the game is state-machine driven, you would need sub state-machines for each possibility under 'Tasks' or 'Options'. Antoine
So I thought about Arrows, as they can express sequential and parallel actions, but I don't know if it would be a right way to model the interruptions/recoveries. What do you think about it? Do you know of similar situations and of the way they've been solved?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe