{-| Module : Game.GoreAndAsh.Actor Description : Module that contains actor API for Gore&Ash Copyright : (c) Anton Gushcha, 2015-2016 License : BSD3 Maintainer : ncrashed@gmail.com Stability : experimental Portability : POSIX -} module Game.GoreAndAsh.Actor.Indexed( GameWireIndexed(..) , GameActor , updateIndexedWire , postActorAction , preActorAction ) where import Control.Wire import Prelude hiding (id, (.)) import Game.GoreAndAsh.Core.Arrow import Game.GoreAndAsh.Core.Monad -- | Game wire that has its own id data GameWireIndexed m i a b = GameWireIndexed { indexedId :: i , indexedWire :: GameWire m a b } -- | Equality by equality of ids instance Eq i => Eq (GameWireIndexed m i a b) where gw1 == gw2 = indexedId gw1 == indexedId gw2 -- | Replaces controlling wire in indexed wire updateIndexedWire :: (GameWire m a b -> GameWire m a b) -> GameWireIndexed m i a b -> GameWireIndexed m i a b updateIndexedWire f wi = wi { indexedWire = f $ indexedWire wi } -- | Common pattern in game for creating incapsulated objects -- -- Usually wires that are actors need context to register themselfes in core. -- Major part of wire functions operates with such wrapped indexed arrows thats -- why the convinient type synonym is exists. type GameActor m i a b = GameMonadT m (GameWireIndexed m i a b) -- | Compose actor and wire, the wire is added at the end of actor controller postActorAction :: Monad m => GameActor m i a b -> (i -> GameWire m b c) -> GameActor m i a c postActorAction mindexed wi = do indexed <- mindexed return $ indexed { indexedWire = wi (indexedId indexed) . indexedWire indexed } -- | Compose actor and wire, the wire is added at the beginning of actor controller preActorAction :: Monad m => (i -> GameWire m c a) -> GameActor m i a b -> GameActor m i c b preActorAction wi mindexed = do indexed <- mindexed return $ indexed { indexedWire = indexedWire indexed . wi (indexedId indexed) }