from otree.api import * from constants import * from utils import bucket_suffix import random doc = """Public Goods Game with Punishment for Generation 1""" class C(BaseConstants): NAME_IN_URL = 'D_PGGame_Gen1_D' PLAYERS_PER_GROUP = None NUM_ROUNDS = Round_Per_Gen class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): # Fields from previous apps Ana_generation = models.IntegerField() Ana_own_id = models.IntegerField() Ana_family_assignment = models.StringField() Ana_GroupID = models.IntegerField() Ana_EndowmentType = models.IntegerField() Ana_Endowment = models.IntegerField() my_order = models.IntegerField() # Member info Ana_Mmb1_id = models.IntegerField() Ana_Mmb2_id = models.IntegerField() Ana_Mmb3_id = models.IntegerField() Ana_fname_Mmb1 = models.StringField() Ana_fname_Mmb2 = models.StringField() Ana_fname_Mmb3 = models.StringField() Ana_Edmt_Mmb1 = models.IntegerField() Ana_Edmt_Mmb2 = models.IntegerField() Ana_Edmt_Mmb3 = models.IntegerField() # Contribution Ana_contribution = models.IntegerField(min=0, max=30, label="") # Contributions of members Ana_Ctbt_Mmb1 = models.IntegerField() Ana_Ctbt_Mmb2 = models.IntegerField() Ana_Ctbt_Mmb3 = models.IntegerField() # Punishment points assigned (to other members at different contribution levels) Ana_mmb1_3 = models.IntegerField(min=0, max=10, label="") Ana_mmb1_6 = models.IntegerField(min=0, max=10, label="") Ana_mmb1_9 = models.IntegerField(min=0, max=10, label="") Ana_mmb1_12 = models.IntegerField(min=0, max=10, label="") Ana_mmb1_15 = models.IntegerField(min=0, max=10, label="") Ana_mmb1_18 = models.IntegerField(min=0, max=10, label="") Ana_mmb1_21 = models.IntegerField(min=0, max=10, label="") Ana_mmb1_24 = models.IntegerField(min=0, max=10, label="") Ana_mmb1_27 = models.IntegerField(min=0, max=10, label="") Ana_mmb1_30 = models.IntegerField(min=0, max=10, label="") Ana_mmb2_3 = models.IntegerField(min=0, max=10, label="") Ana_mmb2_6 = models.IntegerField(min=0, max=10, label="") Ana_mmb2_9 = models.IntegerField(min=0, max=10, label="") Ana_mmb2_12 = models.IntegerField(min=0, max=10, label="") Ana_mmb2_15 = models.IntegerField(min=0, max=10, label="") Ana_mmb2_18 = models.IntegerField(min=0, max=10, label="") Ana_mmb2_21 = models.IntegerField(min=0, max=10, label="") Ana_mmb2_24 = models.IntegerField(min=0, max=10, label="") Ana_mmb2_27 = models.IntegerField(min=0, max=10, label="") Ana_mmb2_30 = models.IntegerField(min=0, max=10, label="") Ana_mmb3_3 = models.IntegerField(min=0, max=10, label="") Ana_mmb3_6 = models.IntegerField(min=0, max=10, label="") Ana_mmb3_9 = models.IntegerField(min=0, max=10, label="") Ana_mmb3_12 = models.IntegerField(min=0, max=10, label="") Ana_mmb3_15 = models.IntegerField(min=0, max=10, label="") Ana_mmb3_18 = models.IntegerField(min=0, max=10, label="") Ana_mmb3_21 = models.IntegerField(min=0, max=10, label="") Ana_mmb3_24 = models.IntegerField(min=0, max=10, label="") Ana_mmb3_27 = models.IntegerField(min=0, max=10, label="") Ana_mmb3_30 = models.IntegerField(min=0, max=10, label="") # Punishment received Ana_punishpoints_received = models.IntegerField(initial=0) Ana_Fair_Aggregate_Disapproval = models.IntegerField( label="What is the fair level of total disapproval you should receive from both players?", min=0, max=20 ) # Belief elicitation - Expected disapproval for high endowment (30 ECUs) Ana_belief_high_3 = models.IntegerField(min=0, max=20, label="") Ana_belief_high_6 = models.IntegerField(min=0, max=20, label="") Ana_belief_high_9 = models.IntegerField(min=0, max=20, label="") Ana_belief_high_12 = models.IntegerField(min=0, max=20, label="") Ana_belief_high_15 = models.IntegerField(min=0, max=20, label="") Ana_belief_high_18 = models.IntegerField(min=0, max=20, label="") Ana_belief_high_21 = models.IntegerField(min=0, max=20, label="") Ana_belief_high_24 = models.IntegerField(min=0, max=20, label="") Ana_belief_high_27 = models.IntegerField(min=0, max=20, label="") Ana_belief_high_30 = models.IntegerField(min=0, max=20, label="") # Belief elicitation - Expected disapproval for low endowment (15 ECUs) Ana_belief_low_3 = models.IntegerField(min=0, max=20, label="") Ana_belief_low_6 = models.IntegerField(min=0, max=20, label="") Ana_belief_low_9 = models.IntegerField(min=0, max=20, label="") Ana_belief_low_12 = models.IntegerField(min=0, max=20, label="") Ana_belief_low_15 = models.IntegerField(min=0, max=20, label="") # Fair disapproval - High endowment (30 ECUs) Ana_fair_high_3 = models.IntegerField(min=0, max=20, label="") Ana_fair_high_6 = models.IntegerField(min=0, max=20, label="") Ana_fair_high_9 = models.IntegerField(min=0, max=20, label="") Ana_fair_high_12 = models.IntegerField(min=0, max=20, label="") Ana_fair_high_15 = models.IntegerField(min=0, max=20, label="") Ana_fair_high_18 = models.IntegerField(min=0, max=20, label="") Ana_fair_high_21 = models.IntegerField(min=0, max=20, label="") Ana_fair_high_24 = models.IntegerField(min=0, max=20, label="") Ana_fair_high_27 = models.IntegerField(min=0, max=20, label="") Ana_fair_high_30 = models.IntegerField(min=0, max=20, label="") # Fair disapproval - Low endowment (15 ECUs) Ana_fair_low_3 = models.IntegerField(min=0, max=20, label="") Ana_fair_low_6 = models.IntegerField(min=0, max=20, label="") Ana_fair_low_9 = models.IntegerField(min=0, max=20, label="") Ana_fair_low_12 = models.IntegerField(min=0, max=20, label="") Ana_fair_low_15 = models.IntegerField(min=0, max=20, label="") # PAGES class BeliefIntro(Page): """Introduction page for belief elicitation""" @staticmethod def is_displayed(player): return (player.round_number == 1 and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") class BeliefElicitation(Page): """Elicit beliefs about disapproval points from others""" form_model = 'player' @staticmethod def is_displayed(player): return (player.round_number == 1 and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") @staticmethod def get_form_fields(player): Ana_Endowment = player.participant.vars.get('Ana_Endowment') """Return all belief fields for both endowment scenarios""" if Ana_Endowment == 30: return ['Ana_belief_high_3', 'Ana_belief_high_6', 'Ana_belief_high_9', 'Ana_belief_high_12', 'Ana_belief_high_15', 'Ana_belief_high_18', 'Ana_belief_high_21', 'Ana_belief_high_24', 'Ana_belief_high_27', 'Ana_belief_high_30'] else: return ['Ana_belief_low_3', 'Ana_belief_low_6', 'Ana_belief_low_9', 'Ana_belief_low_12', 'Ana_belief_low_15'] @staticmethod def vars_for_template(player): return { 'Ana_generation': player.participant.Ana_generation, 'Ana_own_id': player.participant.Ana_own_id, 'Ana_family_assignment': player.participant.Ana_family_assignment, 'round_number': player.round_number, 'Ana_EndowmentType': player.participant.vars.get('Ana_EndowmentType'), 'Ana_Endowment': player.participant.vars.get('Ana_Endowment'), 'Ana_RankingType': player.participant.vars.get('Ana_RankingType'), } class FairDisapproval(Page): """Elicit opinions on fair level of disapproval""" form_model = 'player' @staticmethod def is_displayed(player): return (player.round_number == 1 and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") @staticmethod def get_form_fields(player): """Return all fair disapproval fields for both endowment scenarios""" Ana_Endowment = player.participant.vars.get('Ana_Endowment') if Ana_Endowment == 30: return ['Ana_fair_high_3', 'Ana_fair_high_6', 'Ana_fair_high_9', 'Ana_fair_high_12', 'Ana_fair_high_15', 'Ana_fair_high_18', 'Ana_fair_high_21', 'Ana_fair_high_24', 'Ana_fair_high_27', 'Ana_fair_high_30'] else: return ['Ana_fair_low_3', 'Ana_fair_low_6', 'Ana_fair_low_9', 'Ana_fair_low_12', 'Ana_fair_low_15'] @staticmethod def vars_for_template(player): return { 'Ana_generation': player.participant.Ana_generation, 'Ana_own_id': player.participant.Ana_own_id, 'Ana_family_assignment': player.participant.Ana_family_assignment, 'round_number': player.round_number, 'Ana_EndowmentType': player.participant.vars.get('Ana_EndowmentType'), 'Ana_Endowment': player.participant.vars.get('Ana_Endowment'), 'Ana_RankingType': player.participant.vars.get('Ana_RankingType'), } class BeliefOutro(Page): """Thank you page after belief elicitation""" @staticmethod def is_displayed(player): return (player.round_number == 1 and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") class WaitForPG_G1(WaitPage): @staticmethod def is_displayed(player): return (1 <= player.round_number <= Round_Per_Gen and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") class Punishment_G1(Page): form_model = 'player' @staticmethod def is_displayed(player): return (1 <= player.round_number <= Round_Per_Gen and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") @staticmethod def get_form_fields(player): """Return form fields based on player order and endowments""" my_order = player.participant.vars.get('my_order') if my_order == 1: edmt_2 = player.participant.vars.get('Ana_Edmt_Mmb2') edmt_3 = player.participant.vars.get('Ana_Edmt_Mmb3') if edmt_2 == 30 and edmt_3 == 15: return ['Ana_mmb2_3', 'Ana_mmb2_6', 'Ana_mmb2_9', 'Ana_mmb2_12', 'Ana_mmb2_15', 'Ana_mmb2_18', 'Ana_mmb2_21', 'Ana_mmb2_24', 'Ana_mmb2_27', 'Ana_mmb2_30', 'Ana_mmb3_3', 'Ana_mmb3_6', 'Ana_mmb3_9', 'Ana_mmb3_12', 'Ana_mmb3_15'] elif edmt_2 == 15 and edmt_3 == 30: return ['Ana_mmb2_3', 'Ana_mmb2_6', 'Ana_mmb2_9', 'Ana_mmb2_12', 'Ana_mmb2_15', 'Ana_mmb3_3', 'Ana_mmb3_6', 'Ana_mmb3_9', 'Ana_mmb3_12', 'Ana_mmb3_15', 'Ana_mmb3_18', 'Ana_mmb3_21', 'Ana_mmb3_24', 'Ana_mmb3_27', 'Ana_mmb3_30'] else: # Both 15 return ['Ana_mmb2_3', 'Ana_mmb2_6', 'Ana_mmb2_9', 'Ana_mmb2_12', 'Ana_mmb2_15', 'Ana_mmb3_3', 'Ana_mmb3_6', 'Ana_mmb3_9', 'Ana_mmb3_12', 'Ana_mmb3_15'] elif my_order == 2: edmt_1 = player.participant.vars.get('Ana_Edmt_Mmb1') edmt_3 = player.participant.vars.get('Ana_Edmt_Mmb3') if edmt_1 == 30 and edmt_3 == 15: return ['Ana_mmb1_3', 'Ana_mmb1_6', 'Ana_mmb1_9', 'Ana_mmb1_12', 'Ana_mmb1_15', 'Ana_mmb1_18', 'Ana_mmb1_21', 'Ana_mmb1_24', 'Ana_mmb1_27', 'Ana_mmb1_30', 'Ana_mmb3_3', 'Ana_mmb3_6', 'Ana_mmb3_9', 'Ana_mmb3_12', 'Ana_mmb3_15'] elif edmt_1 == 15 and edmt_3 == 30: return ['Ana_mmb1_3', 'Ana_mmb1_6', 'Ana_mmb1_9', 'Ana_mmb1_12', 'Ana_mmb1_15', 'Ana_mmb3_3', 'Ana_mmb3_6', 'Ana_mmb3_9', 'Ana_mmb3_12', 'Ana_mmb3_15', 'Ana_mmb3_18', 'Ana_mmb3_21', 'Ana_mmb3_24', 'Ana_mmb3_27', 'Ana_mmb3_30'] else: # Both 15 return ['Ana_mmb1_3', 'Ana_mmb1_6', 'Ana_mmb1_9', 'Ana_mmb1_12', 'Ana_mmb1_15', 'Ana_mmb3_3', 'Ana_mmb3_6', 'Ana_mmb3_9', 'Ana_mmb3_12', 'Ana_mmb3_15'] elif my_order == 3: edmt_1 = player.participant.vars.get('Ana_Edmt_Mmb1') edmt_2 = player.participant.vars.get('Ana_Edmt_Mmb2') if edmt_1 == 30 and edmt_2 == 15: return ['Ana_mmb1_3', 'Ana_mmb1_6', 'Ana_mmb1_9', 'Ana_mmb1_12', 'Ana_mmb1_15', 'Ana_mmb1_18', 'Ana_mmb1_21', 'Ana_mmb1_24', 'Ana_mmb1_27', 'Ana_mmb1_30', 'Ana_mmb2_3', 'Ana_mmb2_6', 'Ana_mmb2_9', 'Ana_mmb2_12', 'Ana_mmb2_15'] elif edmt_1 == 15 and edmt_2 == 30: return ['Ana_mmb1_3', 'Ana_mmb1_6', 'Ana_mmb1_9', 'Ana_mmb1_12', 'Ana_mmb1_15', 'Ana_mmb2_3', 'Ana_mmb2_6', 'Ana_mmb2_9', 'Ana_mmb2_12', 'Ana_mmb2_15', 'Ana_mmb2_18', 'Ana_mmb2_21', 'Ana_mmb2_24', 'Ana_mmb2_27', 'Ana_mmb2_30'] else: # Both 15 return ['Ana_mmb1_3', 'Ana_mmb1_6', 'Ana_mmb1_9', 'Ana_mmb1_12', 'Ana_mmb1_15', 'Ana_mmb2_3', 'Ana_mmb2_6', 'Ana_mmb2_9', 'Ana_mmb2_12', 'Ana_mmb2_15'] return [] @staticmethod def vars_for_template(player): my_order = player.participant.vars.get('my_order') if my_order == 1: Display1_ID = player.participant.vars.get('Ana_Mmb2_id') Display2_ID = player.participant.vars.get('Ana_Mmb3_id') Display1_nm = player.participant.vars.get('Ana_fname_Mmb2') Display2_nm = player.participant.vars.get('Ana_fname_Mmb3') Display1_Endw = player.participant.vars.get('Ana_Edmt_Mmb2') Display2_Endw = player.participant.vars.get('Ana_Edmt_Mmb3') elif my_order == 2: Display1_ID = player.participant.vars.get('Ana_Mmb1_id') Display2_ID = player.participant.vars.get('Ana_Mmb3_id') Display1_nm = player.participant.vars.get('Ana_fname_Mmb1') Display2_nm = player.participant.vars.get('Ana_fname_Mmb3') Display1_Endw = player.participant.vars.get('Ana_Edmt_Mmb1') Display2_Endw = player.participant.vars.get('Ana_Edmt_Mmb3') else: # my_order == 3 Display1_ID = player.participant.vars.get('Ana_Mmb1_id') Display2_ID = player.participant.vars.get('Ana_Mmb2_id') Display1_nm = player.participant.vars.get('Ana_fname_Mmb1') Display2_nm = player.participant.vars.get('Ana_fname_Mmb2') Display1_Endw = player.participant.vars.get('Ana_Edmt_Mmb1') Display2_Endw = player.participant.vars.get('Ana_Edmt_Mmb2') display_round = player.round_number # Pre-fill values from previous round for subsequent rounds prefill_values = {} if player.round_number > 1: previous_round_player = player.in_round(player.round_number - 1) fields = Punishment_G1.get_form_fields(player) for field in fields: value = getattr(previous_round_player, field, None) if value is not None: prefill_values[field] = value return { 'Display1_ID': Display1_ID, 'Display2_ID': Display2_ID, 'Display1_nm': Display1_nm, 'Display2_nm': Display2_nm, 'Display1_Endw': Display1_Endw, 'Display2_Endw': Display2_Endw, 'Ana_generation': player.participant.Ana_generation, 'RoundNumber1': display_round, 'RoundNumber2': display_round + 1, 'prefill_values': prefill_values, 'round_number': player.round_number, } @staticmethod def before_next_page(player: Player, timeout_happened=False): """Store punishment decisions in participant.vars and player fields""" fields = Punishment_G1.get_form_fields(player) # If this is not the first round and fields are empty, copy from previous round if player.round_number > 1: previous_round_player = player.in_round(player.round_number - 1) for field in fields: current_value = getattr(player, field, None) if current_value is None: # Copy from previous round previous_value = getattr(previous_round_player, field, None) setattr(player, field, previous_value) # Store in participant.vars for field in fields: player.participant.vars[field] = getattr(player, field, None) class PGGamep1_G1(Page): form_model = 'player' form_fields = ['Ana_contribution'] @staticmethod def is_displayed(player): return (1 <= player.round_number <= Round_Per_Gen and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") @staticmethod def vars_for_template(player): return { 'Ana_generation': player.participant.Ana_generation, 'Ana_own_id': player.participant.Ana_own_id, 'Ana_family_assignment': player.participant.Ana_family_assignment, 'round_number': player.round_number, 'Ana_EndowmentType': player.participant.vars.get('Ana_EndowmentType'), 'Ana_Endowment': player.participant.vars.get('Ana_Endowment'), } @staticmethod def error_message(player, values): if 'Ana_contribution' in values: Ana_contribution = values['Ana_contribution'] endowment_type = player.participant.vars.get('Ana_EndowmentType') if endowment_type == 1: # Low endowment if Ana_contribution < 0 or Ana_contribution > 15: return 'The number of ECUs you contribute has to be a whole number between 0 and 15.' elif endowment_type == 2: # High endowment if Ana_contribution < 0 or Ana_contribution > 30: return 'The number of ECUs you contribute has to be a whole number between 0 and 30.' class WaitForGeneration1(WaitPage): wait_for_all_groups = True @staticmethod def vars_for_template(player): return { 'Ana_contribution': player.Ana_contribution, 'my_order': player.participant.vars.get('my_order'), } @staticmethod def is_displayed(player): return (1 <= player.round_number <= Round_Per_Gen and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") @staticmethod def after_all_players_arrive(subsession): # Get active Gen-1 players players = [ p for p in subsession.get_players() if p.participant.vars.get('Ana_generation') == 1 and p.participant.vars.get('state') == "active" ] # Group by GroupID pg_groups = {} for p in players: gid = p.participant.vars.get('Ana_GroupID') pg_groups.setdefault(gid, []).append(p) # Calculate payoffs for each group for group_players in pg_groups.values(): total_contrib = sum((p.Ana_contribution or 0) for p in group_players) n = len(group_players) individual_share = total_contrib * MULTIPLIER / n for p in group_players: endow = p.participant.vars.get('Ana_Endowment', 0) or 0 round_payoff = endow - (p.Ana_contribution or 0) + individual_share p.payoff = round_payoff # Accumulate PGG payoffs keyed by display round number display_round = p.round_number pgg_payoffs = p.participant.vars.setdefault('pgg_payoffs_by_display_round', {}) pgg_payoffs[display_round] = round_payoff # Calculate punishment points received for group_players in pg_groups.values(): id_map = {p.participant.vars.get('my_order'): p for p in group_players} for p in group_players: received = 0 suffix = bucket_suffix(p.Ana_contribution) my_order = p.participant.vars.get('my_order') if my_order == 1: m2 = id_map.get(2) m3 = id_map.get(3) if m2: received += m2.participant.vars.get(f'Ana_mmb1_{suffix}', 0) or 0 if m3: received += m3.participant.vars.get(f'Ana_mmb1_{suffix}', 0) or 0 elif my_order == 2: m1 = id_map.get(1) m3 = id_map.get(3) if m1: received += m1.participant.vars.get(f'Ana_mmb2_{suffix}', 0) or 0 if m3: received += m3.participant.vars.get(f'Ana_mmb2_{suffix}', 0) or 0 elif my_order == 3: m1 = id_map.get(1) m2 = id_map.get(2) if m1: received += m1.participant.vars.get(f'Ana_mmb3_{suffix}', 0) or 0 if m2: received += m2.participant.vars.get(f'Ana_mmb3_{suffix}', 0) or 0 p.Ana_punishpoints_received = received p.participant.vars['Ana_punishpoints_received'] = received class PGGamep2_G1(Page): @staticmethod def is_displayed(player): return (1 <= player.round_number <= Round_Per_Gen and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") @staticmethod def vars_for_template(player): # Get group members group_members = [ p for p in player.subsession.get_players() if p.participant.vars.get('Ana_GroupID') == player.participant.vars.get('Ana_GroupID') ] id_map = {p.participant.vars.get('my_order'): p for p in group_members} # Get contributions mmb1 = id_map.get(1) mmb2 = id_map.get(2) mmb3 = id_map.get(3) Ana_Ctbt_Mmb1 = mmb1.Ana_contribution if mmb1 else 0 Ana_Ctbt_Mmb2 = mmb2.Ana_contribution if mmb2 else 0 Ana_Ctbt_Mmb3 = mmb3.Ana_contribution if mmb3 else 0 return { 'Ana_generation': player.participant.vars.get('Ana_generation'), 'Ana_own_id': player.participant.vars.get('Ana_own_id'), 'Ana_family_assignment': player.participant.vars.get('Ana_family_assignment'), 'round_number': player.round_number, 'Ana_EndowmentType': player.participant.vars.get('Ana_EndowmentType'), 'Ana_Endowment': player.participant.vars.get('Ana_Endowment'), 'payoff': player.payoff, 'Ana_Ctbt_Mmb1': Ana_Ctbt_Mmb1, 'Ana_Ctbt_Mmb2': Ana_Ctbt_Mmb2, 'Ana_Ctbt_Mmb3': Ana_Ctbt_Mmb3, 'Ana_punishpoints_received': player.Ana_punishpoints_received, } class EndofPG_G1(Page): @staticmethod def is_displayed(player): return (player.round_number == Round_Per_Gen and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") class PostGameFairIntro(Page): """Introduction page for post-game fairness assessment""" @staticmethod def is_displayed(player): return (player.round_number == Round_Per_Gen and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") class PostGameFairDisapproval(Page): """Elicit opinions on fair level of disapproval after playing the game""" form_model = 'player' @staticmethod def is_displayed(player): return (player.round_number == Round_Per_Gen and player.participant.vars.get('Ana_generation') == 1 and player.participant.vars.get('state') == "active") @staticmethod def get_form_fields(player): """Return all fair disapproval fields for both endowment scenarios""" Ana_Endowment = player.participant.vars.get('Ana_Endowment') if Ana_Endowment == 30: return ['Ana_fair_high_3', 'Ana_fair_high_6', 'Ana_fair_high_9', 'Ana_fair_high_12', 'Ana_fair_high_15', 'Ana_fair_high_18', 'Ana_fair_high_21', 'Ana_fair_high_24', 'Ana_fair_high_27', 'Ana_fair_high_30'] else: return ['Ana_fair_low_3', 'Ana_fair_low_6', 'Ana_fair_low_9', 'Ana_fair_low_12', 'Ana_fair_low_15'] @staticmethod def before_next_page(player: Player, timeout_happened=False): pass @staticmethod def vars_for_template(player): return { 'Ana_generation': player.participant.Ana_generation, 'Ana_own_id': player.participant.Ana_own_id, 'Ana_family_assignment': player.participant.Ana_family_assignment, 'round_number': player.round_number - Round_FirstTask + 1, 'Ana_EndowmentType': player.participant.vars.get('Ana_EndowmentType'), 'Ana_Endowment': player.participant.vars.get('Ana_Endowment'), 'Ana_RankingType': player.participant.vars.get('Ana_RankingType'), } page_sequence = [ BeliefIntro, BeliefElicitation, FairDisapproval, BeliefOutro, WaitForPG_G1, Punishment_G1, PGGamep1_G1, WaitForGeneration1, PGGamep2_G1, PostGameFairIntro, PostGameFairDisapproval, EndofPG_G1 ]