Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 功能香蕉旅行者游戏-有趣和疯狂_Haskell_Reactive Banana - Fatal编程技术网

Haskell 功能香蕉旅行者游戏-有趣和疯狂

Haskell 功能香蕉旅行者游戏-有趣和疯狂,haskell,reactive-banana,Haskell,Reactive Banana,我想用反应型香蕉来编写一个旅行者游戏,人们可以为它编写机器人。FRP对我来说是全新的,我很难开始。当我开始时,我创建了一个更复杂的图表,但出于我的目的,我已经尝试使它尽可能简单。 我想要一些指导,主要是关于从哪里开始,以及如何把这个大问题分解成小问题来解决。这是最初的设计 这个想法是要有一个LNodes图(为了简单起见,我现在忽略了加权边)。我把这些节点描述为行星。Planets有一个名字,一张Planet和Resources上玩家的地图。玩家有一个id、资源和一个星球。下面是数据结构和一些相关

我想用反应型香蕉来编写一个旅行者游戏,人们可以为它编写机器人。FRP对我来说是全新的,我很难开始。当我开始时,我创建了一个更复杂的图表,但出于我的目的,我已经尝试使它尽可能简单。 我想要一些指导,主要是关于从哪里开始,以及如何把这个大问题分解成小问题来解决。这是最初的设计

这个想法是要有一个LNodes图(为了简单起见,我现在忽略了加权边)。我把这些节点描述为行星。
Planet
s有一个名字,一张
Planet
Resource
s上玩家的地图。玩家有一个id、资源和一个星球。下面是数据结构和一些相关函数,接下来是更多的讨论

-- 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
——图形生成记录和函数
数据平面名称=Vulcan
|蒙戈
|阿拉基斯
|丹图因
|塔图因
派生(枚举、有界、显示)
数据行星=行星{pName::PlanetName
,player::IntMap播放器
,参考资料::Int
}衍生节目
数据播放器=播放器{pid::Int
,参考资料::Int
}衍生节目
makePlanetNodes::PlanetName->[LNode Planet]
makePlanetNodes planet=Prelude.map makePlanetNodes'$
zip[星球..][0..]
makePlanetNodes(行星,i)的位置=
(i,行星{pName=Planet,players=IM.empty})
makePlanetGraph p=mkGraph p[(0,1,1)、(1,2,2)、(2,3,4)、(3,4,3)、(4,0,2)]
--网络和指挥功能
准备套接字::端口号->IO套接字
prepareSocket端口=do
短袜()
commandProcessor handle=untilM(hIsEOF handle)handleCommand>>hClose handle
哪里
handleCommand=do
行命令句柄参数
“移动”->moveCommand句柄参数
“join”->join命令句柄参数
“take”->take命令句柄参数
“give”->giveCommand句柄参数
_->hPutStrLn是否处理“未知命令”
echoCommand::Handle->[String]->IO()
echoCommand句柄arg=do
hPutStrLn手柄(UNOWORDS参数)
moveCommand=未定义
joinCommand=未定义
takeCommand=未定义
giveCommand=未定义
这是我到目前为止所知道的,我的活动将涉及类型
Planet
Player
。行为 将涉及移动、加入、获取和给予。当玩家加入时,它将创建一个新的
player
事件,并用该
player
更新Vulcan上的地图。移动将允许从一个位置进行遍历
LNode
连接到另一个节点,前提是
LNode
s通过边缘连接。Take将从当前
星球上删除
资源
玩家
处于“开启”状态,并将这些
资源
添加到
播放器
。给予会适得其反

我怎样才能把这个大问题分解成更小的问题,这样我就可以在这个问题上动脑了

更新:事实证明,Hunt the Wumpus不是帮助学习FRP的好选择,请参见FRP的用途说明。这是海因里希·阿普费尔摩斯的回应

也就是说,我现在将完全忽略网络代码。我可以写一些虚拟机器人来测试时间等等

更新:有些人似乎对这个问题感兴趣,所以我将在这里跟踪相关问题


这是一个复杂的项目。游戏大致分为以下几部分:

  • 输入层(将输入转换为游戏事件)
  • 引擎(获取事件和当前状态以生成新的游戏状态)
  • 输出层(显示游戏状态和执行事件产生的消息)
首先,我将使用控制台输入和输出(即stdin和stdout)简化输入和输出层。之后,您可以添加网络支持

其次,我会简化游戏本身。例如,从单人游戏开始。最近,我把Lisp之地的游戏《侠盗猎车手》翻译成Haskell,玩得很开心

第三,我将从游戏引擎开始。这意味着您必须考虑:

  • 什么是游戏状态
  • 比赛项目有哪些
为游戏状态和每个事件定义Haskell数据结构。请注意,游戏状态需要记录与游戏相关的所有内容:地图、玩家位置、玩家状态,甚至随机数种子

游戏状态通常为产品类型:

data GameState = {  _mapNodes :: [Node]
                   ,_mapEdges  :: [ (Node,Node) ]
                   ,_player   :: Node
                   , ...
                 }
游戏事件应定义为总和类型:

data GameEvent =
  | MovePlayer Node
  | Look
  | ...
定义这些数据结构后,编写
performEvent
函数:

performEvent :: GameEvent -> GameState -> IO(GameState)
performEvent
的结果是
IO(GameState)
的原因是您可能需要通知玩家发生了什么,在游戏的这个阶段,使用
IO
monad将是实现这一点的最简单方法(没有双关语)。有一些方法可以净化像
performEvent
这样的函数,但这完全是另一个话题

例如:

performEvent :: GameEvent -> GameState -> IO(GameState)
performEvent (Move p n) s =
  do putStrLn "Moving from " ++ (show $ s _player) ++ " to " ++ (show n)
     return s { _player = n }
performEvent Look       s =
  do putStrLn "You are at " ++ (show $ s _player)
     return s
一旦测试了
performEvent
,就可以添加前端,将一行文本转换为
GameEvent

parseInput :: Text -> Maybe GameEvent
parseInput t = case Text.words t of
                 ("look":_)    -> Just Look
                 ("move":n:_)  -> Move <$> (parseNode n)
                 otherwise     -> Nothing
parseInput::Text->Maybe GameEvent
parseInput t=大小写文本。单词t of
(“看”:-->只是看一下
(“move”:n:))->移动(parseNode n)
否则->无

然后添加一个输入循环,编写一个函数来创建初始游戏状态,在您知道之前,您将拥有一个真正的交互式游戏

啊,猎杀乌姆普斯!是的,开始小一点听起来不错。