Reactive Banana Data Structures Sanity Check

I'm making an implementation of Grand Theft Wumpus using reactive-banana. I'm using the slot machine example to work from. For now, I'm just building a simple graph where a Player can move from Node to Node. I'm not sure I have the Data Structures right, so I wanted to run it by the community. I'm conceptualizing each Node (a Street) and the Player as a Behavior. I reason that since the Graph won't change, just the values inside a Node, I can update any Node as needed, instead of creating a new Graph whenever a value in a Node changes. It seems though, as I scale up, I'd end up with a big union of Behaviors. Does it make sense to describe each Node as a Behavior? Even though I'm starting simply, I intend to write a complete implementiation. http://nostarch.com/download/Lisp08.pdf data StreetName = Baker | Main | Atlantic | Baltic | Connecticut deriving (Enum,Bounded,Show) type Player t = Behavior t Player_ type Street t = Behavior t Street_ data Player_ = Player {location :: StreetName } deriving Show data Street_ = Street_ {sName :: StreetName ,player :: Maybe Player_ } deriving Show data GameEvent = MovePlayer Street | Look does that look okay so far?

Michael Litchard wrote:
I'm making an implementation of Grand Theft Wumpus using reactive-banana. I'm using the slot machine example to work from.
For now, I'm just building a simple graph where a Player can move from Node to Node. I'm not sure I have the Data Structures right, so I wanted to run it by the community. I'm conceptualizing each Node (a Street) and the Player as a Behavior. I reason that since the Graph won't change, just the values inside a Node, I can update any Node as needed, instead of creating a new Graph whenever a value in a Node changes. It seems though, as I scale up, I'd end up with a big union of Behaviors. Does it make sense to describe each Node as a Behavior? Even though I'm starting simply, I intend to write a complete implementiation.
http://nostarch.com/download/Lisp08.pdf
data StreetName = [...]
type Player t = Behavior t Player_ type Street t = Behavior t Street_
data Player_ = Player {location :: StreetName } deriving Show data Street_ = Street_ {sName :: StreetName ,player :: Maybe Player_ } deriving Show
data GameEvent = MovePlayer Street | Look
does that look okay so far?
That's hard to say. It certainly doesn't look wrong, but whether it's a good idea or not depends on what you will do later. My process for programming with Functional Reactive Programming (FRP) is usually this: * What is the "end product", i.e. the thing that users ultimately interact with? In your case, it's probably the drawing of a map of the city. * Does the end product "vary in time"? Yes? Then it's going to be a Behavior City , i.e. a data structure that describes the evolution of the city in time. * How does the city evolve in time? Here I start to think of the events and other behaviors that I use to define the behavior, for instance by writing bcity :: Behavior City bcity = stepper ... -- step function from events or bcity = (++) <$> bsuburbs <*> bcenter -- combine other behaviors and so on. The process is a bit like thinking as a physicist in god-mode: for each object in my little universe, I specify where it should be at any particular time, like 5 o'clock. That said, I found it useful to decouple the interaction of individual parts -- city, node, player -- from their time evolution. Have a look at the Asteroids.hs example http://www.haskell.org/haskellwiki/Reactive-banana/Examples#asteroids The bottom part of the source contains function like advanceRocks or collide that specify more complicated interactions between different objects. The FRP part of the source file just specifies *when* these interactions take place, i.e. advanceRocks happens when etick happens while the player moves when eleft or eright happen. In other words, my rule of thumb is How does it happen? => ordinary functions When does it happen? => events and behaviors In particular, you can write your Wumpus game logic by asking the "how" questions first and only then ask the "when" questions. Thus, I would rename Player_ to Player for the "how" part and simply use Behavior t Player for the fairly small "when" part. Hope that helps. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com
participants (2)
-
Heinrich Apfelmus
-
Michael Litchard