-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstartBattle.py
More file actions
133 lines (99 loc) · 3.97 KB
/
Copy pathstartBattle.py
File metadata and controls
133 lines (99 loc) · 3.97 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
import subprocess
import signal
import sys
import psutil
import argparse
import xml.etree.ElementTree as ET
import time
#TODO: make sure all imports are being used and are nessisary
#TODO: make sure all these work on different OS
#TODO: move the team name to a different location
childs = []
def cleanup(signum, frame):
print("Terminating child process...")
parent = psutil.Process()
for child in childs:
child.terminate()
print(f"Killed process with PID: {child.pid}")
# for child in parent.children(recursive=True):
# print(f"Killed process with PID: {child.pid}") #TODO: is this really needed
# child.terminate()
sys.exit(0) # Exit this proccess as everything is closed properly
def loadBattleFromXML(xmlPath, battleID): #TODO: might need to make this a bit easier to read
tree = ET.parse(xmlPath)
root = tree.getroot()
# Search for the battle with the matching ID
found = False
parsedInfo = {}
for battle in tree.findall('battle'): #TODO: board args
battle_id = battle.get('id')
if (battle.get('id') != battleID):
continue
# At this point we have found the battle with the correct ID
found = True
# Parse all the snakes in this battle
snakes = []
count = 0
for snake in battle.findall('./snake'):
name = snake.findtext('name')
try:
url = snake.findtext('url')
snakes.append({'name': name, 'url': url})
except: #TODO: no support for this yet
port = 8000 + count
count += 1
file = snake.findtext('file')
snakes.append({'name': name, 'port': port, 'file': file})
parsedInfo['snakes'] = snakes
# Parse all the board setting in this battle
#TODO: finish this
break
if (found):
return parsedInfo
else:
print(f"Could not find battle with ID: {battleID}")
sys.exit(-1)
def generateBattleArguments(parsedInfo):
args = ['battlesnake', 'play', '-W', '11', '-H', '11','-g', 'solo', '--browser', '--board-url', 'http://localhost:5173'] #TODO: update to not use solo
# Generate the commands for the snakes
snakes = parsedInfo['snakes']
for snake in snakes:
args.append('--name')
args.append(snake['name'])
args.append('--url')
args.append(snake['url'])
return args
def startSnakeServer(): #TODO: extend to work with already running servers
proc = subprocess.Popen(["python", "main.py"]) #TODO: people are going to change the name of this file
print(f"Started process with PID: {proc.pid}")
childs.append(proc)
time.sleep(2) # needed to allow for the snake server to fully starup before the battle starts
def runBattle(args):
proc = subprocess.Popen(args) #TODO: needs to be adjustable so people can run more than one snake
print(f"Started process with PID: {proc.pid}")
childs.append(proc)
proc.wait()
def main():
xmlFile = "battle.xml"
# Parse the inputed battle ID
try:
parser = argparse.ArgumentParser(
description="Run a Battlesnake battle by ID from the XML file.",
exit_on_error=False
)
parser.add_argument("battleID", type=str, help="ID of the battle to run")
args = parser.parse_args()
except:
print("Error: Missing command line argument <battleID>. Example \"$py .\\startBattle ExampleID\"\n")
sys.exit(-1)
# Parse the command arguments from the battle in the xml file
parsedInfo = loadBattleFromXML(xmlFile, args.battleID)
commandArgs = generateBattleArguments(parsedInfo)
# run the cleanup function when the termination signal is recived
signal.signal(signal.SIGINT, cleanup)
signal.signal(signal.SIGTERM, cleanup)
startSnakeServer()
runBattle(commandArgs)
cleanup(None, None)
if __name__ == "__main__":
main()