from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, # Currency as c, currency_range Currency as c, ) import random doc = """ This is an iterated Prisoner's Dilemma where players play against a computer player that executes a particular strategy. """ class Constants(BaseConstants): name_in_url = 'prisoner2' players_per_group = None # players_per_group = 1 num_rounds = 15 rounds_per_session = num_rounds instructions_template = 'prisoner_2period/instructions.html' history_template = 'prisoner_2period/history.html' # payoff if 1 player defects and the other cooperates""", betray_payoff = c(300) betrayed_payoff = c(0) # payoff if both players cooperate or both defect both_cooperate_payoff = c(200) both_defect_payoff = c(50) decision_letter = { 'Cooperate': 'C', 'Defect': 'D' } decision_name = { 'C': 'Cooperate', 'D': 'Defect' } # bot_strategies = ['tit-for-tat', 'true-random', '2-period-punish'] bot_strategies = ['true-random', '2-period-punish', 'tit-for-tat'] class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): decision = models.StringField( choices=['Cooperate', 'Defect'], doc="""This player's decision""", widget=widgets.RadioSelect ) bot_decision = models.StringField() bot_payoff = models.CurrencyField() bot_strategy = models.StringField() # name = models.StringField( # label='What is your fictitious name?' # ) # guess_strategy = models.StringField( # label='What strategy do you think the bot used? Please name or describe the strategy in the box below:', # widget=widgets.Textarea, # ) # age = models.IntegerField( # label='What is your age?', # ) # # gender = models.StringField( # choices=['Male', 'Female', 'Other'], # label='What is your gender?', # widget=widgets.RadioSelect # ) # # continent = models.StringField( # choices=['Africa', 'Asia', 'Europe', 'North America', 'South America', 'Oceania'], # label='Which continent are you from?', # widget=widgets.RadioSelect # ) # # studied = models.BooleanField( # choices=[ # [True, 'Yes'], # [False, 'No'], # ], # label='Have you studied game theory before?', # widget=widgets.RadioSelect # ) # # # personality = models.StringField( # # choices=[] # # ) # # comments = models.StringField( # label='Please note down any other comments you may have in the box below:', # widget=widgets.Textarea, # blank=True # ) def bot_player(self): # set current session number session_number = ((self.round_number - 1) // Constants.rounds_per_session) + 1 # set current round number in current session round_in_session = self.round_number - ((session_number-1) * Constants.rounds_per_session) # bot always cooperates in first round of each session if round_in_session == 1: self.bot_decision = 'Cooperate' self.participant.vars['all_bot_decisions'] = [Constants.decision_letter[self.bot_decision]] # set bot strategy in first round self.bot_strategy = '2-period-punish' # set forgiveness counter to 2 at start of first round self.participant.vars['forgiveness_counter'] = 2 # bot decisions in subsequent rounds depends on bot strategy & player's prev choices else: prev_player = self.in_round(self.round_number-1) self.bot_strategy = prev_player.bot_strategy if self.bot_strategy == 'tit-for-tat': self.bot_decision = prev_player.decision if self.bot_strategy == 'true-random': self.bot_decision = random.choice(['Cooperate', 'Defect']) if self.bot_strategy == '2-period-punish': if self.participant.vars['forgiveness_counter'] >= 2: self.bot_decision = 'Cooperate' else: self.bot_decision = 'Defect' self.participant.vars['all_bot_decisions'].append(Constants.decision_letter[self.bot_decision]) return self.bot_decision # main method def set_payoff(self): payoff_matrix = { 'Cooperate': { 'Cooperate': Constants.both_cooperate_payoff, 'Defect': Constants.betrayed_payoff }, 'Defect': { 'Cooperate': Constants.betray_payoff, 'Defect': Constants.both_defect_payoff } } bot_decision = self.bot_player() self.payoff = payoff_matrix[self.decision][bot_decision] self.bot_payoff = payoff_matrix[bot_decision][self.decision] # set current session number session_number = ((self.round_number - 1) // Constants.rounds_per_session) + 1 # set current round number in current session round_in_session = self.round_number - ((session_number - 1) * Constants.rounds_per_session) # if player defects, set forgiveness counter to 0 if self.decision == 'Defect': self.participant.vars['forgiveness_counter'] = 0 # if player cooperates, increment forgiveness counter by 1 else: self.participant.vars['forgiveness_counter'] += 1 if round_in_session == 1: self.participant.vars['all_my_decisions'] = [Constants.decision_letter[self.decision]] self.participant.vars['all_my_payoffs'] = [self.payoff] self.participant.vars['all_bot_payoffs'] = [self.bot_payoff] else: self.participant.vars['all_my_decisions'].append(Constants.decision_letter[self.decision]) self.participant.vars['all_my_payoffs'].append(self.payoff) self.participant.vars['all_bot_payoffs'].append(self.bot_payoff) if round_in_session == Constants.rounds_per_session: self.participant.vars['all_my_total_payoffs'].append(sum(self.participant.vars['all_my_payoffs'])) self.participant.vars['all_bot_total_payoffs'].append(sum(self.participant.vars['all_bot_payoffs']))