from otree.api import * import time doc = """ Patrick Sewell (modified a one-shot PD to have multiple repeated coordination games) """ class C(BaseConstants): NAME_IN_URL = 'pennies' PLAYERS_PER_GROUP = 2 KEEPER_ROLE = 'Keeper' STRIKER_ROLE = 'Striker' NUM_ROUNDS = 10 PAYOFF_A = 20 PAYOFF_B = -20 PAYOFF_C = 0 PAYOFF_D = 0 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): def role(self): if self.id_in_group == 1: return 'Keeper' if self.id_in_group == 2: return 'Striker' cooperate = models.BooleanField( choices=[[True, 'A'], [False, 'B']], doc="""This player's decision""", widget=widgets.RadioSelect, ) input_button = models.CharField() number = models.IntegerField() decision_time = models.IntegerField() game_payoff_Pennies = models.IntegerField() def record_decision_time(self): self.decision_time = int(time.time()) -self.participant.vars['start_time'] # records dt self.participant.vars['start_time'] = int(time.time()) # updates start_time def record_game_payoff(self): all_players = self.in_all_rounds() combined_payoff = 0 for temp_player in all_players: combined_payoff += temp_player.payoff self.participant.vars['game_payoff_Pennies'] = int(combined_payoff) self.game_payoff_Pennies = int(combined_payoff) # FUNCTIONS def set_payoffs(group: Group): # for p in group.get_players(): # set_payoff(p) keeper = group.get_player_by_id(1) striker = group.get_player_by_id(2) payoff_matrix_keeper = { (False, True): C.PAYOFF_B, (True, True): C.PAYOFF_A, (False, False): C.PAYOFF_A, (True, False): C.PAYOFF_B, } payoff_matrix_striker = { (False, True): C.PAYOFF_A, (True, True): C.PAYOFF_B, (False, False): C.PAYOFF_B, (True, False): C.PAYOFF_A, } keeper.payoff = payoff_matrix_keeper[(keeper.cooperate, striker.cooperate)] striker.payoff = payoff_matrix_striker[(keeper.cooperate, striker.cooperate)] def other_player(player: Player): return player.get_others_in_group()[0] # def set_payoff(player: Player): # payoff_matrix = { # (False, True): C.PAYOFF_A, # (True, True): C.PAYOFF_D, # (False, False): C.PAYOFF_D, # (True, False): C.PAYOFF_B, # } # other = other_player(player) # player.payoff = payoff_matrix[(player.cooperate, other.cooperate)] # PAGES class Game_Introduction(Page): def is_displayed(self): return self.round_number == 1 #timeout_seconds = 100 def before_next_page(player, timeout_happened): player.participant.vars['start_time'] = int(time.time()) def vars_for_template(player: Player): if player.role() == 'Striker': payoff_a = C.PAYOFF_A payoff_b = C.PAYOFF_B else: payoff_a = C.PAYOFF_B payoff_b = C.PAYOFF_A return { 'payoff_a': payoff_a, 'payoff_b': payoff_b} class Decision(Page): # def is_displayed(player: Player): # return player.role() == 'Striker' form_model = 'player' form_fields = ['cooperate'] # timeout_seconds = 30 def vars_for_template(player: Player): # specify info for progress bar total = C.NUM_ROUNDS page = player.subsession.round_number progress = page / total * 100 if player.role() == 'Striker': payoff_a = C.PAYOFF_A payoff_b = C.PAYOFF_B else: payoff_a = C.PAYOFF_B payoff_b = C.PAYOFF_A return { 'page': page, 'total': total, 'progress': progress, 'payoff_a': payoff_a, 'payoff_b': payoff_b} def before_next_page(player, timeout_happened): player.record_decision_time() player.record_game_payoff() player.game_payoff_Pennies = int(player.participant.vars['game_payoff_Pennies']) class ResultsWaitPage(WaitPage): after_all_players_arrive = set_payoffs class Results(Page): @staticmethod def vars_for_template(player: Player): opponent = other_player(player) if player.role() == 'Striker': payoff_a = C.PAYOFF_A payoff_b = C.PAYOFF_B else: payoff_a = C.PAYOFF_B payoff_b = C.PAYOFF_A return dict( opponent=opponent, same_choice=player.cooperate == opponent.cooperate, my_decision=player.field_display('cooperate'), opponent_decision=opponent.field_display('cooperate'), payoff_a=payoff_a, payoff_b=payoff_b, ) class Probabilities(Page): def is_displayed(self): return self.round_number != C.NUM_ROUNDS form_model = 'player' form_fields = ["number"] def vars_for_template(player: Player): if player.role() == 'Striker': payoff_a = C.PAYOFF_A payoff_b = C.PAYOFF_B else: payoff_a = C.PAYOFF_B payoff_b = C.PAYOFF_A return { 'payoff_a': payoff_a, 'payoff_b': payoff_b} class CombinedResults(Page): @staticmethod def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS @staticmethod def vars_for_template(player: Player): all_players = player.in_all_rounds() combined_payoff = 0 for temp_player in all_players: combined_payoff += temp_player.payoff return { "combined_payoff": combined_payoff } def before_next_page(player, timeout_happened): player.record_game_payoff() page_sequence = [Game_Introduction, Decision, ResultsWaitPage, Results, Probabilities, CombinedResults]