repl.it
Python

No description

fork
loading
Files
  • main.py
  • Packager files
  • requirements.txt
main.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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
import math
import random
from collections import namedtuple
from sty import fg, bg, ef, rs

INTRO = """
You are a secret government agent making the final preparations for you and your team's upcoming mission. You have only three more tasks to complete: install armor plating on your vehicle, crate the materials you need to make a base of operations, and take final inventory of your munitions. An impossible task for a single person, but easy with the help of your team.

You've just recieved word from HQ that a member of your team has alined themself with the rebels! You must find this traitor before they jepordize the mission.

You know that this traitor wont try to sabatoge anything if you work on his team. But you also know that putting everyone on the same team will only arouse suspition. Remember your training agent! Only assign yourself to a group a quarter of your team's total size.

Finish your tasks, and keep an eye out for the traitor. Good luck.
(Press Enter to continue.)
"""

TRAITS = {
  "FIRST_NAMES": ("David", "Michael", "John", "James", "Robert", "Mark", "William", "Richard", "Thomas", "Steven", "Mary", "Susan", "Maria", "Karen", "Lisa", "Linda", "Donna", "Patricia", "Debra", "Deborah"),
  "LAST_NAMES": ("Smith", "Johnson", "Williams", "Jones", "Brown", "Davis", "Miller","Wilson", "Moore", "Taylor", "Anderson", "Thomas", "Jackson", "White", "Harris"),
  "GENDER": ("M", "F", "X"),
  "PERSONALITY": ("Adaptable", "Adventurous", "Affectionate", "Aloof", "Arrogant", "Ambitious", "Courageous", "Compulsive", "Deceitful", "Diligent", "Frank", "Flamboyant", "Lethargic", "Sneaky")
}

class Character():
  def __init__(self, traits_pool):
    self.first_name = random.choice(traits_pool["FIRST_NAMES"])
    self.last_name = random.choice(traits_pool["LAST_NAMES"])
    self.gender = random.choice(traits_pool["GENDER"])
    self.personality = random.sample(traits_pool["PERSONALITY"], 2)
    self.traitor = False;

  def name_str(self):
    return ef.b + fg.green + self.first_name + " " + self.last_name + rs.all

  def profile_str(self):
    return self.name_str() + '\n' + ef.b + "Gender: " + rs.bold_dim + self.gender + '\n' + ef.b + "Personality: " + rs.bold_dim + str(self.personality)


class PlayerCharacter(Character):
  def __init__(self):
    self.fist_name = "You"
    self.last_name = ""
    self.gender = None
    self.personality = []
    self.traitor = False;
  
  def name_str(self):
    return ef.i + "You" + rs.all
  
  def profile_str(self):
    return ef.i + "You look into a mirror and see yourself" + rs.all


