220 lines
8.2 KiB
Python
220 lines
8.2 KiB
Python
import os
|
|
import readline
|
|
import sys
|
|
import colorama
|
|
import json
|
|
from colorama import Fore, Style
|
|
|
|
from models.default_model import DefaultModel
|
|
from models.data_model import DataModel
|
|
from game_evaluator import DeceptionGame, AvalonGame
|
|
|
|
|
|
def repl_report(report, top_k, namemap, ngood):
|
|
sort_order = sorted(
|
|
[(report[i]["side"].get(True, 0.0), i)
|
|
for i in range(len(report))],
|
|
reverse=True)
|
|
|
|
still_good = 0
|
|
for goodness, i in sort_order:
|
|
row = "%s: %2f%% Good %2f%% Evil" % (
|
|
namemap.get(i, "") + " (%s)" % str(i),
|
|
goodness * 100,
|
|
(1.0 - goodness) * 100)
|
|
if still_good < ngood:
|
|
print(Fore.CYAN + Style.BRIGHT + row)
|
|
else:
|
|
print(Fore.RED + Style.BRIGHT + row)
|
|
roles = sorted([(v, k) for k, v in report[i]["role"].iteritems()],
|
|
reverse=True)
|
|
row = " "
|
|
has_roles = True
|
|
for score, role in roles:
|
|
if role == "":
|
|
has_roles = False
|
|
break
|
|
row += "%2.1f%% %s " % (
|
|
score * 100, role)
|
|
if has_roles:
|
|
print(row)
|
|
|
|
still_good += 1
|
|
for prob, deal in top_k:
|
|
print prob
|
|
print deal
|
|
|
|
def display_statement(statement, namemap):
|
|
out = ""
|
|
out += Fore.MAGENTA + Style.BRIGHT
|
|
out += statement["type"].title()
|
|
out += Style.RESET_ALL + " -- "
|
|
for key in statement["print_order"]:
|
|
out += Fore.YELLOW
|
|
out += key.title() + ": "
|
|
out += Style.RESET_ALL
|
|
out += str(statement[key]).title() + " "
|
|
return out
|
|
|
|
|
|
def help():
|
|
print(Fore.GREEN + "Initial Commands:")
|
|
print("load <filename> -- Loads a savefile")
|
|
print("newgame -- Starts a new game")
|
|
print("\n")
|
|
print(Fore.GREEN + "Game Commands:")
|
|
print("save <filename> -- Saves a game to file")
|
|
print("ls -- Lists current assertions")
|
|
print("disb <index> -- Delete (disbelieve) an assertion")
|
|
print("name -- Name a player index for pretty printing")
|
|
print("side -- Assert that someone must be good or evil")
|
|
print("lady -- Assert that one player saw another and made a claim")
|
|
print("vote -- Assert a voted-on team and the votes"
|
|
" (whether it succeeded or not)")
|
|
print("switch -- Good and Evil Lancelots switch")
|
|
print("mission -- Assert the results of a team and a mission")
|
|
print("eval <repetitions> -- Quick eval, discounting special roles")
|
|
print("fulleval <repetitions> -- Eval, counting special roles")
|
|
print("report -- Show last report again")
|
|
|
|
|
|
def main():
|
|
colorama.init(autoreset=True)
|
|
readline.get_history_length()
|
|
print(Fore.GREEN + Style.BRIGHT + "Tim the Enchanter v1.0")
|
|
|
|
game = None
|
|
namemap = {}
|
|
|
|
while True:
|
|
try:
|
|
command_str = raw_input("%s> " % game)
|
|
command_list = command_str.strip().split(" ")
|
|
command = command_list[0]
|
|
if command == "quit" or command == "q" or command == "exit":
|
|
sys.exit(0)
|
|
if command == "help":
|
|
help()
|
|
continue
|
|
if game is None:
|
|
if command == "newgame":
|
|
nplayers = raw_input("How many players? ")
|
|
game = DeceptionGame(
|
|
AvalonGame(int(nplayers)), DataModel)
|
|
namemap = {}
|
|
elif command == "load":
|
|
if len(command_list) < 2:
|
|
print(Fore.RED + "Need an input file")
|
|
continue
|
|
inpath = os.path.expanduser(command_list[1])
|
|
with open(inpath, "r") as savefile:
|
|
observations = json.load(savefile)
|
|
metadata = observations[0]
|
|
data = observations[1:]
|
|
|
|
game = DeceptionGame(
|
|
AvalonGame(int(metadata["game_size"])),
|
|
DataModel)
|
|
namemap = metadata["player_names"]
|
|
game.load_save(data)
|
|
else:
|
|
print(Fore.RED + "Need to create a game")
|
|
continue
|
|
elif command == "ls":
|
|
for i, statement in enumerate(game.seen):
|
|
print "%d: %s" % (i, display_statement(statement, namemap))
|
|
continue
|
|
elif command == "vote":
|
|
proposer = int(raw_input("Proposer? ").strip())
|
|
input = raw_input("Team? ").strip()
|
|
team = [int(x) for x in input]
|
|
votes = [int(x) for x in raw_input("Votes? ").strip()]
|
|
round = int(raw_input("Round? ").strip())
|
|
voten = int(raw_input("Vote Number? ").strip())
|
|
fail_req = game.get_fail_req(round)
|
|
game.do_vote(team, votes, fail_req, round, voten, proposer)
|
|
game.trace = {}
|
|
continue
|
|
|
|
elif command == "mission":
|
|
team = [int(x) for x in raw_input("Team? ").strip()]
|
|
fails = int(raw_input("# of Fails? ").strip())
|
|
must = int(raw_input("Spys must fail? ").strip()) == 1
|
|
round = int(raw_input("Round? ").strip())
|
|
game.do_mission(team, fails, must, round)
|
|
game.trace = {}
|
|
continue
|
|
|
|
elif command == "lady" or command == "lol":
|
|
p1 = int(raw_input("ID For Lady? ").strip())
|
|
p2 = int(raw_input("ID For Target? ").strip())
|
|
claim = int(raw_input("Claim? ").strip()) == 1
|
|
round = int(raw_input("Round? ").strip()) == 1
|
|
game.player_sees_player_and_claims(p1, p2, claim, round)
|
|
game.trace = {}
|
|
continue
|
|
|
|
elif command == "side":
|
|
p1 = int(raw_input("ID For Assertion? ").strip())
|
|
claim = int(raw_input("Good? ").strip()) == 1
|
|
game.add_known_alliance(p1, claim)
|
|
game.trace = {}
|
|
continue
|
|
|
|
elif command == "switch":
|
|
r = int(raw_input("Starting in round?").strip())
|
|
game.switch_lancelots(r)
|
|
game.trace = {}
|
|
continue
|
|
|
|
elif command == "eval":
|
|
times = 200 / (game.n_players - 4) * 2
|
|
if len(command_list) > 1:
|
|
times = int(command_list[1])
|
|
game.eval(times, quick=True)
|
|
players, top_k = game.report()
|
|
repl_report(players, top_k, namemap, game.n_good)
|
|
elif command == "fulleval":
|
|
times = 200 / (game.n_players - 4) * 2
|
|
if len(command_list) > 1:
|
|
times = int(command_list[1])
|
|
game.eval(times)
|
|
players, top_k = game.report()
|
|
repl_report(players, top_k, namemap, game.n_good)
|
|
elif command == "report":
|
|
players, top_k = game.report()
|
|
repl_report(players, top_k, namemap, game.n_good)
|
|
elif command == "save":
|
|
if len(command_list) < 2:
|
|
print(Fore.RED + "Need an output file")
|
|
continue
|
|
metadata = [{
|
|
"game_size": game.n_players,
|
|
"player_names": namemap
|
|
}]
|
|
outpath = os.path.expanduser(command_list[1])
|
|
with open(outpath, "w") as savefile:
|
|
json.dump(metadata + game.seen, savefile, indent=2)
|
|
elif command == "name":
|
|
if len(command_list) < 3:
|
|
print(Fore.RED + "No args?")
|
|
continue
|
|
namemap[int(command_list[1])] = command_list[2]
|
|
elif command == "disb" or command == "disbelieve":
|
|
if len(command_list) < 2:
|
|
print(Fore.RED + "No args?")
|
|
continue
|
|
game.disbelieve(int(command_list[1]))
|
|
else:
|
|
print(Fore.RED + "Unknown command: %s" % command)
|
|
continue
|
|
except EOFError:
|
|
print "Canceled"
|
|
continue
|
|
except Exception, e:
|
|
print str(e)
|
|
continue
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|