如何在文本中表示和跟踪可变状态
这个问题是关于如何设计一个应用程序和布局数据,以在冒险游戏中表示可变状态,其中存在玩家可以进入的位置以及可以在这些位置或者在他们选择之后在玩家库存中的物品他们了。
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)
Move
和MoveResult
函数在哪里
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)
,其中MoveResult
是EnteredLocation
或NoLocationAt
。 这又需要一个像locationAt :: Location -> Direction -> Maybe Location
这样的函数 pickUp :: GameState -> ItemName -> ([MoveResult], GameState)
,其中MoveResult
是PickedUpItem
或NoSuchItem
。 在这种情况下,如何将ItemName
与Item
匹配 useItemWithItem :: GameState -> (ItemName, ItemName) -> ([MoveResult], GameState)
,其中MoveResult
是PickedUpItem
如果有新项目结果),否则为CantUserItems
。 这又需要像combineItems :: Item -> Item -> Maybe Item
这样的函数来查看是否可以组合项目。 PlayerPosition
Location
类型还是引入一些LocationId来表示PlayerPosition
和潜在的项目位置 Location
到目的地Location
经由Direction
边缘,什么是最好的数据结构来使用。 我在想(Location, Direction)
到Location
的Data.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