From e76f4b65668b6416d6ec2e6b375f5b7e2e1f5810 Mon Sep 17 00:00:00 2001 From: Barak Michener Date: Mon, 6 Jan 2014 18:06:35 -0500 Subject: [PATCH] in progress --- models/default_model.py | 178 +++++++++++++++++++++++++++++++++++------------- tim.py | 15 +++- 2 files changed, 142 insertions(+), 51 deletions(-) diff --git a/models/default_model.py b/models/default_model.py index 6447353..d736b4e 100644 --- a/models/default_model.py +++ b/models/default_model.py @@ -39,6 +39,13 @@ class BaseModel(object): def player_role(self, player): return self.game.player_role(self.deal, player) + def get_id_for_role(self, role): + roles = [x[0] for x in self.deal] + try: + return roles.index(role) + except Exception: + return -1 + # Override these! def player_sees_player_and_claims(self, p1, p2, claim, rnd): return True @@ -59,14 +66,21 @@ class DefaultModel(BaseModel): self.mission_ducks_on_round[0] = Bernoulli(0.5) self.mission_ducks_on_round[1] = Bernoulli(0.5) self.mission_ducks_on_round[2] = Bernoulli(0.5) - self.mission_ducks_on_round[3] = Bernoulli(0.0) - self.mission_ducks_on_round[4] = Bernoulli(0.0) + self.early_spy_duck = Bernoulli(0.3) + self.multiple_spy_one_duck = Bernoulli(0.15) self.ignorance_on_round = [None] * 5 self.ignorance_on_round[0] = Bernoulli(0.9) self.ignorance_on_round[1] = Bernoulli(0.7) self.ignorance_on_round[2] = Bernoulli(0.5) self.ignorance_on_round[3] = Bernoulli(0.3) self.ignorance_on_round[4] = Bernoulli(0.3) + self.spy_vote_duck_on_round = [None] * 5 + self.spy_vote_duck_on_round[0] = Bernoulli(0.9) + self.spy_vote_duck_on_round[1] = Bernoulli(0.7) + self.spy_vote_duck_on_round[2] = Bernoulli(0.5) + self.spy_vote_duck_on_round[3] = Bernoulli(0.3) + self.spy_vote_duck_on_round[4] = Bernoulli(0.3) + self.multiple_spy_vote_duck = Bernoulli(0.75) self.merlin_ignorance = Bernoulli(0.2) def player_sees_player_and_claims(self, p1, p2, claim, rnd): @@ -85,29 +99,53 @@ class DefaultModel(BaseModel): n_actually_good_people = sum( [int(self.is_good(x, rnd)) for x in team]) n_spies = len(team) - n_actually_good_people + spy_names = [self.player_role(x) for x in team if self.is_good(x, rnd)] + if fails > n_spies: + return None if n_spies == 0: if fails != 0: return None else: return True else: + # There's at least one spy. if fails == 0: + # They obviously did duck. if must_fail: return None - duck = False - for i in range(n_spies - fails): - duck = duck or self.mission_ducks_on_round[rnd].rand() - return duck - else: - if fails > n_spies: + if n_spies > 1: + return not self.multiple_spy_one_duck.rand() + if rnd >= 0 and rnd < 3: + return self.mission_ducks_on_round[rnd].rand() + elif rnd == 3: + # They always duck on 4 + return True + elif rnd == 4: + # They never duck on 5 return None + elif fails == 1 and n_spies == 1: + # One fail, one spy. + spy = spy_names[0] + if rnd >= 0 and rnd < 3: + return self.mission_ducks_on_round[rnd].rand() + elif rnd == 3: + if spy == "Oberon": + return True + if spy == "GLance": + return True + return False + elif rnd == 4: + return True + elif fails < n_spies: + return self.multiple_spy_one_duck.rand() + elif fails > 1: + # collision! return True + else: + return True + return True def votes(self, team, votes, fail_req, rnd): - n_actually_good_people = sum( - [int(self.is_good(x, rnd)) for x in team]) - n_spies = len(team) - n_actually_good_people - could_happen = True for player, vote in enumerate(votes): role = self.player_role(player) if role in special_votes: @@ -116,35 +154,45 @@ class DefaultModel(BaseModel): continue else: return False - elif player in team: - continue - elif self.is_good(player, rnd): - if n_spies > fail_req - 1: - if vote == 1: - if self.ignorance_on_round[rnd].rand(): - continue - else: - return False - else: - if vote == 0: - if self.ignorance_on_round[rnd].rand(): - continue - else: - return False - else: - if n_spies < fail_req: - if vote == 1: - if self.ignorance_on_round[rnd].rand(): - continue - else: - return False - else: - if vote == 0: - if self.ignorance_on_round[rnd].rand(): - continue - else: - return False - return could_happen + else: + if default_vote(self, player, team, votes, + fail_req, rnd): + continue + else: + return False + return True + + +def default_vote(game, player, team, votes, fail_req, rnd): + n_actually_good_people = sum( + [int(game.is_good(x, rnd)) for x in team]) + n_spies = len(team) - n_actually_good_people + if player in team: + return True + if game.is_good(player, rnd): + if n_spies > fail_req - 1: + # Bad Team! + if votes[player] == 1: + return game.ignorance_on_round[rnd].rand() + else: + return True + else: + # Good Team! + if votes[player] == 0: + return game.ignorance_on_round[rnd].rand() + else: + return True + else: + if n_spies < fail_req: + if votes[player] == 1: + return not game.spy_vote_duck_on_round[rnd].rand() + else: + return game.spy_vote_duck_on_round[rnd].rand() + elif n_spies == fail_req: + return True + elif n_spies > fail_req: + return game.multiple_spy_vote_duck.rand() + return True def merlin_vote(model, player_id, team, votes, fail_req, r): @@ -169,14 +217,18 @@ def merlin_vote(model, player_id, team, votes, fail_req, r): elif n_spies == 1: # He'll either duck or vote it down. Either is fine return True - elif n_spies > 1 and fail_req == 1 and r > 2: - # Even a well-played Merlin would never allow two spies on. - # Unless there's more than one fail required. Then he might - # duck. - if votes[player_id] == 0: - return True + elif n_spies > 1 and fail_req == 1: + # Merlin wants spies to be butting heads. if votes[player_id] == 1: + # Voted down an apparently good team. Ignore this. + return True + if votes[player_id] == 0: + if model.merlin_ignorance.rand(): + return True return False + elif n_spies > 1 and fail_req > 1: + # Ignore the vote here + return True return True @@ -214,7 +266,37 @@ def mordred_vote(game, player_id, team, votes, fail_req, r): return False return True + +def guen_vote(game, player_id, team, votes, fail_req, rnd): + glance = game.get_id_for_role("GLance") + elance = game.get_id_for_role("ELance") + if elance == -1 or glance == -1: + return default_vote(game, player_id, team, votes, fail_req, rnd) + if glance in team and elance in team: + if votes[player_id] == 1: + return False + else: + return True + else: + return default_vote(game, player_id, team, votes, fail_req, rnd) + + +def percy_vote(game, player_id, team, votes, fail_req, rnd): + morgana = game.get_id_for_role("Morgana") + merlin = game.get_id_for_role("Merlin") + if merlin == -1 or morgana == -1: + return default_vote(game, player_id, team, votes, fail_req, rnd) + if merlin in team and morgana in team: + if votes[player_id] == 1: + return False + else: + return True + else: + return default_vote(game, player_id, team, votes, fail_req, rnd) + special_votes = { "Merlin": merlin_vote, - "Mordred": mordred_vote + "Mordred": mordred_vote, + "Guen": guen_vote, + "Percy": percy_vote } diff --git a/tim.py b/tim.py index aaa3eb7..2e0e815 100644 --- a/tim.py +++ b/tim.py @@ -215,6 +215,10 @@ class DeceptionGame(object): progressbar.Bar(marker="*"), " ", progressbar.ETA()]) for i in progress(range(length)): + #print len(deck) + falses = 0 + trues = 0 + nones = 0 for deal in deck: f_list = [] for obs in self.observations: @@ -227,20 +231,25 @@ class DeceptionGame(object): if out is None: is_bad = True dont_copy = True + nones += 1 break if out is True: + trues += 1 continue if out is False: is_bad = True - continue - + falses += 1 + break if not is_bad: if deal not in trace: - trace[deal] = 0 + trace[deal] = 1 trace[deal] += 1 if not dont_copy: new_deck.append(deal) deck = new_deck + #print falses, + #print trues, + #print nones new_deck = [] self.trace = trace