import numpy as np # ── Experiment Parameters ────────────────────────────────────────── SEED = 59 N_MAX_GROUPS = 10 # pre-generate for up to 10 simultaneous groups N_BLOCKS = 6 N_ROUNDS_PER_BLOCK = 20 N_MEMBERS = 9 NOISE_RANGE = 10 # noise ~ Uniform[-NOISE_RANGE, NOISE_RANGE] integer TOTAL_ROUNDS = N_BLOCKS * N_ROUNDS_PER_BLOCK # 180 # Payment parameters POINTS_PER_DOLLAR = 200 # how many points equal $1 REAL_WORLD_CURRENCY_PER_POINT = 1 / POINTS_PER_DOLLAR PARTICIPATION_FEE = 7.00 # USD # Venmo handle (without @) — update before running sessions VENMO_ACCOUNT = 'YOUR_VENMO_HANDLE' # Center-point values: one per player position, consistent with 9-member groups CTR_POINT_VALUES = [10, 20, 30, 40, 50, 60, 70, 80, 90] # ── Pre-generated Random Data ────────────────────────────────────── np.random.seed(SEED) # CTR_POINTS[g][b][p] # g = group index (0-based) # b = block index (0-based) # p = player position within group (0-based, matches id_in_group - 1) # # Each (group, block) is an independent random permutation of CTR_POINT_VALUES, # so every center-point value appears exactly once per group per block. CTR_POINTS = [ [ [int(x) for x in np.random.permutation(CTR_POINT_VALUES)] for _ in range(N_BLOCKS) ] for _ in range(N_MAX_GROUPS) ] # NOISE_VALS[g][b][r][p] # r = round index within block (0-based) # # Drawn from Uniform[-NOISE_RANGE, NOISE_RANGE] integer. # ideal_point = ctr_point + noise (clipped to [0, 100] at display/payoff time). NOISE_VALS = [ [ [ [int(x) for x in np.random.randint(-NOISE_RANGE, NOISE_RANGE + 1, size=N_MEMBERS)] for _ in range(N_ROUNDS_PER_BLOCK) ] for _ in range(N_BLOCKS) ] for _ in range(N_MAX_GROUPS) ] # POLICIES[g][b][r] = (policy_A, policy_B) # Generated per group, because bounds depend on that group's ideal points. # # Mirrors simulation logic: # max_L = max ideal_point across all 9 players in this (group, block, round) # min_R = min ideal_point across all 9 players in this (group, block, round) # policy_A ~ Uniform[0, max_L) (i.e. randint(0, max_L)) # policy_B ~ Uniform[max(min_R, pA+1), 101) # # Both ideal_point = ctr_point + noise are computed from the pre-generated # CTR_POINTS and NOISE_VALS above (same seed, so consistent). POLICIES = [] for _g in range(N_MAX_GROUPS): _group_policies = [] for _b in range(N_BLOCKS): _block_policies = [] for _r in range(N_ROUNDS_PER_BLOCK): _ideal_pts = [ CTR_POINTS[_g][_b][_p] + NOISE_VALS[_g][_b][_r][_p] for _p in range(N_MEMBERS) ] _max_L = max(_ideal_pts) _min_R = min(_ideal_pts) # Ensure max_L >= 1 so randint(0, max_L) is valid _max_L = max(_max_L, 1) _pA = int(np.random.randint(0, _max_L)) _lo = max(_min_R, _pA + 1) # Ensure upper bound > lower bound _lo = min(_lo, 100) _pB = int(np.random.randint(_lo, 101)) _block_policies.append((_pA, _pB)) _group_policies.append(_block_policies) POLICIES.append(_group_policies)