小组¶
你可以在多人游戏中将玩家分为多个小组。(如果你只是需要实验意义上的分组,组内玩家并不真的产生交互,那么参考 实验组。)
要设置每组的人数,前往Constants并设置 PLAYERS_PER_GROUP
变量即可。举例来说,对于2人游戏,设置 PLAYERS_PER_GROUP = 2
。
如果所有玩家均在同一组内,或者这是一个单人游戏,将其设为 None
:
每名玩家均有一个 id_in_group
属性,这一属性告诉你这是玩家 1
,玩家 2
,诸如此类。
获得玩家¶
小组对象有下面这些方法:
get_players()¶
返回组内玩家的列表(按照 id_in_group
排序)。
get_player_by_id(n)¶
返回组内具有所指定 id_in_group
的玩家。
获得其他玩家¶
玩家对象有 get_others_in_group()
与 get_others_in_subsession()
方法,分别返回同一小组与子会话中的 其他 玩家的列表。
角色¶
如果每一组中均有多种角色,如买家/卖家,委托人/代理人,诸如此类,你可以将它们定义在常量中。变量名以 _ROLE
结尾:
class C(BaseConstants):
...
PRINCIPAL_ROLE = 'Principal'
AGENT_ROLE = 'Agent
oTree会自动将每一个角色分配给不同的玩家(按照 id_in_group
循序分配)。你可以通过这一点来展示给不同角色不同内容,例如:
class AgentPage(Page):
@staticmethod
def is_displayed(player):
return player.role == C.AGENT_ROLE
在模板中:
You are the {{ player.role }}.
你也可以使用 group.get_player_by_role()
,它类似于 get_player_by_id()
:
def set_payoffs(group):
principal = group.get_player_by_role(C.PRINCIPAL_ROLE)
agent = group.get_player_by_role(C.AGENT_ROLE)
# ...
如果你想要转换玩家的角色,你应当重新分配小组,使用 group.set_players()
,subsession.group_randomly()
等等。
小组配对¶
固定配对¶
默认情况下,每一轮中,玩家被分为数个小组,每组人数为 C.PLAYERS_PER_GROUP
。分组是按照顺序进行的——举例来说,如果2人一组,那么玩家1与玩家2就会被分为一组,然后是玩家3与玩家4被分为一组,以此类推。 id_in_group
也在每组中被顺序分配。
这意味着默认情况下,每一轮中分组是相同的,甚至在不同应用之间均有相同的 PLAYERS_PER_GROUP
。
如果你想重新安排小组,你可以使用下面的技巧。
group_randomly()¶
子会话有一个 group_randomly()
方法可以随机排列玩家,此时玩家被随机分配在任一小组的任一位置。
如果你想要在不同小组间随机安排玩家但保持玩家的角色不变,使用 group_randomly(fixed_id_in_group=True)
。
举例来说,下面的代码会使玩家在每一轮之间随机组队:
def creating_session(subsession):
subsession.group_randomly()
下面的代码让玩家在每一轮之间随机组队,但是保持 id_in_group
不变:
def creating_session(subsession):
subsession.group_randomly(fixed_id_in_group=True)
下面的例子中,假定 PLAYERS_PER_GROUP = 3
,并且会话中共有12名参与者:
def creating_session(subsession):
print(subsession.get_group_matrix()) # outputs the following:
# [[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9],
# [10, 11, 12]]
subsession.group_randomly(fixed_id_in_group=True)
print(subsession.get_group_matrix()) # outputs the following:
# [[1, 8, 12],
# [10, 5, 3],
# [4, 2, 6],
# [7, 11, 9]]
subsession.group_randomly()
print(subsession.get_group_matrix()) # outputs the following:
# [[8, 10, 3],
# [4, 11, 2],
# [9, 1, 6],
# [12, 5, 7]]
group_like_round()¶
在不同轮之间复制小组的结构,可使用 group_like_round(n)
方法。方法中的参数即小组结构被复制的那一轮的轮次。
在下面的例子中,第一轮将随机组队,后面的轮次均复制第一轮的小组结构。
def creating_session(subsession):
if subsession.round_number == 1:
# <some shuffling code here>
else:
subsession.group_like_round(1)
get_group_matrix()¶
子会话有一个方法 get_group_matrix()
,此方法返回小组的结构,以矩阵的形式,例如:
[[1, 3, 5],
[7, 9, 11],
[2, 4, 6],
[8, 10, 12]]
set_group_matrix()¶
set_group_matrix()
让你可以任意改变小组结构。首先使用 get_players()
获得玩家的列表,或者使用 get_group_matrix()
获得已经存在的小组矩阵。构建你想要的矩阵并将其传给 set_group_matrix()
:
def creating_session(subsession):
matrix = subsession.get_group_matrix()
for row in matrix:
row.reverse()
# now the 'matrix' variable looks like this,
# but it hasn't been saved yet!
# [[3, 2, 1],
# [6, 5, 4],
# [9, 8, 7],
# [12, 11, 10]]
# save it
subsession.set_group_matrix(matrix)
你也可以传递一个整数矩阵。整数矩阵中必须包含从1到子会话中的玩家数量的所有整数。每一个整数代表 id_in_subsession
为此整数的玩家。举例如下:
def creating_session(subsession):
new_structure = [[1,3,5], [7,9,11], [2,4,6], [8,10,12]]
subsession.set_group_matrix(new_structure)
print(subsession.get_group_matrix()) # will output this:
# [[1, 3, 5],
# [7, 9, 11],
# [2, 4, 6],
# [8, 10, 12]]
为了检查小组重排是否工作正常,打开浏览器并切换到你的会话的”Results”选项卡,并检查每一轮中的 group
与 id_in_group
两栏是否正确。
group.set_players()¶
此函数类似与 set_group_matrix
,但它仅仅重新排列小组中的玩家,例如你可以使用它来分配给玩家不同的角色。
在会话中重排小组¶
creating_session
通常是重排小组的好地方,但是 creating_session
是在会话创建前运行,即玩家开始行动之前。所以如果你的重排逻辑需要依赖于会话开始后的因素,你应当在等待页面重排。
你需要创建一个 WaitPage
且在其中设定 wait_for_all_groups=True
并将重排的代码放入 after_all_players_arrive
中:
class ShuffleWaitPage(WaitPage):
wait_for_all_groups = True
@staticmethod
def after_all_players_arrive(subsession):
subsession.group_randomly()
# etc...