oTree学习教程(六)Multiplayer games

oTree的群组系统允许您将玩家分成小组并让玩家与同一组中的其他玩家互动。这通常用于多人游戏。(如果您只需要“治疗组”意义上的团体,其中玩家实际上并不相互交流,那么请参阅处理。)

要设置组大小,请转到应用的models.py并进行设置 Constants.players_per_group。例如,对于2人游戏:

如果所有玩家都在同一组中,或者如果是单人游戏,请将其设置为None

在这种情况下,self.group.get_players()将返回每个人的subsession。

每个玩家都有一个属性id_in_group,告诉你它是玩家1,玩家2等。

获得玩家

组对象具有以下方法:

get_players()

返回组中的玩家列表(按排序id_in_group)。

get_player_by_id(n)

返回给定组中的玩家id_in_group

get_player_by_role(r)

返回具有给定角色的玩家。如果使用此方法,则必须定义角色方法。例如:

获得其他玩家

Player对象具有get_others_in_group()和get_others_in_subsession()方法,这些方法返回组和子会话中其他玩家的列表。 例如,对于2人组,您可以获得玩家的合作伙伴:

组匹配

固定匹配

默认情况下,在每轮中,玩家被分成几组Constants.players_per_group。它们按顺序分组 - 例如,如果每组有2个玩家,则P1和P2将组合在一起,P3和P4也是如此,依此类推。id_in_group也在每个组中按顺序分配。

这意味着默认情况下,每组中的组都相同,甚至在具有相同的应用程序之间也是如此players_per_group

如果要重新排列组,可以使用以下技巧。

group_randomly()

子会话有一种group_randomly()随机分配玩家的方法,因此他们可以在任何组中以及组内的任何位置结束。

如果你想在小组之间洗牌,但让玩家保持固定角色,请使用group_randomly(fixed_id_in_group=True)

例如,这将每轮随机分组玩家:

这将每轮随机分组玩家,但保持id_in_group固定:

下面的示例使用命令行创建一个包含12个玩家的公共产品游戏,然后进行交互式组改组。假设,12人游戏将有4组:otree shellplayers_per_group = 3

 

请注意,在每轮中,玩家最初按固定匹配中的描述顺序分组,即使您在前一轮中进行了一些改组。要抵消这种情况,可以使用group_like_round()

group_like_round()

要将组结构从一轮复制到另一轮,请使用该group_like_round(n)方法。此方法的参数是应该复制组结构的整数。

在下面的示例中,组在第1轮中进行混洗,然后后续轮次复制第1轮的分组结构。

get_group_matrix()

子会话有一个方法get_group_matrix(),它将组的结构作为矩阵返回,即列表列表,每个子列表是一个组中的队列,按顺序排列id_in_group

以下几行是等效的。

set_group_matrix()允许您以任何方式修改组结构。 首先,使用get_players()获取玩家列表,或使用get_group_matrix()获取预先存在的组矩阵。 使用Python列表操作构建矩阵,如.extend(),. append(),. pop(),. relverse(),以及列表索引和切片(例如[0],[2:4])。 然后将此修改后的矩阵传递给set_group_matrix():

以下是在creation_session中的外观:

您还可以传递整数矩阵。它必须包含从1到subsession中的玩家数量的所有整数。每个整数代表具有该值的玩家id_in_subsession。例如:

您甚至可以set_group_matrix用来制作不均匀尺寸的组。

要检查您的组改组是否正常工作,请将浏览器打开到会话的“结果”选项卡,然后查看每轮中的groupid_in_group列。

group.set_players()

如果您只想重新排列组中的玩家,您可以使用该方法group.set_players()作为参数,按顺序分配给该组的玩家列表。

例如,如果您希望将玩家重新分配到相同的组但是在其组内随机改变角色(例如,因此玩家1将成为玩家2或保持玩家1),您将执行以下操作:

示例:将玩家分配给角色

假设你想根据一些外部标准(如性别)将玩家分配到角色。

此示例显示如何制作3个玩家的组,其中玩家1是男性,玩家2和3是女性。该示例假定您已经设置participant.vars['gender'] 了每个参与者(例如,在之前的应用程序中),并且女性玩家的数量是男性玩家的两倍。

creating_session通常是一个改组的好地方,但请记住,在创建会话之前,在玩家开始游戏之前运行creation_session。 因此,如果您的洗牌逻辑需要依赖会话开始后发生的事情,那么您应该在等待页面中进行洗牌。