class WorkPhase():
  """
  assignments - A map of task ids to a list of person ids
  """
  def __init__(self):
    self.assignments = {}

    self._command_map = {
      "help": self._cmd_help,
      "profile": self._cmd_profile,
      "assign": self._cmd_assign,
      "list": self._cmd_list,
      "continue": self._cmd_continue
    }
  
  def _cmd_help(self, game):
    print("assign [person number] [task number] - Assign a person to a task")
    print("profile [person number] - View a team members profile")
    print("list [team, task] - List your tasks or your team")
    print("continue - begins the next day")
    print("help - display this message")

  def _cmd_profile(self, game, char_id):
    try:
      print(game.team[int(char_id)].profile_str())
    except IndexError:
      print("Invalid person")
  
  def _cmd_assign(self, game, person_id_str, task_id_str):
    person_id = int(person_id_str)
    task_id = int(task_id_str)

    # Ensure person exists
    if person_id >= len(game.team):
      print("Invalid person!")
      return

    # Ensure task exists
    if task_id >= len(game.tasks):
      print("Invalid task!")
      return

    # Check that the person is not assigned anywhere else
    # If they are, remove them first
    for k, v in self.assignments.items():
      if person_id in v:
        self.assignments[k].remove(person_id)

    # Check if entry exists in map
    if task_id not in self.assignments:
      self.assignments[task_id] = [person_id]
      print("Assigned " + game.team[person_id].name_str() + " to task " + task_id_str)

    elif person_id not in self.assignments[task_id]:
      # Special case for PC
      if isinstance(game.team[person_id], PlayerCharacter) and len(self.assignments[task_id]) >= math.floor(len(game.team) / 4):
        print("Remember your training agent! You can't assign yourself to groups larger than 25% of your team!")
        return

      self.assignments[task_id].append(person_id)
      print("Assigned " + game.team[person_id].name_str() + " to task " + task_id_str)

  def _cmd_list(self, game, subcmd):
    if subcmd == "team":
      game.print_team()
    elif subcmd == "task":
      # Header
      print(ef.b + fg.red + "Tasks: " + rs.all)

      # Print id, progress and people assigned
      for task_id, task in enumerate(game.tasks):
        if task_id in self.assignments:
          p = [game.team[person_id].name_str() for person_id in self.assignments[task_id]]
        else:
          p = []

        print(str(task_id) + ": " + str(task.complete) + "/" + str(task.max) + " " + ', '.join(p))
    else:
      print("Invalid argument")
  
  def _cmd_continue(self, game):
    game.day = game.day + 1

    if game.day <= game.total_days:
      game.set_phase(WorkPhase())
    else:
      game.set_phase(EndPhase())

  def begin(self, game):
    print(ef.b + fg.blue + "Day " + str(game.day) + rs.all)
    game.print_tasks()
    print()
  
  def run(self, game):
    player_input = input(">")
    cmd, *args = player_input.split(" ")

    if cmd not in self._command_map:
      print("Invalid command.")
      print(ef.i + "Type 'help' for more information." + rs.all)
      return

    try:
      self._command_map[cmd](game, *args)
    except TypeError:
      print("Invalid number of parameters")
      print(ef.i + "Type 'help' for more information." + rs.all)

  def end(self, game, next_phase):
    for task_id, task in enumerate(game.tasks):
      if task_id in self.assignments:
        
        # Can the traitor sabatoge?
        if game.contains_traitor(self.assignments[task_id]) and not game.contains_pc(self.assignments[task_id]):
          # Will the traitor sabatoge?
          r = random.randint(0, 10 - game.day)
          if r < 2:
            print("Unfortunately task " + str(task_id) + " has been sabatoged.")
            game.tasks[task_id] = Game.Task(task.max, 0)
            continue

        new_complete = task.complete + len(self.assignments[task_id])
        game.tasks[task_id] = Game.Task(task.max, min(new_complete, task.max))


class EndPhase():
  def begin(self, game):
    game.print_tasks()

    if game.win():
      print("Congratualtions! You win!")
    else:
      print("You lost.")

    for t in game.team:
      if t.traitor is True:
        print("The traitor was " + t.name_str() + "! Did you figure it out?")
  
  def run(self, game):
    pass


class Game():
  """
  Holds Game state.

  Update tasks by replacing the tuple.

  Attributes:
    total_days: The number of days to go up to
    day: the current day as an int
    tasks: A list of Task objects
    team: A list of Characters
    phase: The current phase.
  """

  Task = namedtuple("Task", ["max", "complete"])

  def __init__(self, total_days, task_maxes, team_size):
    self.total_days = total_days;
    self.day = 1;
    self.tasks = [Game.Task(m, 0) for m in task_maxes]
    self.team = [Character(TRAITS) for i in range(team_size)]
    self.phase = None

    # Select traitor
    self.team[random.randrange(len(self.team))].traitor = True

    self.team.append(PlayerCharacter())
  
  def print_team(self):
    print(ef.b + fg.red + "Your Team:" + rs.all)
    for i, c in enumerate(self.team):
      print(str(i) + ": " + c.name_str())

  def print_tasks(self):
    print(ef.b + fg.red + "Task Progress: " + rs.all)
    for i, v in enumerate(game.tasks):
      print(str(i) + ": " + str(v.complete) + "/" + str(v.max))

  def contains_traitor(self, ids):
    for i in ids:
      try:
        if self.team[i].traitor is True:
          return True
      except IndexError:
        continue

    return False
  
  def contains_pc(self, ids):
    for i in ids:
      try:
        if isinstance(self.team[i], PlayerCharacter):
          return True
      except IndexError:
        continue

    return False

  def win(self):
    for task in self.tasks:
      if task.complete != task.max:
        return False
    return True

  def set_phase(self, next_phase):
    # Try to call end()
    if self.phase is not None:
      try:
        self.phase.end(self, next_phase)
      except AttributeError:
        pass
    
    self.phase = next_phase
    self.phase.begin(self)
  
  def run(self):
    while self.day <= self.total_days:
      self.phase.run(self)


if __name__ == "__main__":
  random.seed()

  input(INTRO)

  game = Game(5, [16, 11, 6], 7)

  game.print_team()
  print()
  game.set_phase(WorkPhase())

  game.run()
?