tim-the-enchanter/models/probs_from_game.py

199 lines
8.4 KiB
Python

from collections import defaultdict as dd
import json
roles = [u'oberon', u'merlin', u'mordred', u'morgana', u'percival', u'assassin']
ANY_GOOD = [u'merlin', u'percival', u'good']
ANY_EVIL = [u'oberon', u'mordred', u'morgana', u'assassin', u'evil']
def isSpy(x, game):
return game["players"][x]["spy"]
def approval(x):
if x[0] + x[1] == 0:
return 0.0
return (x[0] * 1.0) / (x[0] + x[1])
def getRole(x, game):
if str(x) not in game["role_by_seat"]:
if isSpy(x, game):
return "evil"
return "good"
return game["role_by_seat"][str(x)]
def sumKeys(a, b):
return (a[0] + b[0], a[1] + b[1])
def sum_helper(table, constraint_list, keys=["Approve", "Reject"]):
if len(constraint_list) == 0:
return (table[keys[0]], table[keys[1]])
c = constraint_list[0]
out = dd(int)
if isinstance(c, type([])):
for v in c:
out = sumKeys(out, sum_helper(table[v], constraint_list[1:]))
elif c is None:
for k in table:
out = sumKeys(out, sum_helper(table[k], constraint_list[1:]))
else:
return sumKeys(out, sum_helper(table[c], constraint_list[1:]))
return out
class TrainTable(object):
"""Docstring for TrainTable. """
# good: round, vote, proposer_role, evils on team
def __init__(self, path):
self.good_vote = dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(int))))))
self.percy_vote = dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(int)))))))
self.merlin_vote = dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(int)))))))
self.evil_vote = dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(int))))))
self.morgana_vote = dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(int))))))
self.assassin_vote = dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(int))))))
self.oberon_vote = dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(int))))))
self.mordred_vote = dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(lambda: dd(int))))))
self._path = path
self._build_prob_table()
def GoodVote(self, round=None, vote=None, proposer_role=None, evil_count=None, size=None):
return sum_helper(self.good_vote, [size, round, vote, proposer_role, evil_count])
def PercivalVote(self, round=None, vote=None, proposer_role=None, evil_count=None, team_contains=None, size=None):
return sum_helper(self.percy_vote, [size, round, vote, proposer_role, evil_count, team_contains])
def EvilVote(self, round=None, vote=None, proposer_role=None, evil_count=None, size=None):
return sum_helper(self.evil_vote, [size, round, vote, proposer_role, evil_count])
def MordredVote(self, round=None, vote=None, proposer_role=None, evil_count=None, size=None):
return sum_helper(self.mordred_vote, [size, round, vote, proposer_role, evil_count])
def MorganaVote(self, round=None, vote=None, proposer_role=None, evil_count=None, size=None):
return sum_helper(self.morgana_vote, [size, round, vote, proposer_role, evil_count])
def AssassinVote(self, round=None, vote=None, proposer_role=None, evil_count=None, size=None):
return sum_helper(self.asassin_vote, [size, round, vote, proposer_role, evil_count])
def OberonVote(self, round=None, vote=None, proposer_role=None, evil_count=None, size=None):
return sum_helper(self.oberon_vote, [size, round, vote, proposer_role, evil_count])
def MerlinVote(self, round=None, vote=None, proposer_role=None, evil_count=None, known_evil=None, size=None):
return sum_helper(self.merlin_vote, [size, round, vote, proposer_role, evil_count, known_evil])
def _build_prob_table(self):
f = open(self._path)
self._data = json.load(f)
f.close()
self._build_good_vote(self.good_vote, "good")
self._build_percy_vote(self.percy_vote)
self._build_merlin_vote(self.merlin_vote)
self._build_evil_vote(self.evil_vote, "evil")
self._build_evil_vote(self.mordred_vote, "mordred")
self._build_evil_vote(self.morgana_vote, "morgana")
self._build_evil_vote(self.assassin_vote, "assassin")
self._build_evil_vote(self.oberon_vote, "oberon")
def _build_good_vote(self, table, exprole):
for game in self._data:
size = len(game["players"])
for player in game["players"]:
idx = player["seat"]
if player["spy"]:
continue
if getRole(idx, game) != exprole:
continue
for round_n, round in enumerate(game["log"]):
for vote_n in range(1, 6):
if str(vote_n) not in round:
break
vote = round[str(vote_n)]
prole = getRole(vote["proposer"], game)
if vote["proposer"] == idx:
prole = "self"
evils = sum([int(isSpy(x, game)) for x in vote["team"]])
action = vote["votes"][idx]
table[size][round_n + 1][vote_n][prole][evils][action] += 1
def _build_evil_vote(self, table, exprole):
for game in self._data:
size = len(game["players"])
for player in game["players"]:
idx = player["seat"]
if not player["spy"]:
continue
if getRole(idx, game) != exprole:
continue
for round_n, round in enumerate(game["log"]):
for vote_n in range(1, 6):
if str(vote_n) not in round:
break
vote = round[str(vote_n)]
prole = getRole(vote["proposer"], game)
if vote["proposer"] == idx:
prole = "self"
evils = sum([int(isSpy(x, game)) for x in vote["team"]])
action = vote["votes"][idx]
table[size][round_n + 1][vote_n][prole][evils][action] += 1
def _build_percy_vote(self, table):
for game in self._data:
size = len(game["players"])
for player in game["players"]:
idx = player["seat"]
if player["spy"]:
continue
if getRole(idx, game) != "percival":
continue
for round_n, round in enumerate(game["log"]):
for vote_n in range(1, 6):
if str(vote_n) not in round:
break
vote = round[str(vote_n)]
prole = getRole(vote["proposer"], game)
evils = sum([int(isSpy(x, game)) for x in vote["team"]])
action = vote["votes"][idx]
tc = ""
rolesOnTeam = [getRole(x, game) for x in vote["team"]]
if "merlin" in rolesOnTeam:
tc += "merlin"
if "morgana" in rolesOnTeam:
tc += "morgana"
if tc == "":
tc = "neither"
table[size][round_n + 1][vote_n][prole][evils][tc][action] += 1
def _build_merlin_vote(self, table):
for game in self._data:
size = len(game["players"])
for player in game["players"]:
idx = player["seat"]
if player["spy"]:
continue
if getRole(idx, game) != "merlin":
continue
for round_n, round in enumerate(game["log"]):
for vote_n in range(1, 6):
if str(vote_n) not in round:
break
vote = round[str(vote_n)]
prole = getRole(vote["proposer"], game)
evils = sum([int(isSpy(x, game)) for x in vote["team"]])
action = vote["votes"][idx]
known_evils = sum([int(isSpy(x, game) and (getRole(x, game) != "mordred")) for x in vote["team"]])
table[size][round_n + 1][vote_n][prole][evils][known_evils][action] += 1
def main():
table = TrainTable("dataset.json")
if __name__ == '__main__':
main()