from otree.api import * import random doc = """ This is a one-shot "Prisoner's Dilemma". Two players are asked separately whether they want to cooperate or defect. Their choices directly determine the payoffs. """ class C(BaseConstants): NAME_IN_URL = 'prisoner' PLAYERS_PER_GROUP = 2 NUM_ROUNDS = 1 PAYOFF_A = cu(200) PAYOFF_B = cu(180) PAYOFF_C = cu(120) PAYOFF_D = cu(0) class Subsession(BaseSubsession): def creating_session(self): players = self.get_players() # Ensure there is an even number of players to form groups of 2 if len(players) % 2 != 0: raise ValueError("Number of players is not even. Cannot form groups of 2.") group_matrix = [] # Shuffle the list of players to randomize the groups random.shuffle(players) # Create two groups of two members each for i in range(0, len(players), C.PLAYERS_PER_GROUP): group_matrix.append(players[i:i + C.PLAYERS_PER_GROUP]) # Set the new group matrix self.set_group_matrix(group_matrix) # Assign a group ID to each player for identification for group in self.get_groups(): for player in group.get_players(): player.participant.vars['group_id'] = group.id class Group(BaseGroup): pass class Player(BasePlayer): payment = models.IntegerField(initial=100) is_bid_winner = models.BooleanField(initial=False) selected_bid = models.IntegerField(min=0, max=100) final_euro_amount = models.FloatField(initial=4.00) cooperate = models.BooleanField( choices=[[True, 'Cooperate'], [False, 'Defect']], doc="""This player's decision""", widget=widgets.RadioSelect, ) q1 = models.StringField( choices=[['True', 'True'], ['False', 'False']], label='Question 1: In the BDM mechanism, if my bid is lower than the randomly chosen price, I will still receive the advice but will not have to pay for it.', widget=widgets.RadioSelectHorizontal, ) q2 = models.StringField( choices=[['True', 'True'], ['False', 'False']], label='Question 2: In the Prisoner Dilemma game, if both players defect, they will receive a smaller punishment than if they both cooperate.', widget=widgets.RadioSelectHorizontal, ) q3 = models.StringField( choices=[['You get a small punishment, and the other gets a reward', 'You get a small punishment, and the other gets a reward'], ['Both get a moderate punishment','Both get a moderate punishment'], ['You get a heavy punishment, and the other gets a reward','You get a heavy punishment, and the other gets a reward'], ['Both get a small punishment','Both get a small punishment'],], label='Question 3: In the Prisoners Dilemma, what happens if you cooperate and the other participant defects?', ) q4 = models.StringField( choices=[['50 ECU', '50 ECU'], ['100 ECU', '100 ECU'], ['150 ECU', '150 ECU'], ['200 ECU', '200 ECU']], label='Question 4: What is the maximum amount you can bid for the advice in the BDM mechanism?', widget=widgets.RadioSelectHorizontal, ) bid = models.IntegerField(label='What is bid for the Advice?', min=0, max=100) educational_level = models.StringField( choices=[['Bachelors Degree', 'Bachelors Degree'], ['Masters Degree', 'Masters Degree'], ['Doctorate Degree', 'Doctorate Degree'], ['Other', 'Other'],], label='What is your current education program type?', ) age = models.IntegerField(label='What is your age?', min=13, max=125) gender = models.StringField( choices=[['Male', 'Male'], ['Female', 'Female'], ['Other', 'Other'], ['Prefer Not To Say', 'Prefer Not To Say']], label='What is your Gender?', ) knowledge = models.StringField( choices=[ ['1', 'Strongly disagree'], ['2', 'Disagree'], ['3', 'Neutral'], ['4', 'Agree'], ['5', 'Strongly agree'] ], label='I was well aware of the game and its rules before starting the experiment.', widget=widgets.RadioSelectHorizontal, ) influenced = models.StringField( choices=[ ['1', 'Strongly disagree'], ['2', 'Disagree'], ['3', 'Neutral'], ['4', 'Agree'], ['5', 'Strongly agree'] ], label='Without the advice, my decision would have probably been different. (Select Neutral, in case you did not get the advice)', widget=widgets.RadioSelectHorizontal, ) feedback = models.StringField( choices=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], label='How do you see yourself: are you generally a person who is fully prepared to take risks or do you try to avoid taking risks? Please tick a box on the scale, where the value 0 means “not at all willing to take risks” and the value 10 means “very willing to take risks”', widget=widgets.RadioSelectHorizontal, ) # FUNCTIONS def set_payoffs(group: Group): for p in group.get_players(): set_payoff(p) def decide_bid_winner(group: Group): players = group.get_players() the_selected_bid = random.randint(1, 100) for p in players: p.is_bid_winner = True if p.bid >= the_selected_bid else False p.selected_bid = the_selected_bid if p.is_bid_winner == True: p.payment -= the_selected_bid 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_B, (False, False): C.PAYOFF_C, (True, False): C.PAYOFF_D, } other = other_player(player) player.payoff = payoff_matrix[(player.cooperate, other.cooperate)] player.payment += int(player.payoff) player.final_euro_amount += (player.payment/100)*1.25 # PAGES class Introduction_p(Page): pass class Introduction_bdm(Page): @staticmethod def vars_for_template(player: Player): if player.id_in_group % 2 == 0: return {'custom_text': 'a human advice from an expert economics professor'} else: return {'custom_text': 'an AI advice generated by ChatGPT'} class Evaluation(Page): form_model = 'player' form_fields = ['q1','q2','q3','q4'] def error_message(self, values): # Custom validation logic goes here error_messages = [] # Check if answers are correct if values['q1'] != 'False': error_messages.append("Answer to Question 1 is incorrect.") if values['q2'] != 'True': error_messages.append("Answer to Question 2 is incorrect.") if values['q3'] != 'You get a heavy punishment, and the other gets a reward': error_messages.append("Answer to Question 3 is incorrect.") if values['q4'] != '100 ECU': error_messages.append("Answer to Question 4 is incorrect.") # Display retry warning if any answers are incorrect if error_messages: return '\n'.join(error_messages) class Bidding(Page): form_model = 'player' form_fields = ['bid'] @staticmethod def vars_for_template(player: Player): if player.id_in_group % 2 == 0: return {'custom_text': 'a human advice from an expert economics professor'} else: return {'custom_text': 'an AI advice generated by ChatGPT'} class Decision(Page): form_model = 'player' form_fields = ['cooperate'] @staticmethod def vars_for_template(player: Player): if player.id_in_group % 2 == 0: return { 'custom_text': '
In a single-round Prisoner\'s Dilemma game, where you must make a decision without knowledge of your opponent\'s choice, I would advise you to choose “defect” instead of “cooperate”.
In a single-round Prisoner\'s Dilemma game, where you must make a decision without knowledge of your opponent\'s choice, it is rational to betray. The reasoning behind this decision is based on the inherent risk of betrayal being the dominant strategy.