好吧,我想我可以提供我的答案,这可能更多的是一种意见,而不是明确的“这样做”(我没有接受过任何正式的编程培训)。
我觉得你agent_locations
应该是每个的成员World
实例。
我尝试主要从界面角度进行思考。在我看来,世界级应该负责管理你的世界的资源,在本例中是空间。自从World
是空间经理,代理商应该询问他们的world如果空间可用(即未占用),则彼此不存在。因此,我认为你的self.location_is_good
更合适的称呼是self.world.is_location_available(x, y)
[1]
这使得世界很自然地负责查找给定空间的可用性。世界级还可能有其他变量来决定空间是否可用。如果那里有灌木丛怎么办?或者其他的东西。您可能已经有某种桌子可供您使用(x, y)
每个世界的坐标。 “被占用”可以是这些对象的属性。
此外:你的世界已经知道每个代理的状态(通过[(agent.x, agent.y) for agent in self.agents]
[2])。这agent_locations
dict 本质上是这些属性的索引或缓存,因此属于World
.
关于将状态送回的痛苦World
...好吧,你不会通过以下方式解决这个问题Agent
而是这样做。但做update_agent_location(self, agent, x, y)
是完全多余的,因为x == agent.x; y == agent.y
(如果你颠倒你调用它的行)。你可以在 World 中简单地使用一种方法,update_agent_state(self, agent)
,World 可以使用它来更新其索引。您甚至可以提交一个额外的参数来描述状态更改的类型(如果您不想每次都更新所有属性)。
class World(object):
# ...
def update_agent_state(self, agent, state_change=None):
# Update properties based on what changed, or
# drop state_change param and update everything everytime
if state_change == Agent.LOCATION_CHANGE:
self.agent_locations[agent.x, agent.y] = agent
elif state_change == Agent.WHATEVER:
pass
class Agent(object):
LOCATION_CHANGE = 1
def update(self):
for x, y in self.valid_locations():
if not self.can_move_to(x, y)
continue
self.move(x, y)
def can_move_to(self, x, y):
"""Determines if x, y is a location where we can move."""
if not self.world.is_location_available(x, y):
return False
if not self.has_money_to_travel_to(x, y):
return False
return True
def move(self, x, y):
"""Moves to x, y and notifies world of state change."""
self.x = x
self.y = y
self.world.update_agent_state(self, Agent.LOCATION_CHANGE)
类似的东西(阅读我的脚注)。
[1] 当然,除非空间是自由的,否则位置的“好坏”取决于其他变量。例如。如果您只应搬到 (x, y),如果 1) 该位置可用并且 2) 代理有 1000 美元支付机票,那么您应该有Agent.can_move_to(x, y)
它反过来调用世界的方法,并检查它的钱包。
[2] 我假设你的self.agents = {}
是一个错字,因为你不能append
在字典上。你的意思是一个列表([]
) 正确的?