Quiero usar reactive-banana para escribir un juego de viajero para el que las personas pueden escribir bots. FRP es completamente nuevo para mí, y tengo problemas para comenzar. Creé un gráfico más elaborado cuando comencé, pero para mis propósitos aquí, he tratado de hacerlo lo más simple posible. Me gustaría obtener alguna orientación, principalmente sobre dónde empezar y cómo resolver este gran problema en pequeños problemas para resolver. Aquí está el diseño inicial.Functional-Banana Traveler Game - Intriguing and Maddening
La idea es tener un gráfico de LNodes (con bordes ponderados que ignoro por ahora por simplicidad). Estos LNodes que describo como Planet
s. El Planet
s tiene un nombre, un mapa de los jugadores en el Planet
y Resource
s. Los jugadores tienen una identificación, recursos y un Planeta. Aquí están las Estructuras de Datos y algunas funciones asociadas, seguidas de más discusión.
-- Graph-building records and functions
data PlanetName = Vulcan
| Mongo
| Arakis
| Dantooine
| Tatooine
deriving (Enum,Bounded,Show)
data Planet = Planet {pName :: PlanetName
,player :: IntMap Player
,resources :: Int
} deriving Show
data Player = Player {pid :: Int
,resources :: Int
} deriving Show
makePlanetNodes :: PlanetName -> [LNode Planet]
makePlanetNodes planet = Prelude.map makePlanetNodes' $
zip [planet ..] [0 ..]
where makePlanetNodes' (planet,i) =
(i,Planet {pName = planet, players = IM.empty})
makePlanetGraph p = mkGraph p [(0,1,1),(1,2,2),(2,3,4),(3,4,3),(4,0,2)]
-- Networking and command functions
prepareSocket :: PortNumber -> IO Socket
prepareSocket port = do
sock' <- socket AF_INET Stream defaultProtocol
let socketAddress = SockAddrInet port 0000
bindSocket sock' socketAddress
listen sock' 1
putStrLn $ "Listening on " ++ (show port)
return sock'
acceptConnections :: Socket -> IO()
acceptConnections sock' = do
forever $ do
(sock, sockAddr) <- Network.Socket.accept sock'
handle <- socketToHandle sock ReadWriteMode
sockHandler sock handle
sockHandler :: Socket -> Handle -> IO()
sockHandler sock' handle = do
hSetBuffering handle LineBuffering
forkIO $ commandProcessor handle
return()
commandProcessor :: Handle -> IO()
commandProcessor handle = untilM (hIsEOF handle) handleCommand >> hClose handle
where
handleCommand = do
line <- hGetLine handle
let (cmd:arg) = words line
case cmd of
"echo" -> echoCommand handle arg
"move" -> moveCommand handle arg
"join" -> joinCommand handle arg
"take" -> takeCommand handle arg
"give" -> giveCommand handle arg
_ -> do hPutStrLn handle "Unknown command"
echoCommand :: Handle -> [String] -> IO()
echoCommand handle arg = do
hPutStrLn handle (unwords arg)
moveCommand = undefined
joinCommand = undefined
takeCommand = undefined
giveCommand = undefined
Esto es lo que sé hasta ahora, mis actos supondrán tipos Planet
y Player
. Behaviors implicará mover, unir, tomar y dar. Cuando un jugador se une, creará un nuevo evento Player
y actualizará el Mapa en Vulcan con ese Player
. Move permitirá un recorrido de LNode
a otro, siempre que el LNode
s esté conectado por un borde. Tomar eliminará resources
del actual Planet
el Player
está "on" y agrega los resources
al Player
. Give hará lo opuesto.
¿Cómo puedo resolver este gran problema en problemas más pequeños para que pueda entender todo esto?
Actualización: Resulta que Hunt the Wumpus no es una buena opción para ayudar a aprender FRP, vea una explicación de lo que es FRP para here. Es en una respuesta de Heinrich Apfelmus.
Dicho esto, voy a ignorar por completo el código de red por ahora. Podría escribir algunos bots falsos para probar el tiempo, etc.
Actualización: Algunas personas parecen estar interesadas en este problema, por lo que voy a seguir las preguntas relacionadas aquí.
¡Ah hunt the wumpus! Sí, comenzar sonidos más pequeños es un buen movimiento. –