source: main.py

Last change on this file was 10, checked in by David Owen <dsowen@fugue88.ws>, 8 years ago

Run a controlled AI trial, 1000 rounds

  • Property executable set to True
File size: 5.5 KB
Line 
1#!/usr/bin/python3
2
3from random import shuffle
4
5from player import Player
6import ai
7
8
9def spies_for_players(player_count):
10    return {
11        5: 2,
12        6: 2,
13        7: 3,
14        8: 3,
15        9: 3,
16        10: 4
17    }[player_count]
18
19
20def mission_size(player_count, mission_num):
21    return {
22        5: [2, 3, 2, 3, 3],
23        6: [2, 3, 4, 3, 4],
24        7: [2, 3, 3, 4, 4],
25        8: [3, 4, 4, 5, 5],
26        9: [3, 4, 4, 5, 5],
27        10: [3, 4, 4, 5, 5]
28    }[player_count][mission_num - 1]
29
30
31def required_failures(player_count, mission_num):
32    if mission_num == 4 and player_count >= 7:
33        return 2
34    else:
35        return 1
36
37
38class Shared(object):
39
40    def __init__(self, player_count, players, role_deck):
41        self.player_count = player_count
42        self.players = players
43        self.role_deck = role_deck
44        self.mission = 0
45        self.captain = 0
46        self.team_failures = 0
47        self.wins = 0
48        self.losses = 0
49
50    def current_mission_size(self):
51        team_size = mission_size(self.player_count, self.mission)
52        print("Mission {} needs {} members".format(self.mission, team_size))
53        return team_size
54
55    def next_mission(self):
56        self.mission += 1
57
58    def get_proposed_team(self, team_size):
59        print("Captain is {}".format(self.captain))
60        team = self.players[self.captain].propose_team(team_size)
61        print("He proposed {}".format(team))
62        return team
63
64    def next_team_captain(self):
65        self.captain = (self.captain + 1) % self.player_count
66
67    def reset_team_failures(self):
68        self.team_failures = 0
69
70    def record_team_failure(self):
71        self.team_failures += 1
72
73    def get_mission_failures(self, team):
74        failures = 0
75        for i in team:
76            if self.role_deck[i] == "SPY":
77                if not self.players[i].perform_mission():
78                    failures = failures + 1
79        return failures
80
81    def required_failures(self):
82        return required_failures(self.player_count, self.mission)
83
84    def mission_succeeded(self):
85        print("Mission succeeded")
86        self.wins += 1
87
88    def mission_failed(self, failures):
89        print("Mission had {} failures".format(failures))
90        self.losses += 1
91
92    def game_over(self):
93        if self.team_failures == 5:
94            print("The spies won!")
95            for p in self.players:
96                p.observe_game(False)
97            return True
98        elif self.wins >= 3:
99            print("The Resistance won!")
100            for p in self.players:
101                p.observe_game(True)
102            return True
103        elif self.losses >= 3:
104            print("The Spies won!")
105            for p in self.players:
106                p.observe_game(False)
107            return True
108        else:
109            return False
110
111    def winner(self):
112        if self.team_failures == 5:
113            return "SPIES"
114        elif self.wins >= 3:
115            return "RESISTANCE"
116        elif self.losses >= 3:
117            return "SPIES"
118
119
120class AdvanceMission(object):
121
122    def __init__(self, shared):
123        self.shared = shared
124
125    def do(self):
126        self.shared.next_mission()
127        team_size = self.shared.current_mission_size()
128        return AssembleTeam(self.shared, team_size)
129
130
131class AssembleTeam(object):
132
133    def __init__(self, shared, team_size):
134        self.shared = shared
135        self.team_size = team_size
136
137    def do(self):
138        team = self.shared.get_proposed_team(self.team_size)
139
140        votes = [p.approve_team(team) for p in self.shared.players]
141        approvals = sum(votes)
142        approved = approvals > self.shared.player_count / 2
143
144        print("Team {}: {} for, {} against".format(
145            {True: "approved", False: "rejected"}[approved],
146            approvals, self.shared.player_count - approvals
147        ))
148
149        for p in self.shared.players:
150            p.observe_team_vote(approved, votes)
151
152        self.shared.next_team_captain()
153
154        if approved:
155            self.shared.reset_team_failures()
156            return PerformMission(self.shared, team)
157        else:
158            self.shared.record_team_failure()
159            return AssembleTeam(self.shared, self.team_size)
160
161
162class PerformMission(object):
163
164    def __init__(self, shared, team):
165        self.shared = shared
166        self.team = team
167
168    def do(self):
169        failures = self.shared.get_mission_failures(self.team)
170        success = failures < self.shared.required_failures()
171
172        for p in self.shared.players:
173            p.observe_mission(success, failures)
174
175        if success:
176            self.shared.mission_succeeded()
177        else:
178            self.shared.mission_failed(failures)
179
180        return AdvanceMission(self.shared)
181
182
183def main(player_count):
184    spy_count = spies_for_players(player_count)
185    resistance_count = player_count - spy_count
186    print("Will have {} spies and {} resistance".format(spy_count, resistance_count))
187    role_deck = ["RES"] * resistance_count + ["SPY"] * spy_count
188    shuffle(role_deck)
189    print(role_deck)
190    players = [Player(player_count, i, r) if r == "SPY"
191               else ai.Player(player_count, i, r)
192               for i, r in enumerate(role_deck)]
193
194    spy_nums = [i for i, r in enumerate(role_deck) if r == "SPY"]
195
196    for i, r in enumerate(role_deck):
197        if r == "SPY":
198            players[i].reveal_spies(spy_nums)
199
200    shared = Shared(player_count, players, role_deck)
201    state = AdvanceMission(shared)
202
203    while not shared.game_over():
204        state = state.do()
205
206    return shared.winner()
207
208
209if __name__ == '__main__':
210    main(10)
Note: See TracBrowser for help on using the repository browser.