Я хочу использовать реактивный банан, чтобы написать путевую игру, в которой люди могут писать ботов. FRP совершенно для меня совершенно, и у меня возникли проблемы с запуском. Когда я начал, я создал более сложный график, но для моих целей здесь я попытался сделать его максимально простым. Я хотел бы получить некоторые рекомендации, в основном о том, с чего начать, и как разбить эту большую проблему на более мелкие проблемы. Здесь начальный дизайн.
Идея состоит в том, чтобы иметь график LNodes (с взвешенными ребрами, на которые я сейчас игнорирую для простоты). Эти LNodes я описываю как Planet
s. Planet
имеют имя, карту игроков на Planet
и Resource
s. Игроки имеют идентификатор, ресурсы и планету. Здесь строятся данные и некоторые связанные с ними функции, за которыми следует больше обсуждений.
-- 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
Здесь, что я знаю до сих пор, мои события будут включать типы Planet
и Player
. поведения
будет включать в себя перемещение, соединение, принятие и предоставление. Когда игрок присоединяется, он создаст новое событие Player
и обновит карту на Vulcan с помощью Player
. Перемещение позволит пройти от одного
LNode
к другому, если LNode
соединены ребром. Take удалит resources
из текущего Planet
Player
"on" и добавит те resources
в
Player
. Дайте будет делать обратное.
Как я могу разбить эту большую проблему на более мелкие проблемы, чтобы я мог разглядеть эту тему?
Обновление: Оказывается, Hunt Wumpus не является хорошим выбором, чтобы помочь узнать FRP, см. объяснение того, что FRP для здесь. Это в ответ Генрих Апфельмус.
Тем не менее, я полностью проигнорирую сетевой код. Я мог бы просто написать несколько фиктивных ботов для проверки времени и т.д.
Обновление. Некоторые люди, похоже, заинтересованы в этой проблеме, поэтому я собираюсь отслеживать связанные вопросы здесь.