假设您已在Subsession类上定义了一个名为do_my_shuffle()的方法,该方法使用set_group_matrix等。

您需要使用wait_for_all_groups = True创建WaitPage并将洗牌代码放在after_all_players_arrive中:

在此等待页面之后,玩家将被重新分配给他们的新组。

假设您有一个包含多轮的游戏,并且在开头的等待页面中您想要对组进行随机播放,并将这个新的组结构应用于所有轮次。 您可以将group_like_round()与in_rounds()一起使用。 您还应该使用is_displayed(),以便此方法仅执行一次。 例如:

到达时间分组

请参阅group_by_arrival_time

示例:可配置组大小

假设您希望每次创建会话时都能够配置每个组的玩家数量。(设置 类型是这样,但仅当所有玩家都在同一组中时。)Constants.players_per_group = None

配置会话中所述,在会话配置中创建一个密钥(您可以调用它players_per_group),然后使用此代码将玩家分成这个大小的组:

 

等待页面

当一个玩家需要等待其他人采取某些行动才能继续之前,等待页面是必要的。例如,在最后通game游戏中,玩家2在看到玩家1的提议之前不能接受或拒绝。

如果你WaitPage的页面序列中有一个,那么oTree会等到组中的所有玩家都到达序列中的那个点,然后允许所有玩家继续进行。

如果你的subsession有多个组同时演示,并且你想要一个等待所有组的等待页面(即subsession中的所有玩家),你可以在等待页面上设置wait_for_all_groups = True属性,例如:

有关组的更多信息,请参阅

等待页面可以定义以下方法:

after_all_players_arrive()

您在此处定义的任何代码都将在所有玩家到达等待页面后执行。例如,这是设置玩家收益或确定胜利者的好地方。

注意,你不能在after_all_players_arrive中引用self.player,因为代码对整个组执行一次,而不是对每个单独的玩家执行。 (但是,您可以在等待页面中使用self.player is_displayed。)

 

is_displayed()

与常规页面的工作方式相同。如果返回,False则玩家跳过等待页面。

如果组中的某些或所有玩家跳过等待页面,则after_all_players_arrive()可能无法运行。

group_by_arrival_time 

如果您在WaitPage上设置,则玩家将按照他们到达该等待页面的顺序进行分组:group_by_arrival_time = True

例如,如果players_per_group = 2,则到达等待页面的前2个玩家将被组合在一起,然后是接下来的2个玩家,依此类推。

这在某些参与者可能退出的会话中很有用(例如,在线实验,或允许参与者提前退出的同意页面的实验),或者某些参与者比其他参与者花费更长时间的会话。

使用group_by_arrival_time的典型方法是将其放在过滤掉参与者的应用之后。 例如,如果您的会话有一个同意页面,让参与者有机会选择退出研究,您可以制作一个仅包含同意页面的“同意”应用,然后使用['consent','my_game这样的app_sequence '],其中my_game使用group_by_arrival_time。 这意味着如果有人选择同意,他们将被排除在my_game中的分组之外。

如果游戏有多轮,您可能只想按第1轮的到达时间进行分组:

如果你这样做,那么后续轮次将保持与第1轮相同的组结构。否则,将在每轮中按照到达时间对玩家进行重新分组。 (group_by_arrival_time将组结构复制到未来轮次。)

笔记:

id_in_group不一定按照玩家到达页面的顺序分配。
group_by_arrival_time只能在等待页面是page_sequence中的第一页时使用
如果在具有group_by_arrival_time的页面上使用is_displayed,则它应仅基于轮数。 不要使用is_displayed向某些玩家显示该页面,而不是其他玩家。
如果group_by_arrival_time = True,则在creation_session中,所有玩家最初将在同一组中。 当玩家到达等待页面时,组仅“在运行中”创建。
如果您需要进一步控制将玩家安排到组中,请使用get_players_for_group()。

get_players_for_group()
如果您正在使用group_by_arrival_time并希望更好地控制将哪些玩家分配到一起,则可以使用get_players_for_group()。

假设除了按到达时间进行分组外,您还需要每组人员由1名男子和1名女子(或2名“A”队员和2名“B”队员等)组成。

