花火¶

此环境是经典环境的一部分。请先阅读该页面以获取一般信息。
导入 |
|
---|---|
动作 |
离散 |
并行 API |
是 |
手动控制 |
否 |
智能体 |
|
智能体 |
2 |
动作形状 |
Discrete(20) |
动作值 |
Discrete(20) |
观察形状 |
(658,) |
观察值 |
[0,1] |
花火(Hanabi)是一个2-5人的合作游戏,玩家需要协同合作,组成不同颜色的烟花。烟花是一组同色、从1到5按顺序排列的牌。游戏中的牌既有颜色也有数字;每个玩家可以看到其他玩家手中的牌,但看不到自己的牌。玩家不能直接互相交流,而是必须移除一个信息标记来提供信息。玩家可以告诉其他玩家其手中的牌是特定颜色或特定数字。游戏开始时有8个信息标记,玩家可以通过弃掉手中的牌来返还一个信息标记到场上。玩家也可以打出手中的牌:这张牌必须要么开启一个新的烟花,要么按顺序追加到现有的烟花上。但是,两组烟花不能有相同的颜色,并且同一组烟花不能重复数字。如果打出的牌不满足这些条件,则会放置一个生命标记。当放置了3个生命标记、所有5组烟花都已完成或牌堆中的所有牌都已抽完时,游戏结束。得分基于每组已完成烟花中最大牌面的数值。
环境参数¶
花火接受多个参数来定义游戏的大小和复杂度。默认为完整的2人花火游戏。
hanabi_v5.env(colors=5, ranks=5, players=2, hand_size=5, max_information_tokens=8,
max_life_tokens=3, observation_type='minimal')
colors
: 牌可以具有的颜色数量(影响牌堆大小)
ranks
: 牌可以具有的数字数量(影响牌堆大小)
hand_size
: 玩家手牌大小。标准游戏为 (玩家数 >= 4 时为 4,否则为 5)
max_information_tokens
: 信息标记的最大数量(标记越多,可以透露的信息越多,游戏越容易)
max_life_tokens
: 生命标记的最大数量(标记越多,可以容忍的错误越多,游戏越容易)
observation_type
: “minimal”:最小观察(人类玩家所见)。“card_knowledge”:包含对过去提示的每张牌的了解,以及简单的推断知识,形式为“这张牌不是红色,因为之前没有被提示为红色”。“seer”:显示所有牌,包括玩家自己的牌,无论是否给出过提示。
观察空间¶
观察是一个字典,其中包含一个'observation'
元素,即下方描述的通常的强化学习观察,以及一个'action_mask'
元素,用于保存合法动作,如合法动作掩码部分所述。
智能体的主要观察空间是一个大小为 658 的向量,代表剩余的生命和信息标记、当前构建的烟花、所有其他智能体的手牌、当前牌堆大小以及弃牌堆。观察向量包含以下特征:生命标记、信息标记、玩家数量、牌堆大小、已组成的烟花、合法动作、观察到的手牌、弃牌堆、从其他玩家那里收到的提示,这些特征被序列化为一个比特串。
每张牌都用一个 25 位独热向量编码,其中牌的编码等于其颜色*T + 数字,T 是最大可能的数字。默认情况下,此值为 5。最大牌堆大小为 50。剩余牌堆大小用一元编码表示。每种颜色烟花的状态用独热编码表示。剩余信息标记用一元编码表示。剩余生命标记用一元编码表示。弃牌堆用弃牌的数字的热力图编码表示。也就是说,最低有效位设为 1 表示该颜色中数字最小的牌已被弃掉。
当玩家透露有关他们牌的信息时,每张牌透露的信息也会被观察到。前 25 位表示该特定牌是否可能是特定颜色。例如,如果牌只能是红色,则观察到的透露信息的前 25 位将是 11111,后跟 20 个零。接下来的 5 位存储该牌的颜色是否被明确透露,因此如果牌被透露为红色,则接下来的 5 位将是 10000。最后 5 位是该牌被透露的数字。因此,如果牌被透露为数字 1,则接下来的 5 位将是 10000。这些 25 位信息会针对每个玩家手上的所有牌进行跟踪和观察。
索引 |
描述 |
值 |
---|---|---|
0 - 24 |
其他玩家手牌中卡牌 1 的向量 |
[0, 1] |
25 - 49 |
其他玩家手牌中卡牌 2 的向量 |
[0, 1] |
50 - 74 |
其他玩家手牌中卡牌 3 的向量 |
[0, 1] |
75 -100 |
其他玩家手牌中卡牌 4 的向量 |
[0, 1] |
100-124 |
其他玩家手牌中卡牌 5 的向量 |
[0, 1] |
125-174 |
剩余牌堆大小的一元编码 |
[0, 1] |
175-179 |
红色烟花的向量 |
[0, 1] |
180-184 |
黄色烟花的向量 |
[0, 1] |
185-189 |
绿色烟花的向量 |
[0, 1] |
190-195 |
白色烟花的向量 |
[0, 1] |
195-199 |
蓝色烟花的向量 |
[0, 1] |
200-207 |
剩余信息标记的一元编码 |
[0, 1] |
208-210 |
剩余生命标记的一元编码 |
[0, 1] |
211-260 |
弃牌堆的热力图编码 |
[0, 1] |
261-262 |
上一玩家 ID 的独热编码 |
[0, 1] |
263-266 |
上一玩家动作类型的向量 |
[0, 1] |
267-268 |
上一动作目标的向量 |
[0, 1] |
269-273 |
上一动作中透露颜色的向量 |
[0, 1] |
274-278 |
上一动作中透露数字的向量 |
[0, 1] |
279-280 |
手牌中哪些牌被透露的向量 |
[0, 1] |
281-282 |
打出或弃掉的牌的位置 |
[0, 1] |
283-307 |
代表上一张打出的牌的向量 |
[0, 1] |
308-342 |
本玩家第 0 张牌的透露信息 |
[0, 1] |
343-377 |
本玩家第 1 张牌的透露信息 |
[0, 1] |
378-412 |
本玩家第 2 张牌的透露信息 |
[0, 1] |
413-447 |
本玩家第 3 张牌的透露信息 |
[0, 1] |
445-482 |
本玩家第 4 张牌的透露信息 |
[0, 1] |
483-517 |
其他玩家第 0 张牌的透露信息 |
[0, 1] |
518-552 |
其他玩家第 1 张牌的透露信息 |
[0, 1] |
553-587 |
其他玩家第 2 张牌的透露信息 |
[0, 1] |
588-622 |
其他玩家第 3 张牌的透露信息 |
[0, 1] |
663-657 |
其他玩家第 4 张牌的透露信息 |
[0, 1] |
合法动作掩码¶
当前智能体可用的合法动作位于字典观察的action_mask
元素中。action_mask
是一个二进制向量,向量的每个索引代表该动作是否合法。对于除了轮到行动的智能体之外的任何智能体,action_mask
将全为零。执行非法动作会结束游戏,执行非法动作的智能体获得 -1 的奖励,所有其他智能体获得 0 的奖励。
动作空间¶
动作空间是一个标量值,范围从 0 到最大动作数。这些值代表玩家可以执行的所有可能动作,无论是否合法。环境中的每个可能动作都映射到一个 UUID,范围从 0 到最大动作数。默认情况下,最大动作数为 20。第一组动作是弃掉智能体手中的牌。如果玩家手中有 k 张牌,则前 k 个动作值是弃掉其中一张牌。接下来的 k 个动作是打出玩家手中的一张牌。最后,剩余的动作是透露其他玩家手牌中的颜色或数字。第一组透露动作是按顺序透露下一位玩家所有牌的颜色或数字,并为环境中所有其他玩家重复此过程。
动作 ID |
动作 |
---|---|
0 |
弃掉位置 0 的牌 |
1 |
弃掉位置 1 的牌 |
2 |
弃掉位置 2 的牌 |
3 |
弃掉位置 3 的牌 |
4 |
弃掉位置 4 的牌 |
5 |
打出位置 0 的牌 |
6 |
打出位置 1 的牌 |
7 |
打出位置 2 的牌 |
8 |
打出位置 3 的牌 |
9 |
打出位置 4 的牌 |
10 |
透露玩家 1 的红色牌 |
11 |
透露玩家 1 的黄色牌 |
12 |
透露玩家 1 的绿色牌 |
13 |
透露玩家 1 的白色牌 |
14 |
透露玩家 1 的蓝色牌 |
15 |
透露玩家 1 的数字 1 牌 |
16 |
透露玩家 1 的数字 2 牌 |
17 |
透露玩家 1 的数字 3 牌 |
18 |
透露玩家 1 的数字 4 牌 |
19 |
透露玩家 1 的数字 5 牌 |
奖励¶
每一步的奖励计算为相对于上一步的游戏得分变化。游戏得分计算为每组已构建烟花中数值的总和。如果游戏失败,得分设为零,因此最终奖励将是目前为止收到所有奖励的负值。
例如,如果烟花按以下方式创建
蓝色 1, 蓝色 2, 红色 1, 绿色 1, 绿色 2, 绿色 3
游戏结束时,总得分为 2 + 1 + 3 = 6
如果执行了非法动作,游戏终止,执行非法动作的玩家失败。与普通失败一样,他们的最终奖励将是目前为止收到所有奖励的负值。其他玩家的奖励不受非法动作的影响。
版本历史¶
v5:为未来兼容性将环境切换到依赖 OpenSpiel(使用 Shimmy)(1.23.0)
v4:修复了任意调用 observe() 的错误 (1.8.0)
v3:观察中的合法动作掩码取代了 infos 中的非法动作列表 (1.5.0)
v2:修复了默认参数 (1.4.2)
v1:由于采用了新的智能体迭代方案,即所有智能体完成后才进行迭代,因此提高了所有环境的版本 (1.4.0)
v0:初始版本发布 (1.0.0)
用法¶
AEC¶
from pettingzoo.classic import hanabi_v5
env = hanabi_v5.env(render_mode="human")
env.reset(seed=42)
for agent in env.agent_iter():
observation, reward, termination, truncation, info = env.last()
if termination or truncation:
action = None
else:
mask = observation["action_mask"]
# this is where you would insert your policy
action = env.action_space(agent).sample(mask)
env.step(action)
env.close()
API¶
- class pettingzoo.classic.hanabi.hanabi.raw_env(colors: int = 5, ranks: int = 5, players: int = 2, hand_size: int = 5, max_information_tokens: int = 8, max_life_tokens: int = 3, observation_type: str = 'card_knowledge', random_start_player: bool = False, render_mode: str | None = None)[source]¶
初始化
raw_env
类。- 参数说明
colors: int, 颜色数量,范围 [2,5]。
ranks: int, 数字数量,范围 [2,5]。
players: int, 玩家数量,范围 [2,5]。
hand_size: int, 手牌大小,范围 [2,5]。
max_information_tokens: int, 信息标记数量 (>=0)。
max_life_tokens: int, 生命标记数量 (>=1)。
- observation_type: str。
“minimal”:最小观察。“card_knowledge”:一阶共同知识观察。“seer”:所有牌的完整信息。
random_start_player: bool, 布尔值,随机开始玩家。
- 常见游戏配置
- Hanabi-Full (默认){
“colors”: 5, “ranks”: 5, “players”: 2, “max_information_tokens”: 8, “max_life_tokens”: 3, “hand_size”: (玩家数 >= 4 时为 4,否则为 5) “observation_type”: “card_knowledge”, “hand_size”: 2, }
- Hanabi-Small{
“colors”: 2, “ranks”: 5, “players”: 2, “max_information_tokens”: 3, “hand_size”: 2, “max_life_tokens”: 1, “observation_type”: “card_knowledge”, }
- Hanabi-Very-Small{
“colors”: 1, “ranks”: 5, “players”: 2, “max_information_tokens”: 3, “hand_size”: 2, “max_life_tokens”: 1, “observation_type”: “card_knowledge”, }
- observation_space(agent)[source]¶
接收智能体并返回该智能体的观察空间。
对于同一个智能体名称,必须返回相同的值
默认实现是返回
observation_spaces
字典