Original Code
import random
class Character:
def __init__(self, name, role):
self.name = name
self.role = role
self.alive = True
self.player_controlled = False
self.protected = False
self.witch_cure = False
self.witch_poison = False
self.guard_prev = -1
class KillerGame:
def __init__(self, num_players=12):
print("Welcome to the Killer Games!")
self.players = [Character(str(i), 'civilian') for i in range(num_players)]
global the_one
the_one = random.choice([p for p in self.players])
the_one.player_controlled = True
for i in range(4):
random.choice([p for p in self.players if p.role == 'civilian']).role = 'killer'
for i in range(1):
guard = random.choice([p for p in self.players if p.role == 'civilian'])
guard.role = "guard"
for i in range(1):
witch = random.choice([p for p in self.players if p.role == 'civilian'])
witch.role = "witch"
witch.witch_cure = True
witch.witch_poison = True
print("There are 12 player, labled number 0-11.")
print(f"You are player {the_one.name}")
if the_one.role == "killer":
print("You are a killer. Try to murder all civilians and don't get voted out. Good luck.")
elif the_one.role == "witch":
print("You are a witch. Try to use your poison and cure to eliminate all killers. Good luck.")
elif the_one.role == "guard":
print("You are a guard. Try to use your ability to protect other players to eliminate all killers. Good luck.")
else:
print("You are a civilian. Try to elimiate the killers using your power to vote. Good luck.")
self.turn = 0
def night_phase_guard(self):
self.dead = []
print("Night "+str(self.turn+1))
for player in self.players:
if player.role == 'guard' and player.alive:
if player.player_controlled:
valid = 0
while valid == 0:
target = input("Choose a player to protect (enter their number): ")
for p in self.players:
if p.name == target:
if not p.alive or p in self.dead:
print("This player is dead. Please choose someone else.")
break
elif p.protected:
print("You cannot protect this player since you already protected them last turn. Please choose someone else.")
break
else:
valid = 1
for pl in self.players:
if pl.protected:
pl.protected = False
p.protected = True
break
else:
if any(not p.protected and p.alive and not p in self.dead for p in self.players):
for pl in self.players:
if pl.protected:
pl.protected = False
flag = pl
if self.turn == 0:
target = player
else:
target = random.choice([p for p in self.players if not p.protected and p.alive and not p in self.dead and p == flag])
target.protected = True
def night_phase_killer(self):
if the_one.role == "killer":
print("Current other alive killers:")
for k in self.players:
if k.role == "killer" and k.alive and k.name != the_one.name:
print(f"Killer {k.name} is alive.")
for player in self.players:
if player.role == 'killer' and player.alive:
if player.player_controlled:
valid = 0
while valid == 0:
target = input("Choose a civilian to kill (enter their number): ")
for p in self.players:
if p.name == target:
if not p.alive or p in self.dead:
print("This player is dead. Please choose someone else.")
break
elif p.name == player.name:
print("You cannot kill yourself. Please choose someone else.")
break
elif p.role == "killer":
print("You cannot kill a killer. Please choose someone else.")
break
else:
valid = 1
target = p
break
else:
if any(p.role == 'civilian' and p.alive and not p in self.dead for p in self.players):
target = random.choice([p for p in self.players if p.role == 'civilian' and p.alive and not p in self.dead])
if the_one.role == "killer":
print(f"Killer {player.name} killed player {target.name}")
self.dead.append(target)
def night_phase_witch(self):
for player in self.players:
if player.role == 'witch' and player.alive:
used_cure = False
if player.player_controlled:
if any(p.alive and p in self.dead for p in self.players) and player.witch_cure:
valid1 = 0
while valid1 == 0:
reply1 = input("At least one person was killed tonight. Do you want to use your cure? (Yes or No) ")
if reply1 == "Yes":
valid1 = 1
target = random.choice([p for p in self.players if p.alive and p in self.dead])
self.dead.remove(target)
player.witch_cure = False
used_cure = True
elif reply1 == "No":
valid1 = 1
valid2 = 0
if player.witch_poison and not used_cure:
while valid2 == 0:
reply2 = input("Do you want to use your poison? (Yes or No) ")
if reply2 == "Yes":
valid2 = 1
valid3 = 0
while valid3 == 0:
target = input("Choose a player to poison (enter their number): ")
for p in self.players:
if p.name == target:
if not p.alive or p in self.dead:
print("This player is dead. Please choose someone else.")
break
elif p.name == player.name:
print("You cannot poison yourself. Please choose someone else.")
break
else:
valid3 = 1
target = p
self.dead.append(target)
player.witch_poison = False
break
elif reply2 == "No":
valid2 = 1
else:
if any(p.alive and p in self.dead for p in self.players) and player.witch_cure:
pool = [0,1,2,3,4,5,6,7,8,9]
flag = random.choice(pool)
if flag < 7:
target = random.choice([p for p in self.players if p.alive and p in self.dead])
self.dead.remove(target)
player.witch_cure = False
used_cure = True
elif player.witch_poison and not used_cure:
pool = []
for p in self.players:
if p.alive and p.name != player.name:
pool.append(p)
if p.role == "killer":
for i in range(self.turn*8+2):
pool.append(p)
target = random.choice([p for p in pool])
self.dead.append(target)
player.witch_poison = False
def day_phase_anounce(self):
for d in self.dead:
if not d.protected:
d.alive = False
print("Day "+str(self.turn+1))
print("Morning comes. The deaths are revealed.")
for player in self.players:
if not player.alive:
print(f"Player {player.name} is dead.")
if not the_one.alive:
print("You are dead. You can continue observing the game.")
def day_phase_vote(self):
votes = {}
for player in self.players:
if player.alive:
if player.player_controlled:
valid = 0
while valid == 0:
vote = input(f"Player {player.name}, choose someone to vote for (enter their number): ")
for p in self.players:
if p.name == vote:
if not p.alive:
print("This player is dead. Please choose someone else.")
break
elif p.name == player.name:
print("You cannot choose yourself. Please choose someone else.")
break
else:
valid = 1
vote = p
break
else:
pool = []
for p in self.players:
if p.alive and p.name != player.name:
pool.append(p)
if p.role == "killer" and player.role == "civilian":
for i in range(self.turn*8+2):
pool.append(p)
elif p.role == "civilian" and player.role == "killer":
for i in range(self.turn*3+6):
pool.append(p)
vote = random.choice([p for p in pool])
print(f"Player {player.name} votes to exile player {vote.name}")
if vote.name not in votes:
votes[vote.name] = 1
else:
votes[vote.name] += 1
exile_target = max(votes, key=votes.get)
print(f"The player with the most votes, {exile_target}, is exiled.")
for player in self.players:
if player.name == exile_target:
player.alive = False
self.turn += 1
def check_game_over(self):
killers_alive = any(player.alive and player.role == 'killer' for player in self.players)
civilians_alive = any(player.alive and player.role == 'civilian' for player in self.players)
end = False
if not killers_alive:
print("Civilians win! All killers are eliminated.")
end = True
elif not civilians_alive:
print("Killers win! All civilians are eliminated.")
end = True
if end:
print("The roles of each player is revealed.")
for p in self.players:
print(f"Player {p.name} is a {p.role}.")
return end
killer_game = KillerGame()
while 1:
if not killer_game.check_game_over():
killer_game.night_phase_guard()
killer_game.night_phase_killer()
killer_game.night_phase_witch()
killer_game.day_phase_anounce()
else:
print("New Game")
killer_game = KillerGame()
continue
if not killer_game.check_game_over():
killer_game.day_phase_vote()
else:
print("New Game")
killer_game = KillerGame()
continue
FEEDBACK SECTION
Improvements to be made
- Add Player number validation function to validate each input of the user.
def get_valid_player_number(self, prompt, exclude_self=False, alive_only=True):
while True:
try:
player_num = int(input(prompt))
if 0 <= player_num < len(self.players):
player = self.players[player_num]
if exclude_self and player.player_controlled:
print("You cannot choose yourself. Please choose someone else.")
elif alive_only and not player.alive:
print("This player is dead. Please choose someone else.")
else:
return player_num
else:
print("Invalid number. Please try again.")
except ValueError:
print("Please enter a valid number.")
- In the
night_phase_guard(self), add the logic of immediately killing the player because testing have shown that there are occasions where we could vote even after death for multiple rounds.
if not target.protected:
target.alive = False
print(f"Player {target.name} has been killed.")
else:
print(f"Player {target.name} was protected and survived.")
- In the phase of assigning roles, divide into assigning
killers, guard, witch separately. Thus, this will ensure that every time a unique role is assigned.
def __init__(self, num_players=12):
print("Welcome to the Killer Games!")
self.players = [Character(str(i), 'civilian') for i in range(num_players)]
the_one = random.choice(self.players)
the_one.player_controlled = True
# Assign killers
killers = random.sample([p for p in self.players if p.role == 'civilian'], 4)
for killer in killers:
killer.role = 'killer'
# Assign guard
guard = random.choice([p for p in self.players if p.role == 'civilian'])
guard.role = "guard"
# Assign witch
witch = random.choice([p for p in self.players if p.role == 'civilian'])
witch.role = "witch"
witch.witch_cure = True
witch.witch_poison = True
- Call
check_game_over at the start of day and night phases. 每日一遍,防止诈尸
def start_day_phase(self):
if self.check_game_over():
return
def start_night_phase(self):
if self.check_game_over():
return
Code’s strengths
- The overall concept and structure of your game are well-thought-out. You've created a complex, interactive game that requires strategic thinking, making it engaging and fun to play.
- You've effectively used object-oriented programming principles. Defining a
Character class and a KillerGame class helps in organizing the code logically and making it more manageable.