-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathsimple_cli.py
More file actions
149 lines (121 loc) · 5.78 KB
/
simple_cli.py
File metadata and controls
149 lines (121 loc) · 5.78 KB
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
import os
import argparse
import battlecode_cli as cli
import sys
try:
import colorama
colorama.init()
CINIT=True
except:
CINIT=False
pass
map_extension = ".bc18map"
map_extension_text = ".bc18t"
replay_extension = ".bc18"
# ANSI escape codes
# See https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
color_red = "\033[31m"
color_reset = "\033[0m"
def run_game(map_path, player1dir, player2dir, replay_dir, docker, terminal_viewer, extra_delay, max_memory, initial_time, per_frame_time):
args = {}
args['dir_p1'] = player1dir
args['dir_p2'] = player2dir
args['docker'] = docker
# TODO: Will cause name collisions if multiple instances run at the same time!
args['replay_filename'] = os.path.join(replay_dir, "replay_" + str(len(os.listdir(replay_dir))) + replay_extension)
args['player_memory'] = max_memory
args['player_cpu'] = 20
args['time_pool'] = initial_time
args['time_additional'] = per_frame_time
args['use_viewer'] = False
args['terminal_viewer'] = terminal_viewer
args['extra_delay'] = extra_delay
args['map'] = cli.get_map(map_path)
if terminal_viewer and sys.platform == 'win32' and not CINIT:
print('To get pretty output with -tv on windows, run `py -3 -m pip install colorama`')
(game, sandboxes, sock_file) = cli.create_game(args)
try:
winner = cli.run_game(game, sandboxes, args, sock_file)
finally:
cli.cleanup(sandboxes, args, sock_file)
print("Winner is player " + str(1 if winner == 'player1' else 2))
def get_maps(map_directory):
maps = [o for o in os.listdir(map_directory) if o.endswith(map_extension) or o.endswith(map_extension_text)]
# This map is built-in
maps.append('testmap.bc18map')
return maps
file_dir = os.path.dirname(os.path.realpath(__file__))
map_directory = os.path.abspath(file_dir + '/../battlecode-maps')
parser = argparse.ArgumentParser(
"battlecode.sh",
description='Run BattleCode 2018 matches'
)
parser.add_argument('-p1', '--player1', help="Path to the directory for player 1", required=True)
parser.add_argument('-p2', '--player2', help="Path to the directory for player 2", required=True)
map_names = ", ".join(s.replace(map_extension, "").replace(map_extension_text, "") for s in get_maps(map_directory))
parser.add_argument('-m', '--map', help="The map to play on. The available maps are:\n" + map_names, required=True)
parser.add_argument('--replay-dir', help="Directory to save replays to. This may not work with docker. (default: %(default)s)", default="replays", required=False)
parser.add_argument('--mem', type=int, help='Memory in megabytes that a player is allowed to use. (default: %(default)s)', default=256)
parser.add_argument('--docker', action='store_const', const=True, default=False, help="Use Docker to run the game. This requires Docker to be installed and the gods to be on your side")
parser.add_argument('--unlimited-time', action='store_const', const=True, default=False, help='Allow players to use an unlimited amount of time')
parser.add_argument('-tv', '--terminal-viewer', action='store_const', const=True, default=False, help="Print game images in the terminal.")
parser.add_argument('-ed', '--extra-delay', type=int, default=0, help="add extra delay after each turn (make -tv slower)")
args = parser.parse_args()
map_path = args.map
# Input validation
replay_dir = os.path.abspath(args.replay_dir)
if not os.path.isdir(replay_dir):
prompt = "Replay directory '" + args.replay_dir + "' does not exist. Do you want to create it? [y/N] "
if input(prompt).strip() == "y":
os.mkdir(replay_dir)
else:
exit(1)
if not map_path.endswith(map_extension) or map_path.endswith(map_extension_text):
for ext in (map_extension, map_extension_text):
t = os.path.join(map_directory, map_path + ext)
print(t)
if os.path.isfile(t):
map_path = t
if not os.path.isfile(map_path):
print("Could not find any map named " + str(args.map) + ". Use --help to see a list of all available maps.\nExpected path: " + str(map_path))
exit(1)
if args.mem <= 0:
print("Max memory to use cannot be negative")
exit(1)
def validate_player_dir(path, require_bat):
if not os.path.exists(path):
return "Cannot find the directory '" + path + "'. You should pass a relative or absolute path to a directory with your player code"
if not os.path.isdir(path):
return "'" + path + "' is not a directory. You should pass a relative or absolute path to a directory with your player code"
if not os.path.exists(os.path.join(path, "run.sh")):
return "Your player directory ('" + path + "') does not contain a run.sh file. See the example player folders to see how it should look."
if require_bat and not os.path.exists(os.path.join(path, "run.bat")):
return "Your player directory ('" + path + "') does not contain a run.bat file which is required when not using docker on Windows. See the example player folders to see how it should look."
return None
require_run_bat = sys.platform == "win32" and not args.docker
err1 = validate_player_dir(args.player1, require_run_bat)
if err1 is not None:
print(color_red + "Player 1: " + err1 + color_reset)
exit(1)
err2 = validate_player_dir(args.player2, require_run_bat)
if err2 is not None:
print(color_red + "Player 2: " + err2 + color_reset)
exit(1)
initial_time = 1000000000 if args.unlimited_time else 10 * 1000
per_frame_time= 50
try:
run_game(
map_path,
args.player1,
args.player2,
replay_dir,
docker=args.docker,
terminal_viewer=args.terminal_viewer,
extra_delay=args.extra_delay,
max_memory=args.mem,
initial_time=initial_time,
per_frame_time=per_frame_time
)
except KeyboardInterrupt:
print("Game Stopped")
exit(0)