forked from iSchool-590PR-2019-Spring/Final_Project
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTournament.py
161 lines (131 loc) · 6 KB
/
Tournament.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import random
import pandas as pd
import Game
import Player
import Strategy
# a list of all strategies, to be used to build a player's list
allStrategies = [Strategy.AlwaysCooperate, Strategy.AlwaysDefect, Strategy.Random, Strategy.TitForTat,
Strategy.TitForTwoTats, Strategy.TwoTitsForTat, Strategy.FirmButFair,
Strategy.SuspiciousTitForTat, Strategy.HardTitForTat, Strategy.ReverseTitForTat,
Strategy.GrimTrigger, Strategy.SoftGrudger, Strategy.Gradual, Strategy.Pavlov,
Strategy.SoftMajority, Strategy.HardMajority]
# function to create player list out of how many times each strategy should appear
def create_playerlist(strategies: dict):
"""Generate a list of players based on some number of each strategy
:param strategies: dictionary of form {Strategy.strategyname: #PlayersPerStrategy}
:return: dictionary consisting of form {playername: playerObject}
>>> stratlist = {Strategy.AlwaysCooperate: 2, Strategy.AlwaysDefect: 2}
>>> playerlist = create_playerlist(stratlist)
>>> len(playerlist)
4
"""
players = {}
for strat, number in strategies.items():
for num in range(number):
p = Player.Player(strategy=strat)
players[p.name] = p
return players
# function to create player list based on list of strategies
def create_randomized_playerlist(strategies: list, min: int, max: int):
"""
Generate a list of players given a list of strategies,
where each strategy will occur some number of times between the min and max
:param strategies: a list of strategies to be used
:param min: the minimum number of times the strategy will occur in the player list
:param max: the maximum number of times the strategy will occur in the player list
:return: a dictionary player list that can be used by the play_tournament function
"""
# create dictionary of form {Strategy.strategyname: #PlayersPerStrategy} from strategy list
strategydict = {}
for strategy in strategies:
strategydict[strategy] = random.randint(min, max)
# create dictionary of form {playername: playerObject} from strategy dictionary
playerlist = create_playerlist(strategydict)
return playerlist
# function to play tournament and generate list of all player stats for each game
def play_tournament(players, numrounds=100, noisegrowth=0.01, noisemax=0.5, mode='I'):
"""
Play a tournament in which each player plays a game against every other player.
:param players: a dictionary of form {'playername': playerObject}
:param numrounds: number of rounds played for each game
:param noisegrowth: maximum amount noise can grow/reduce each round
:param noisemax: maximum level of noise in game
:param mode: set mode of game to misimplementation (I) or misperception (P)
:return: a list of all players, each player has a dict with id and stats
>>> stratlist = {Strategy.AlwaysCooperate: 1, Strategy.AlwaysDefect: 1}
>>> playerlist = create_playerlist(stratlist)
>>> t = play_tournament(playerlist, noisemax=0)
>>> len(t)
2
>>> p1 = t[0]
>>> p1['strategy']
'AllC'
>>> p1['winRate']
0.0
>>> p1['scoreAvg']
0.0
"""
games = []
# play the tournament
for p1 in players:
thisplayer = players[p1]
for p2 in players:
if players[p2] == thisplayer:
break
else:
otherplayer = players[p2]
game = Game.Game(thisplayer, otherplayer, numrounds, noisegrowth, noisemax)
game.set_mode(mode)
game.play_game()
games.append(game)
numgames = len(players) - 1
# collect the stats on each player
allplayers = []
for player in players.values():
playerdict = {}
playerdict['id'] = player.name
playerdict['strategy'] = player.strategy.id
playerdict['scoreAvg'] = player.points / numgames
playerdict['winRate'] = player.wins / numgames
playerdict['lossRate'] = player.losses / numgames
playerdict['tieRate'] = player.ties / numgames
allplayers.append(playerdict)
# reset stats for each player
player.points = 0
player.wins = 0
player.losses = 0
player.ties = 0
return allplayers
def run_MCsim(players: dict, times=1000, filename: str = None, numrounds=100, noisegrowth=0.01, noisemax=0.5, mode='I'):
"""
run the monte carlo simulation and export the results to a csv file
:param players: players that will be in each tournament
:param times: how many times the tournament will be run
:param filename: name of the csv file results will be exported to (in Results folder) - don't include '.csv'.
If a filename is not specified, it will return the pandas dataframe.
:param numrounds: number of rounds played in each game
:param noisegrowth: max noise increment
:param noisemax: max noise per game
:param mode: game calculates scores based on real plays (misperception, 'P') or noisy plays (misimplementation, 'I')
"""
tCount = 0
AllTournamentStats = []
for t in range(times):
tCount += 1
tournament = play_tournament(players, numrounds, noisegrowth, noisemax, mode)
for player in tournament:
tstats = {}
tstats['TournamentID'] = tCount
tstats['PlayerID'] = player['id']
tstats['PlayerStrategy'] = player['strategy']
tstats['PlayerScore'] = player['scoreAvg']
tstats['PlayerWinRate'] = player['winRate']
tstats['PlayerLossRate'] = player['lossRate']
tstats['PlayerTieRate'] = player['tieRate']
AllTournamentStats.append(tstats)
results = pd.DataFrame(AllTournamentStats)
results = results[['TournamentID', 'PlayerID', 'PlayerStrategy', 'PlayerScore', 'PlayerWinRate', 'PlayerLossRate', 'PlayerTieRate']]
if filename is None:
return results
else:
results.to_csv('Results/' + filename + '.csv', index=False)