如何在文本中表示和跟踪可变状态

这个问题是关于如何设计一个应用程序和布局数据,以在冒险游戏中表示可变状态,其中存在玩家可以进入的位置以及可以在这些位置或者在他们选择之后在玩家库存中的物品他们了。

newtype ItemName     = ItemName Text
newtype LocationName = LocationName Text
newtype Description  = Description Text
new type ItemWeight  = ItemWeight Int

data Location = Location LocationName Description [Item]
data Item     = Item ItemName [ItemName] Description ItemWeight
data Player   = Player PlayerPosition [Item]

data PlayerPosition = ...

因为这是可变的,并且其他所有内容都是不可变的,所以每个Location都有一个Item列表可能没有意义。 对于Player

在这样的游戏中,核心逻辑属于一个被称为的功能。

playMove :: Move -> GameState -> ([MoveResult], GameState)

MoveMoveResult函数在哪里

data Move                              data MoveResult
  = MoveTo Direction                     = EnteredLocation Location
  | PickUpItem ItemName                  | NoLocationAt Direction
  | UseItemWithItem ItemName ItemName    | PickedUpItem Item
  | Examine ItemName                     | UsedItemWithItem Item
  | Quit                                 | CantUseItems Item Item
                                         | NoSuchItem Item
                                         | Description Item
                                         | InventoryFull ItemWeight Item
                                         | GameWon
                                         | ...

Move用户输入解析为Move值并输出MoveResult ,这是发生在IO monad中的事情。 方向只是North | South | East | West一个总和类型 North | South | East | West

其中大部分无疑会涉及一个捕获的GameState

  • 玩家在世界上的位置
  • 他们的库存内容
  • 物品所在的位置。 物品可能位于玩家的库存中,也可能处于空闲状态。 还没有通过组合项目来创建项目,或者在组合项目时被删除。
  • 我的问题是

  • 代表GameState数据结构是什么? 这样的结构应该包含玩家的位置和库存内容,以及在世界上可以找到的物品。 它应该像API一样提供API
  • moveTo :: GameState -> Direction -> ([MoveResult], GameState) ,其中MoveResultEnteredLocationNoLocationAt 。 这又需要一个像locationAt :: Location -> Direction -> Maybe Location这样的函数
  • pickUp :: GameState -> ItemName -> ([MoveResult], GameState) ,其中MoveResultPickedUpItemNoSuchItem 。 在这种情况下,如何将ItemNameItem匹配
  • useItemWithItem :: GameState -> (ItemName, ItemName) -> ([MoveResult], GameState) ,其中MoveResultPickedUpItem如果有新项目结果),否则为CantUserItems 。 这又需要像combineItems :: Item -> Item -> Maybe Item这样的函数来查看是否可以组合项目。
  • 什么是一个很好的数据结构来表示PlayerPosition
  • 我应该使用沉重的Location类型还是引入一些LocationId来表示PlayerPosition和潜在的项目位置
  • 对于图形映射原点Location到目的地Location经由Direction边缘,什么是最好的数据结构来使用。 我在想(Location, Direction)LocationData.Map
  • 我知道拉链,以及playMove适合State monad的事实。 我的问题是如何构建GameState来捕获这个问题的可变和不可变的部分。


    编辑:答案

    我确实从Reddit上的这个富有成效的讨论中找到了答案。 如果其他人发现这个问题,那么在讨论中/ u / achadoseperdidos指出我的问题的答案由Learn PureScript by Example的第11章提供,它实际上描述了如何使用RWS monad写一个冒险游戏 - 我正在寻找答案。


    在这种规模下,您无需担心规模或效率。 只需使用如下记录:

    import qualified Data.Map as M
    
    data Location = Location
      { locationname :: String
      , description :: String
      } deriving Ord
    
    data GameStep = GameStep
      { itemsWorld :: M.Map Location [Item]
      , inventory :: [Item]
      , position :: Location
      }
    
    链接地址: http://www.djcxy.com/p/58769.html

    上一篇: How to represent and track mutable state in a text

    下一篇: STM with fclabels