from otree.api import * # ====================================================================================================================== doc = """ Section C (Part III). Main experiment rounds with matches followed by interaction sets. """ # ====================================================================================================================== # 1. Defining Constants # ====================================================================================================================== class Constants(BaseConstants): name_in_url = 'choices' players_per_group = None num_rounds = 6 # Define a dictionary for payoffs --------------------------------------------------------------------------------- d_payoff = { 'CC': 5, 'DC': 7, 'CD': 0, 'DD': 2 } # Define game lengths --------------------------------------------------------------------------------------------- game_len = [6, 23, 3, 4, 17, 7, 16, 1, 3, 19, 16, 11, 4, 9, 12, 13, 2, 3, 21, 9, 7, 6, 4, 1, 19, 3, 15, 7, 20, 3] # Include the instructions template INSTRUCTIONS_TEMPLATE = __name__ + '/instructions.html' PAYOFF_TABLE = __name__ + '/payoff_table.html' # Define a dictionary for choice sets ----------------------------------------------------------------------------- d_choices = { 1: ['PALLC', 'CDDALT', 'DTFT'], # In format of strategies A, B and opposing 2: ['ALLD', 'DTFT', 'GRIM1'], 3: ['DCALT', 'PTF2T', 'GRIM3'], 4: ['ALLD', 'FDDCALT', '2TF2T'], 5: ['CDALT', 'PTFT', 'ALLD'], 6: ['PALLD', 'DGRIM2', 'GRIM3'], 7: ['TFT', '2TF2T', '2TF2T'], 8: ['CDALT', 'ATF3T', 'DTFT'], 9: ['ALLC', 'GRIM1', 'TF2T'], 10: ['GRIM1', 'GRIM2', 'ALLD'], 11: ['TFT', 'DTF3T', 'GRIM3'], 12: ['DCALT', 'FCCDALT', '2TF2T'], 13: ['CDALT', 'TF3T', 'TFT'], 14: ['ALLC', 'DDDCALT', 'GRIM1'], 15: ['PALLD', 'DDCALT', 'GRIM2'], 16: ['CDALT', 'CDDDALT', 'GRIM3'], 17: ['TFT', 'FCDDALT', 'TF2T'], 18: ['CDALT', 'ATF2T', 'TFT'], 19: ['DCALT', 'TF2T', 'GRIM1'], 20: ['ALLC', 'FDDDCALT', 'TFT'], 21: ['TFT', 'GRIM3', 'GRIM3'], 22: ['TFT', 'D2TFT', '2TF2T'], 23: ['GRIM1', 'CCDALT', '2TF2T'], 24: ['ALLC', 'TFT', 'GRIM1'], 25: ['TFT', '2TFT', 'TF2T'], 26: ['TFT', 'DCCALT', 'GRIM3'], 27: ['DCALT', 'DTF2T', 'TFT'], 28: ['TFT', 'FCDDDALT', 'TF2T'], 29: ['ALLD', 'PALLC', 'ALLD'], 30: ['ALLC', 'FDCCALT', 'TF3T'], 31: ['CDALT', 'DTF3T', 'GRIM1'], 32: ['PALLD', 'FCCDALT', 'TFT'], 33: ['ALLC', 'TF3T', '2TF2T'], 34: ['DALLC', 'DDDCALT', 'TFT'], 35: ['TFT', 'DDCALT', 'ALLD'], 36: ['PALLC', 'DCCALT', 'GRIM3'], 37: ['TFT', 'DTF2T', 'GRIM3'], 38: ['TFT', 'FCDDDALT', '2TF2T'], 39: ['ALLD', 'PALLC', 'ALLD'], 40: ['CDALT', 'FDCCALT', 'TF3T'], 41: ['ALLC', 'GRIM1', 'GRIM3'], 42: ['PALLC', '2TF2T', 'TF2T'], 43: ['PALLD', 'ATF3T', 'DTFT'], 44: ['GRIM1', 'DGRIM2', 'GRIM3'], 45: ['ALLC', 'GRIM2', 'TF2T'], 46: ['DCALT', 'GRIM3', 'GRIM3'], 47: ['ALLD', 'D2TFT', 'TF2T'], 48: ['CDALT', 'CCDALT', 'TF2T'], 49: ['ALLC', 'TFT', 'GRIM3'], 50: ['CDALT', '2TFT', 'ALLD'], 51: ['GRIM1', 'PTF2T', 'TF3T'], 52: ['PALLD', 'FDDCALT', 'TF3T'], 53: ['TFT', 'CDDALT', 'GRIM3'], 54: ['ALLC', 'DTFT', 'TF2T'], 55: ['PALLC', 'PTFT', 'GRIM3'], 56: ['PALLC', 'CDDDALT', 'ALLD'], 57: ['ALLD', 'ATF2T', 'GRIM1'], 58: ['TFT', 'FDDDCALT', '2TFT'], 59: ['GRIM1', 'TF2T', 'ALLD'], 60: ['TFT', 'FCCDALT', 'TF2T'], 61: ['ALLD', 'ALLD', 'ALLD'] } # Define dictionary of choices based on treatment id d_games = { 0: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], 1: [1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 26, 27, 28, 29, 30, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50], 2: [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60], 3: [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40], 4: [16, 17, 18, 19, 20, 26, 27, 28, 29, 30, 1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50], 5: [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60], } # Create a dictionary for strategies ------------------------------------------------------------------------------- d_strategies = { 'ALLC': {'OOOO': 'C1', 'C1CC': 'C1', 'C1CD': 'C1', 'C1DC': 'C1', 'C1DD': 'C1', }, 'ALLD': {'OOOO': 'D1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'D1', 'D1DD': 'D1', }, 'PALLC': {'OOOO': 'C1', 'C1CC': 'C1', 'C1CD': 'C1', 'C1DC': 'C1', 'C1DD': 'D1', 'D1CC': 'C1', 'D1CD': 'C1', 'D1DC': 'C1', 'D1DD': 'D1', }, 'PALLD': {'OOOO': 'D1', 'C1CC': 'C1', 'C1CD': 'D1', 'C1DC': 'D1', 'C1DD': 'D1', 'D1CC': 'C1', 'D1CD': 'D1', 'D1DC': 'D1', 'D1DD': 'D1', }, 'DALLC': {'OOOO': 'D1', 'C1CC': 'C1', 'C1CD': 'C1', 'C1DC': 'C1', 'C1DD': 'C1', 'D1CC': 'C1', 'D1CD': 'C1', 'D1DC': 'C1', 'D1DD': 'C1', }, 'GRIM1': {'OOOO': 'C1', 'C1CC': 'C1', 'C1CD': 'D1', 'C1DC': 'D1', 'C1DD': 'D1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'D1', 'D1DD': 'D1', }, 'GRIM2': {'OOOO': 'C1', 'C1CC': 'C1', 'C1CD': 'C2', 'C1DC': 'C2', 'C1DD': 'C2', 'C2CC': 'C1', 'C2CD': 'D1', 'C2DC': 'D1', 'C2DD': 'D1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'D1', 'D1DD': 'D1', }, 'GRIM3': {'OOOO': 'C1', 'C1CC': 'C1', 'C1CD': 'C2', 'C1DC': 'C2', 'C1DD': 'C2', 'C2CC': 'C1', 'C2CD': 'C3', 'C2DC': 'C3', 'C2DD': 'C3', 'C3CC': 'C1', 'C3CD': 'D1', 'C3DC': 'D1', 'C3DD': 'D1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'D1', 'D1DD': 'D1', }, 'DGRIM2': {'OOOO': 'D1', 'D1CC': 'C1', 'D1CD': 'C2', 'D1DC': 'C2', 'D1DD': 'C2', 'C1CC': 'C1', 'C1CD': 'C2', 'C1DC': 'C2', 'C1DD': 'C2', 'C2CC': 'C1', 'C2CD': 'D2', 'C2DC': 'D2', 'C2DD': 'D2', 'D2CC': 'D2', 'D2CD': 'D2', 'D2DC': 'D2', 'D2DD': 'D2', }, 'TFT': {'OOOO': 'C1', 'C1CC': 'C1', 'C1CD': 'D1', 'C1DC': 'C1', 'C1DD': 'D1', 'D1CC': 'C1', 'D1CD': 'D1', 'D1DC': 'C1', 'D1DD': 'D1', }, 'TF2T': {'OOOO': 'C1', 'C1CC': 'C1', 'C1CD': 'C2', 'C1DC': 'C1', 'C1DD': 'C2', 'C2CC': 'C1', 'C2CD': 'D1', 'C2DC': 'C1', 'C2DD': 'D1', 'D1CC': 'C1', 'D1CD': 'D1', 'D1DC': 'C1', 'D1DD': 'D1', }, 'TF3T': {'OOOO': 'C1', 'C1CC': 'C1', 'C1CD': 'C2', 'C1DC': 'C1', 'C1DD': 'C2', 'C2CC': 'C1', 'C2CD': 'C3', 'C2DC': 'C1', 'C2DD': 'C3', 'C3CC': 'C1', 'C3CD': 'D1', 'C3DC': 'C1', 'C3DD': 'D1', 'D1CC': 'C1', 'D1CD': 'D1', 'D1DC': 'C1', 'D1DD': 'D1', }, '2TFT': {'OOOO': 'C1', 'C1CC': 'C1', 'C1CD': 'D1', 'C1DC': 'C1', 'C1DD': 'D1', 'D1CC': 'D2', 'D1CD': 'D1', 'D1DC': 'D2', 'D1DD': 'D1', 'D2CC': 'C1', 'D2CD': 'D1', 'D2DC': 'C1', 'D2DD': 'D1', }, '2TF2T': {'OOOO': 'C1', 'C1CC': 'C1', 'C1CD': 'C2', 'C1DC': 'C1', 'C1DD': 'C2', 'C2CC': 'C1', 'C2CD': 'D1', 'C2DC': 'C1', 'C2DD': 'D1', 'D1CC': 'D2', 'D1CD': 'D1', 'D1DC': 'D2', 'D1DD': 'D1', 'D2CC': 'C1', 'D2CD': 'C2', 'D2DC': 'C1', 'D2DD': 'C2', }, 'DTFT': {'OOOO': 'D1', 'D1CC': 'C1', 'D1CD': 'D1', 'D1DC': 'C1', 'D1DD': 'D1', 'C1CC': 'C1', 'C1CD': 'D1', 'C1DC': 'C1', 'C1DD': 'D1', }, 'DTF2T': {'OOOO': 'D1', 'D1CC': 'C1', 'D1CD': 'C2', 'D1DC': 'C1', 'D1DD': 'C2', 'C1CC': 'C1', 'C1CD': 'C2', 'C1DC': 'C1', 'C1DD': 'C2', 'C2CC': 'C1', 'C2CD': 'D2', 'C2DC': 'C1', 'C2DD': 'D2', 'D2CC': 'C1', 'D2CD': 'D2', 'D2DC': 'C1', 'D2DD': 'D2', }, 'DTF3T': {'OOOO': 'D1', 'D1CC': 'C1', 'D1CD': 'C2', 'D1DC': 'C1', 'D1DD': 'C2', 'C1CC': 'C1', 'C1CD': 'C2', 'C1DC': 'C1', 'C1DD': 'C2', 'C2CC': 'C1', 'C2CD': 'C3', 'C2DC': 'C1', 'C2DD': 'C3', 'C3CC': 'C1', 'C3CD': 'D2', 'C3DC': 'C1', 'C3DD': 'D2', 'D2CC': 'C1', 'D2CD': 'D2', 'D2DC': 'C1', 'D2DD': 'D2', }, 'D2TFT': {'OOOO': 'D1', 'D1CC': 'C1', 'D1CD': 'D2', 'D1DC': 'C1', 'D1DD': 'D2', 'D2CC': 'D1', 'D2CD': 'D2', 'D2DC': 'D1', 'D2DD': 'D2', 'C1CC': 'C1', 'C1CD': 'D2', 'C1DC': 'C1', 'C1DD': 'D2', }, 'PTFT': {'OOOO': 'C1', 'C1CC': 'C2', 'C1CD': 'C2', 'C1DC': 'C2', 'C1DD': 'C2', 'C2CC': 'C2', 'C2CD': 'D1', 'C2DC': 'C2', 'C2DD': 'D1', 'D1CC': 'C2', 'D1CD': 'D1', 'D1DC': 'C2', 'D1DD': 'D1', }, 'PTF2T': {'OOOO': 'C1', 'C1CC': 'C2', 'C1CD': 'C2', 'C1DC': 'C2', 'C1DD': 'C2', 'C2CC': 'C2', 'C2CD': 'C3', 'C2DC': 'C2', 'C2DD': 'C3', 'C3CC': 'C2', 'C3CD': 'D1', 'C3DC': 'C2', 'C3DD': 'D1', 'D1CC': 'C2', 'D1CD': 'D1', 'D1DC': 'C2', 'D1DD': 'D1', }, 'ATF2T': {'OOOO': 'C1', 'C1CC': 'C2', 'C1CD': 'D1', 'C1DC': 'C2', 'C1DD': 'D1', 'D1CC': 'C2', 'D1CD': 'D1', 'D1DC': 'C2', 'D1DD': 'D1', 'C2CC': 'C2', 'C2CD': 'C1', 'C2DC': 'C2', 'C2DD': 'C1', }, 'ATF3T': {'OOOO': 'C1', 'C1CC': 'C2', 'C1CD': 'D1', 'C1DC': 'C2', 'C1DD': 'D1', 'C2CC': 'C2', 'C2CD': 'C3', 'C2DC': 'C2', 'C2DD': 'C3', 'C3CC': 'C2', 'C3CD': 'C1', 'C3DC': 'C2', 'C3DD': 'C1', 'D1CC': 'C2', 'D1CD': 'D1', 'D1DC': 'C2', 'D1DD': 'D1', }, 'CDALT': {'OOOO': 'C1', 'C1CC': 'D1', 'C1CD': 'D1', 'C1DC': 'C1', 'C1DD': 'C1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'C1', 'D1DD': 'C1', }, 'DCALT': {'OOOO': 'D1', 'C1CC': 'D1', 'C1CD': 'D1', 'C1DC': 'C1', 'C1DD': 'C1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'C1', 'D1DD': 'C1', }, 'CCDALT': {'OOOO': 'C1', 'C1CC': 'C2', 'C1CD': 'C2', 'C1DC': 'C1', 'C1DD': 'C1', 'C2CC': 'D1', 'C2CD': 'D1', 'C2DC': 'C1', 'C2DD': 'C1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'C1', 'D1DD': 'C1', }, 'CDDALT': {'OOOO': 'C1', 'C1CC': 'D1', 'C1CD': 'D1', 'C1DC': 'C1', 'C1DD': 'C1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'D2', 'D1DD': 'D2', 'D2CC': 'D1', 'D2CD': 'D1', 'D2DC': 'C1', 'D2DD': 'C1', }, 'DDCALT': {'OOOO': 'D1', 'C1CC': 'D1', 'C1CD': 'D1', 'C1DC': 'C1', 'C1DD': 'C1', 'D2CC': 'D1', 'D2CD': 'D1', 'D2DC': 'C1', 'D2DD': 'C1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'D2', 'D1DD': 'D2', }, 'DCCALT': {'OOOO': 'D1', 'C1CC': 'C2', 'C1CD': 'C2', 'C1DC': 'C1', 'C1DD': 'C1', 'C2CC': 'D1', 'C2CD': 'D1', 'C2DC': 'C1', 'C2DD': 'C1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'C1', 'D1DD': 'C1', }, 'CDDDALT': {'OOOO': 'C1', 'C1CC': 'D1', 'C1CD': 'D1', 'C1DC': 'C1', 'C1DD': 'C1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'D2', 'D1DD': 'D2', 'D2CC': 'D1', 'D2CD': 'D1', 'D2DC': 'D3', 'D2DD': 'D3', 'D3CC': 'D1', 'D3CD': 'D1', 'D3DC': 'C1', 'D3DD': 'C1', }, 'FCCDALT': {'OOOO': 'C1', 'C1CC': 'C2', 'C1CD': 'C1', 'C1DC': 'C1', 'C1DD': 'C1', 'C2CC': 'D1', 'C2CD': 'C1', 'C2DC': 'C1', 'C2DD': 'C1', 'D1CC': 'D1', 'D1CD': 'C1', 'D1DC': 'C1', 'D1DD': 'C1', }, 'FCDDALT': {'OOOO': 'C1', 'C1CC': 'D1', 'C1CD': 'C1', 'C1DC': 'C1', 'C1DD': 'C1', 'D1CC': 'D1', 'D1CD': 'D2', 'D1DC': 'D2', 'D1DD': 'D2', 'D2CC': 'D1', 'D2CD': 'C1', 'D2DC': 'C1', 'D2DD': 'C1', }, 'FDDCALT': {'OOOO': 'D1', 'D1CC': 'D1', 'D1CD': 'D2', 'D1DC': 'D2', 'D1DD': 'D2', 'D2CC': 'D1', 'D2CD': 'C1', 'D2DC': 'C1', 'D2DD': 'C1', 'C1CC': 'D1', 'C1CD': 'C1', 'C1DC': 'C1', 'C1DD': 'C1', }, 'FDCCALT': {'OOOO': 'D1', 'D1CC': 'D1', 'D1CD': 'C1', 'D1DC': 'C1', 'D1DD': 'C1', 'C1CC': 'C2', 'C1CD': 'C1', 'C1DC': 'C1', 'C1DD': 'C1', 'C2CC': 'D1', 'C2CD': 'C1', 'C2DC': 'C1', 'C2DD': 'C1', }, 'FCDDDALT': {'OOOO': 'C1', 'C1CC': 'D1', 'C1CD': 'C1', 'C1DC': 'C1', 'C1DD': 'C1', 'D1CC': 'D1', 'D1CD': 'D2', 'D1DC': 'D2', 'D1DD': 'D2', 'D2CC': 'D1', 'D2CD': 'D3', 'D2DC': 'D3', 'D2DD': 'D3', 'D3CC': 'D1', 'D3CD': 'C1', 'D3DC': 'C1', 'D3DD': 'C1', }, 'DDDCALT': {'OOOO': 'D1', 'D1CC': 'D1', 'D1CD': 'D1', 'D1DC': 'D2', 'D1DD': 'D2', 'D2CC': 'D1', 'D2CD': 'D1', 'D2DC': 'D3', 'D2DD': 'D3', 'D3CC': 'D1', 'D3CD': 'D1', 'D3DC': 'C1', 'D3DD': 'C1', 'C1CC': 'D1', 'C1CD': 'D1', 'C1DC': 'C1', 'C1DD': 'C1', }, 'FDDDCALT': {'OOOO': 'D1', 'D1CC': 'D1', 'D1CD': 'D2', 'D1DC': 'D2', 'D1DD': 'D2', 'D2CC': 'D1', 'D2CD': 'D3', 'D2DC': 'D3', 'D2DD': 'D3', 'D3CC': 'D1', 'D3CD': 'C1', 'D3DC': 'C1', 'D3DD': 'C1', 'C1CC': 'D1', 'C1CD': 'C1', 'C1DC': 'C1', 'C1DD': 'C1', }, } # Create a dictionary for descriptions ----------------------------------------------------------------------------- d_description = { 'ALLC': 'Choose A in the first game. Continue to choose A for all remaining games.', 'ALLD': 'Choose B in the first game. Continue to choose B for all remaining games.', 'PALLC': 'Choose A in the first game. In subsequent games, choose A if in the last game either player played A. Otherwise, choose B if in the last game both players played B.', 'PALLD': 'Choose B in the first game. In subsequent games, choose B if in the last game either player played B. Otherwise, choose A if in the last game both players played A.', 'DALLC': 'Choose B in the first game. In subsequent games, choose A for all remaining games.', 'GRIM1': 'Choose A in the first game. In subsequent games, choose A if in the last game both players played A. If in the last game either player played B, choose B for all remaining games.', 'GRIM2': 'Choose A in the first two games. In subsequent games, choose A if in either of the last two games both players played A. If in both of the last two games either player played B, choose B for all remaining games.', 'GRIM3': 'Choose A in the first three games. In subsequent games, choose A if in any of the last three games both players played A. If in all of the last three games either player played B, choose B for all remaining games.', 'DGRIM2': 'Choose B and then A in the first two games. In subsequent games, choose A if in either of the last two games both players played A. If in both of the last two games either player played B, choose B for all remaining games.', 'TFT': 'Choose A in the first game. In subsequent games, choose A if in the last game your counterpart played A. Otherwise, choose B if in the last game your counterpart played B.', 'TF2T': 'Choose A in the first two games. In subsequent games, choose A if in either of the last two games your counterpart played A. Otherwise, choose B if in both of the last two games your counterpart played B.', 'TF3T': 'Choose A in the first three games. In subsequent games, choose A if in any of the last three games your counterpart played A. Otherwise, choose B if in all of the last three games your counterpart played B.', '2TFT': 'Choose A in the first game. In subsequent games, choose B if in either of the last two games your counterpart played B. Otherwise, choose A if in both of the last two games your counterpart has not played B.', '2TF2T': 'Choose A in the first game. In subsequent games, choose A if in the last three games your counterpart has not played B consecutively. Otherwise, choose B if in two consecutive games of the last three games your counterpart played B.', 'DTFT': 'Choose B in the first game. In subsequent games, choose A if in the last game your counterpart played A. Otherwise, choose B if in the last game your counterpart played B.', 'DTF2T': 'Choose B and then A in the first two games. In subsequent games, choose A if in either of the last two games your counterpart played A. Otherwise, choose B if in both of the last two games your counterpart played B.', 'DTF3T': 'Choose B then A then A in the first three games. In subsequent games, choose A if in any of the last three games your counterpart played A. Otherwise, choose B if in all of the last three games your counterpart played B.', 'D2TFT': 'Choose B in the first game. In subsequent games, choose B if in either of the last two games your counterpart played B. Otherwise, choose A if in both of the last two games your counterpart has not played B.', 'PTFT': 'Choose A in the first two games. In subsequent games, choose A if in the last game your counterpart played A. Otherwise, choose B if in the last game your counterpart played B.', 'PTF2T': 'Choose A in the first three games. In subsequent games, choose A if in either of the last two games your counterpart played A. Otherwise, choose B if in both of the last two games your counterpart played B.', 'ATF2T': 'Choose A in the first game. In subsequent games choose A if in either of the last two games your counterpart played A. Otherwise, choose B if in both of the last two games your counterpart did not play A.', 'ATF3T': 'Choose A in the first game. In subsequent games, choose A if in any of the last three games your counterpart played A. Otherwise, choose B if in all of the last three games your counterpart did not play A.', 'CDALT': 'Choose A in the first game. In subsequent games, choose A if in the last game you played B. Otherwise, choose B if in the last game you played A.', 'DCALT': 'Choose B in the first game. In subsequent games, choose A if in the last game you played B. Otherwise, choose B if in the last game you played A.', 'CCDALT': 'Choose A in the first two games. In subsequent games, choose A if in either of the last two games you played B. Otherwise, choose B if in both of the last two games you played A.', 'CDDALT': 'Choose A in the first game. In subsequent games, choose B if in either of the last two games you played A. Otherwise, choose A if in either of the last two games you did not play A.', 'DDCALT': 'Choose B in the first two games. In subsequent games, choose B if in either of the last two games you played A. Otherwise, choose A if in both of the last two games you played B.', 'DCCALT': 'Choose B in the first game. In subsequent games, choose A if in either of the last two games you played B. Otherwise, choose B if in both of the last two games you did not play B.', 'CDDDALT': 'Choose A in the first game. In subsequent games, choose B if in any of the last three games you have played A. Otherwise, choose A if in all of the last three games you did not play A.', 'FCCDALT': 'Choose A in the first two games. In subsequent games, choose A if in either of the last two games either player played B. Otherwise, choose B if in both of the last two games both players played A.', 'FCDDALT': 'Choose A in the first game. In subsequent games, choose B if in either of the last two games both players played A. Otherwise, choose A if in both of the last two games both players did not play A.', 'FDDCALT': 'Choose B in the first two games. In subsequent games, choose B if in either of the last two games both players played A. Otherwise, choose A if in both of the last two games either player played B.', 'FDCCALT': 'Choose B in the first game. In subsequent games, choose A if in either of the last two games either player played B. Otherwise, choose B if in both of the past two games both players did not play B.', 'FCDDDALT': 'Choose A in the first game. In subsequent games, choose B if in any of the last three games both players played A. Otherwise, choose A if in the last three games no game had both players play A.', 'DDDCALT': 'Choose B in the first three games. In subsequent games, choose B if in any of the last three games you have played A. Otherwise, choose A if in all of the last three games you played B.', 'FDDDCALT': 'Choose B in the first three games. In subsequent games, choose B if in any of the last three games both players played A. Otherwise, choose A if in all of the last three games either player played B.' } # Create a dictionary for image paths ----------------------------------------------------------------------------- d_image = { 'TFT': 'strategies/TFT.jpg', 'ALLC': 'strategies/ALLC.jpg', 'ALLD': 'strategies/ALLD.jpg', 'CDALT': 'strategies/CDALT.jpg', 'GRIM1': 'strategies/GRIM1.jpg', 'GRIM2': 'strategies/GRIM2.jpg', 'GRIM3': 'strategies/GRIM3.jpg', 'DGRIM2': 'strategies/DGRIM2.jpg', 'DGRIM3': 'strategies/DGRIM3.jpg', 'TF2T': 'strategies/TF2T.jpg', 'TF3T': 'strategies/TF3T.jpg', '2TF2T': 'strategies/2TF2T.jpg', 'DTFT': 'strategies/DTFT.jpg', 'DCALT': 'strategies/DCALT.jpg', '2TFT': 'strategies/2TFT.jpg', 'D2TFT': 'strategies/D2TFT.jpg', 'DTF2T': 'strategies/DTF2T.jpg', 'DTF3T': 'strategies/DTF3T.jpg', 'CCDALT': 'strategies/CCDALT.jpg', 'CDDALT': 'strategies/CDDALT.jpg', 'DDCALT': 'strategies/DDCALT.jpg', 'CDDDALT': 'strategies/CDDDALT.jpg', 'DCCALT': 'strategies/DCCALT.jpg', 'DALLC': 'strategies/DALLC.jpg', 'PALLD': 'strategies/PALLD.jpg', 'PALLC': 'strategies/PALLC.jpg', 'PTFT': 'strategies/PTFT.jpg', 'PTF2T': 'strategies/PTF2T.jpg', 'ATF2T': 'strategies/ATF2T.jpg', 'ATF3T': 'strategies/ATF3T.jpg', 'FCCDALT': 'strategies/FCCDALT.jpg', 'FCDDALT': 'strategies/FCDDALT.jpg', 'FDDCALT': 'strategies/FDDCALT.jpg', 'FCDDDALT': 'strategies/FCDDDALT.jpg', 'FDCCALT': 'strategies/FDCCALT.jpg', 'DDDCALT': 'strategies/DDDCALT.jpg', 'FDDDCALT': 'strategies/FDDDCALT.jpg', } # Create a dictionary for image paths ----------------------------------------------------------------------------- d_image_opp = { 'ALLD': 'strategies/opposing/ALLD_opp.jpg', 'GRIM1': 'strategies/opposing/GRIM1_opp.jpg', 'GRIM2': 'strategies/opposing/GRIM2_opp.jpg', 'GRIM3': 'strategies/opposing/GRIM3_opp.jpg', 'TFT': 'strategies/opposing/TFT_opp.jpg', 'TF2T': 'strategies/opposing/TF2T_opp.jpg', 'TF3T': 'strategies/opposing/TF3T_opp_a.jpg', '2TF2T': 'strategies/opposing/2TF2T_opp.jpg', '2TFT': 'strategies/opposing/2TFT_opp.jpg', 'DTFT': 'strategies/opposing/DTFT_opp.jpg', } # Create a counter counter = 0 class Player(BasePlayer): # Create the strategy choice fields ------------------------------------------------------------------------------- choice = models.BooleanField(label="", choices=[[True, 'Option A'], [False, 'Option B']], widget=widgets.RadioSelectHorizontal) # Create the strategy choice fields ------------------------------------------------------------------------------- choice_1 = models.BooleanField(initial=None) choice_2 = models.BooleanField(initial=None) choice_3 = models.BooleanField(initial=None) choice_4 = models.BooleanField(initial=None) choice_5 = models.BooleanField(initial=None) # Create the stores for the choice id faced in the round ---------------------------------------------------------- id_1 = models.IntegerField(initial=0) id_2 = models.IntegerField(initial=0) id_3 = models.IntegerField(initial=0) id_4 = models.IntegerField(initial=0) id_5 = models.IntegerField(initial=0) # Create storing fields for values across the round and in the implementation ------------------------------------- strategy_p = models.StringField(initial='') strategy_c = models.StringField(initial='') history = models.StringField(initial='OOOO') state_p = models.StringField(initial='OO') state_c = models.StringField(initial='OO') outcome = models.IntegerField(initial=0) ind_mistake = models.BooleanField(initial=False) ind_error = models.BooleanField(initial=False) # Define values for interaction implementations ------------------------------------------------------------------- outcome_1 = models.IntegerField(initial=0) mistake_1 = models.BooleanField(initial=False) outcome_2 = models.IntegerField(initial=0) mistake_2 = models.BooleanField(initial=False) outcome_3 = models.IntegerField(initial=0) mistake_3 = models.BooleanField(initial=False) outcome_4 = models.IntegerField(initial=0) mistake_4 = models.BooleanField(initial=False) outcome_5 = models.IntegerField(initial=0) mistake_5 = models.BooleanField(initial=False) # Define round variables ------------------------------------------------------------------------------------------ treatment_manu = models.BooleanField(initial=False) treatment_show = models.BooleanField(initial=False) class Subsession(BaseSubsession): pass class Group(BaseGroup): pass # ====================================================================================================================== # 2. Defining functions # ====================================================================================================================== def choose(history, sub_strategy, sub_state, opp_chose=False): # Set the key based on the state and the most recent round of play sub_key = sub_state + history[-2:] if opp_chose: sub_key = sub_key[0:2] + sub_key[3] + sub_key[2] if sub_key == 'OOOO': sub_action = sub_strategy['OOOO'] else: sub_action = sub_strategy[sub_key] return sub_action # Define a function that will switch to strings to E and F values, and report relevant histories to return to template - def report_history(string): string = string.replace('C', 'A') string = string.replace('D', 'B') first_string = string[4:][::2] second_string = string[5:][::2] return first_string, second_string # Define a function that generates an error with 1/8th chance ---------------------------------------------------------- def error(string): import random ind_error = random.randint(1, 8) == 1 if ind_error: string = 'C' if string == 'D' else 'D' return string, ind_error def live_method_function(player: Player, data): # Check if the interaction has ended ------------------------------------------------------------------------------- if len(report_history(player.history)[0]) < Constants.game_len[player.participant.implement_counter]: # Set value to indicate the interaction has not ended ---------------------------------------------------------- ind_game_end = False # Call respective update_turn functions based on treatments ---------------------------------------------------- if player.treatment_manu: ind_game_end = update_turn(player, data, manu=player.treatment_manu) print('update turn used for manual') elif not player.treatment_manu: if data['nextAction']: ind_game_end = update_turn(player, data, manu=player.treatment_manu) print('update turn used for automatic') else: # Set the value to indicate the interaction has ended ---------------------------------------------------------- ind_game_end = True print('The number of games played have been: ', len(report_history(player.history)[0])) # Create the turn_number variable if len(report_history(player.history)[0]) == 1: turn_number_message = str(len(report_history(player.history)[0])) + ' game has' else: turn_number_message = str(len(report_history(player.history)[0])) + ' games have' # # Return relevant values ------------------------------------------------------------------------------------------- return {player.id_in_group: dict(history_player=report_history(player.history)[0], history_comput=report_history(player.history)[1], ind_error_player=player.ind_error, gameEnd=ind_game_end, turn_number=turn_number_message)} def update_turn(player: Player, data, manu): # Step 1: Update the states ---------------------------------------------------------------------------------------- player.state_p = Constants.d_strategies[player.strategy_p][player.state_p + player.history[-2:]] player.state_c = Constants.d_strategies[player.strategy_c][player.state_c + player.history[-1:] + player.history[-2:-1]] # Step 2: Update the states choice_p = player.state_p[0] choice_c = player.state_c[0] # Step 3: If the implementation is manual, then check player choice against required choice if manu: if choice_p != ['D', 'C'][data['coop']]: # mistake_message = 'You made a mistake at turn' + str(report_history(player.history)[0])) + 'where you played ' + str(['D', 'C'][data['coop']]) + 'where you should have chosen' + choice_p choice_p = ['D', 'C'][data['coop']] player.ind_mistake = True # Step 4: Introduce the chance of an error that chances the action actual_p, player.ind_error = error(choice_p) actual_o = error(choice_c)[0] # Step 5: Add the actions to the history player.history += actual_p + actual_o # Step 6: Add the results to the payoff player.outcome += Constants.d_payoff[player.history[-2:]] player.outcome = [player.outcome, 0][player.ind_mistake] # Step 7: Return a True value if the game has ended return len(report_history(player.history)[0]) >= Constants.game_len[player.participant.implement_counter] # ====================================================================================================================== # 3. Defining Pages # ====================================================================================================================== class cBegin(Page): @staticmethod def vars_for_template(player: Player): # Set the treatments for this round player.treatment_manu = player.participant.manual_first if player.round_number in [1, 3, 5] else\ not player.participant.manual_first player.treatment_show = True if player.round_number in [1, 2, 3, 4] else False @staticmethod def before_next_page(player: Player, timeout_happened): # Set the choice IDs that participants face in the round player.id_1, player.id_2, player.id_3, player.id_4, player.id_5 =\ Constants.d_games[player.participant.id_set][player.participant.count_c: player.participant.count_c + 5] class cChoice(Page): form_model = 'player' form_fields = ['choice'] @staticmethod def vars_for_template(player: Player): id_choice = Constants.d_games[player.participant.id_set][player.participant.count_c] set_choices = Constants.d_choices[id_choice] return dict(choice_number=player.participant.count_c % 5 + 1, image_a=Constants.d_image[set_choices[0]], image_b=Constants.d_image[set_choices[1]], image_opp=Constants.d_image_opp[set_choices[2]], description_a=Constants.d_description[set_choices[0]], description_b=Constants.d_description[set_choices[1]], description_opp=Constants.d_description[set_choices[2]]) @staticmethod def before_next_page(player: Player, timeout_happened): # Store the result if player.participant.count_c % 5 == 0: player.choice_1 = player.choice elif player.participant.count_c % 5 == 1: player.choice_2 = player.choice elif player.participant.count_c % 5 == 2: player.choice_3 = player.choice elif player.participant.count_c % 5 == 3: player.choice_4 = player.choice elif player.participant.count_c % 5 == 4: player.choice_5 = player.choice # Clear results player.choice = None # Move the choice counter ahead player.participant.count_c += 1 class cInbetween(Page): @staticmethod def before_next_page(player: Player, timeout_happened): import random num_rand = random.randint(0, 4) chosen_strategy = [player.choice_1, player.choice_2, player.choice_3, player.choice_4, player.choice_5][num_rand] ind_choice_set = Constants.d_games[player.participant.id_set][player.participant.count_c - 5:player.participant.count_c][num_rand] choice_set_a, choice_set_b, choice_set_opp = Constants.d_choices[ind_choice_set] # Set values player.strategy_p = [choice_set_b, choice_set_a][chosen_strategy] player.strategy_c = choice_set_opp print('The random number is:', num_rand) print('The chosen strategy is:', chosen_strategy) print('The set player strategy was:', player.strategy_p) print('The player opposing strategy was:', player.strategy_c) class cInteraction(Page): form_model = 'player' live_method = live_method_function @staticmethod def vars_for_template(player: Player): return dict(implementation_num=(player.participant.implement_counter % 5) + 1, image_strategy=Constants.d_image[player.strategy_p], description_strategy=Constants.d_description[player.strategy_p]) @staticmethod def before_next_page(player: Player, timeout_happened): print('The current implement counter is set at: ', player.participant.implement_counter) # Write a simple if code using the function's second argument if player.participant.implement_counter % 5 == 0: player.mistake_1 = player.ind_mistake player.outcome_1 = player.outcome elif player.participant.implement_counter % 5 == 1: player.mistake_2 = player.ind_mistake player.outcome_2 = player.outcome elif player.participant.implement_counter % 5 == 2: player.mistake_3 = player.ind_mistake player.outcome_3 = player.outcome elif player.participant.implement_counter % 5 == 3: player.mistake_4 = player.ind_mistake player.outcome_4 = player.outcome elif player.participant.implement_counter % 5 == 4: player.mistake_5 = player.ind_mistake player.outcome_5 = player.outcome # Update values player.history = 'OOOO' player.state_c = 'OO' player.state_p = 'OO' player.ind_mistake = False player.ind_error = False player.outcome = 0 # Move the counter forward one period player.participant.implement_counter += 1 class cResults(Page): def vars_for_template(player: Player): # Return a dictionary of game lengths and Yes/No values for correct implementation return dict(length_1=Constants.game_len[player.participant.implement_counter - 5], length_2=Constants.game_len[player.participant.implement_counter - 4], length_3=Constants.game_len[player.participant.implement_counter - 3], length_4=Constants.game_len[player.participant.implement_counter - 2], length_5=Constants.game_len[player.participant.implement_counter - 1], correct_1=['Yes', 'No'][player.mistake_1], correct_2=['Yes', 'No'][player.mistake_2], correct_3=['Yes', 'No'][player.mistake_3], correct_4=['Yes', 'No'][player.mistake_4], correct_5=['Yes', 'No'][player.mistake_5],) @staticmethod def before_next_page(player: Player, timeout_happened): # Create dictionary of current round results keys = ['payoff_1', 'payoff_2', 'payoff_3', 'payoff_4', 'payoff_5', 'correct_1', 'correct_2', 'correct_3', 'correct_4', 'correct_5'] keys = [key + '_' + str(player.round_number) for key in keys] values = [player.outcome_1, player.outcome_2, player.outcome_3, player.outcome_4, player.outcome_5, player.mistake_1, player.mistake_2, player.mistake_3, player.mistake_4, player.mistake_5,] d_result = dict(zip(keys, values)) # Append the dictionary to the global participant store player.participant.d_payoff = player.participant.d_payoff | d_result # ====================================================================================================================== # 4. Page sequence # ====================================================================================================================== page_sequence = [cBegin, cChoice, cChoice, cChoice, cChoice, cChoice, cInbetween, cInteraction, cInteraction, cInteraction, cInteraction, cInteraction, cResults]