[Haskell-cafe] State Machine and the Abstractions
Yves Parès
limestrael at gmail.com
Fri May 27 21:06:10 CEST 2011
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".
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?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20110527/b614861b/attachment-0001.htm>
More information about the Haskell-Cafe
mailing list