如果您定义了一个名为get_players_for_group的方法,则只要新玩家到达等待页面,就会调用它。 该方法的参数是等待分组的玩家列表(不是已断开连接或关闭其浏览器的人)。 如果您选择其中一些玩家并将其作为列表返回,那么这些玩家将被分配到一个组,并向前移动。 如果您没有返回任何内容,则不会发生分组。

这是一个例子,每组有2个A球员,2个B球员。

防止玩家卡在等待页面上

一个常见的问题尤其是在线实验时,玩家会等待其组中的其他玩家辍学或太慢。

以下是您可以采取的一些措施来减少此问题:

使用group_by_arrival_time

如上所述,您可以使用,group_by_arrival_time以便只有在同一时间主动显示的玩家才能组合在一起。

group_by_arrival_time如果在“锁定”任务之后使用,则效果很好。换句话说,在您的多人游戏之前,您可以进行单人游戏任务。这个想法是参与者努力完成这个初始任务,他们不太可能在那之后辍学。

使用页面超时

在每个页面上使用timeout_seconds,这样如果播放器处于慢速或非活动状态,其页面将自动前进。或者,您可以通过单击管理界面中的“提前最慢参与者”按钮手动强制超时。

自定义等待页面的外观

您可以通过设置title_textbody_text属性来自定义等待页面上显示的文本,例如:

您还可以创建自定义等待页面模板。例如,将此保存为my_app/templates/my_app/MyWaitPage.html(此模板必须扩展'otree / WaitPage.html'):

然后告诉您的等待页面使用此模板:

然后你可以vars_for_template按照通常的方式使用。实际上,body_texttitle_text属性只是设置的简写vars_for_template; 以下2个代码段是等效的:

如果要全局应用自定义等待页面模板,请将其保存到_templates/global/WaitPage.html。然后,oTree将自动在任何地方使用它而不是内置的等待页面。

CSS和JavaScript在等待页面

等待页面具有相同的块结构,常规页面(global_scriptsapp_scriptsscripts,等...),这样你就可以按照所描述的相同的指令JavaScript和CSS 和自定义主题

例如,要将CSS应用于自定义等待页面_templates/global/WaitPage.html,请global_scripts在模板中放置一个块。

你甚至可以让其他自定义页面等待继承_templates/global/WaitPage.html,现在的样子常规页面继承_templates/global/Page.html,并且可以限定块app_scriptsscripts等。

 

聊天

您可以在页面中添加聊天室,以便参与者可以相互通信。

以前使用过该otreechat附加组件的人的注意事项:

2017年11月,otreechat附加组件合并为otree。 现在,您不再需要单独安装otreechat,并且您的模板中不需要{%load otreechat}。

用法

基本用法

无论您想在模板中使用聊天框,请使用:

这将在同一组中的玩家之间建立聊天室,其中每个玩家的昵称显示为“玩家1”,“玩家2”等(基于玩家的id_in_group)。

自定义昵称和聊天室成员

您可以传递可选参数channel和/或nickname像这样:

昵称

nickname是将在聊天中为该用户显示的昵称。典型的用法是。{% chat nickname=player.role %}

频道

channel是聊天室的名称,这意味着如果2个玩家拥有相同的名字channel,他们可以互相聊天。 channel没有显示在用户界面中; 它只是在内部使用。它的默认值是group.id,意味着组中的所有玩家可以一起聊天。您可以使用channel以将聊天范围扩展到组的当前页面或子分区等(请参阅下面的示例)。无论channel参数的价值如何,聊天至少应限定在同一会话和同一应用中的玩家。

示例:按角色聊天

这里有一个例子,我们在团队中基于角色进行沟通,而不是群体内的沟通,例如,所有买家可以互相交谈,所有卖家都可以互相交谈。

然后在模板中:

示例:跨轮次聊天

如果您需要玩家与当前处于不同轮次游戏中的玩家聊天,您可以:

示例:所有轮次中的所有组之间的聊天

如果您希望会话中的每个人都可以自由地互相聊天,那么只需:

(数字1并不重要;重要的是每个人都一样。)

造型

要自定义样式,只需在元素后面加入一些CSS ,例如:{% chat %}

您还可以通过将其置于<div> 父级内部并为其设置样式来自定义外观<div>。例如,要设置宽度:

页面上的多个聊天

您可以在每个页面上放置多个框,以便玩家可以同时处于多个通道中。{% chat %}

例如,此代码可以与组中的每个其他玩家进行1:1聊天。

导出聊天记录的

聊天记录下载链接将显示在oTree的常规数据导出页面上。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值