functions/actors 处理 WorldState 中的鸡或蛋
Chicken or egg in functions/actors processing WorldState
我看过系列"Purely Functional Retrogames"
http://prog21.dadgum.com/23.html
它讨论了一些有趣的技术来构建(半)纯游戏世界更新循环。
但是,我有以下附带说明,我似乎无法理解:
假设你有一个系统,其中每个敌人和每个玩家都是独立的参与者,或者独立的纯函数。
假设他们都得到一个 "WorldState" 作为输入,并输出一个新的 WorldState(或者,如果你从演员的角度考虑,将新的 WorldState 发送给下一个演员,例如以 "Game Render"演员).
那么,有两种方法可以解决这个问题:
要么你从一个演员开始,(f.i。玩家),然后喂他 "current world"。
然后,你将新世界喂给下一个敌人,依此类推,直到所有参与者都转换了世界。然后,最后一个世界就是您可以提供给渲染循环的新世界。 (或者,如果您按照上面的文章进行操作,您最终会得到一个世界上发生的事件列表,可以对其进行处理)。
第二种方法是同时为所有参与者提供当前的 WorldState。它们会产生任何可能发生冲突的变化(例如,两个敌人和玩家可以在同一动画帧中拿硬币)-> 由游戏系统通过处理事件来解决这些冲突。通过处理所有事件,游戏参与者创建新世界,用于下一个更新帧。
我有一种感觉,我只是遇到了完全相同的 "race condition" 问题,我希望通过使用具有不可变数据的纯函数来避免这种情况。
这里有什么建议吗?
我没读过这篇文章,但是在硬币示例中,您正在创建一种全局变量:您将世界状态的副本提供给所有参与者,并且您假设每个参与者都会评估游戏,取决定并期望他们的行动会成功,而不管最后阶段是解决冲突。我不会将此称为竞争条件,而是 "blind condition",是的,这不会起作用。
我想你是为了允许并行性而来到这个解决方案,这在解决方案 1 中是不可用的。在我看来,问题是关于责任的。
硬币必须属于一个参与者(充当资源管理器的服务器),就像应用程序中的任何东西一样。这个演员是唯一负责决定硬币会发生什么的人。
所有请求(是否有东西要抓取、抓住它、放下东西...)都应该发送给这个演员(每个单元格、每个地图、关卡或任何对游戏有意义的拆分一个演员) .
然后您将如何管理它取决于您:按接收顺序处理所有请求,缓冲它们直到同步消息到来,然后做出随机决定或优先级决定...无论如何,服务器将是能够在没有任何竞争条件风险的情况下回复所有参与者成功或失败,因为服务器进程 运行(至少在 erlang 中)在单个核心上并且一次处理一条消息。
除了 Pascal 答案之外,您还可以通过将(我假设是巨大的映射)拆分为更小的块来解决并行化问题,这些块取决于其邻居的最后状态(或其一部分,如边缘)。这允许您在许多节点之间分发这个游戏。
我看过系列"Purely Functional Retrogames"
http://prog21.dadgum.com/23.html
它讨论了一些有趣的技术来构建(半)纯游戏世界更新循环。
但是,我有以下附带说明,我似乎无法理解:
假设你有一个系统,其中每个敌人和每个玩家都是独立的参与者,或者独立的纯函数。
假设他们都得到一个 "WorldState" 作为输入,并输出一个新的 WorldState(或者,如果你从演员的角度考虑,将新的 WorldState 发送给下一个演员,例如以 "Game Render"演员).
那么,有两种方法可以解决这个问题:
要么你从一个演员开始,(f.i。玩家),然后喂他 "current world"。 然后,你将新世界喂给下一个敌人,依此类推,直到所有参与者都转换了世界。然后,最后一个世界就是您可以提供给渲染循环的新世界。 (或者,如果您按照上面的文章进行操作,您最终会得到一个世界上发生的事件列表,可以对其进行处理)。
第二种方法是同时为所有参与者提供当前的 WorldState。它们会产生任何可能发生冲突的变化(例如,两个敌人和玩家可以在同一动画帧中拿硬币)-> 由游戏系统通过处理事件来解决这些冲突。通过处理所有事件,游戏参与者创建新世界,用于下一个更新帧。
我有一种感觉,我只是遇到了完全相同的 "race condition" 问题,我希望通过使用具有不可变数据的纯函数来避免这种情况。
这里有什么建议吗?
我没读过这篇文章,但是在硬币示例中,您正在创建一种全局变量:您将世界状态的副本提供给所有参与者,并且您假设每个参与者都会评估游戏,取决定并期望他们的行动会成功,而不管最后阶段是解决冲突。我不会将此称为竞争条件,而是 "blind condition",是的,这不会起作用。
我想你是为了允许并行性而来到这个解决方案,这在解决方案 1 中是不可用的。在我看来,问题是关于责任的。
硬币必须属于一个参与者(充当资源管理器的服务器),就像应用程序中的任何东西一样。这个演员是唯一负责决定硬币会发生什么的人。
所有请求(是否有东西要抓取、抓住它、放下东西...)都应该发送给这个演员(每个单元格、每个地图、关卡或任何对游戏有意义的拆分一个演员) .
然后您将如何管理它取决于您:按接收顺序处理所有请求,缓冲它们直到同步消息到来,然后做出随机决定或优先级决定...无论如何,服务器将是能够在没有任何竞争条件风险的情况下回复所有参与者成功或失败,因为服务器进程 运行(至少在 erlang 中)在单个核心上并且一次处理一条消息。
除了 Pascal 答案之外,您还可以通过将(我假设是巨大的映射)拆分为更小的块来解决并行化问题,这些块取决于其邻居的最后状态(或其一部分,如边缘)。这允许您在许多节点之间分发这个游戏。