小组

你可以在多人游戏中将玩家分为多个小组。(如果你只是需要实验意义上的分组,组内玩家并不真的产生交互,那么参考 实验组。)

要设置每组的人数,前往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”选项卡,并检查每一轮中的 groupid_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...

按照到达时间组队

参考 group_by_arrival_time