Commit 86e1cacb authored by Matthew Hausknecht's avatar Matthew Hausknecht

Refactored team launching code.

parent 6d34aeac
...@@ -34,8 +34,6 @@ def main(args): ...@@ -34,8 +34,6 @@ def main(args):
if args.logging and not os.path.exists(args.logDir): if args.logging and not os.path.exists(args.logDir):
os.makedirs(args.logDir) os.makedirs(args.logDir)
num_agents = args.offenseAgents + args.defenseAgents num_agents = args.offenseAgents + args.defenseAgents
team1 = args.offenseTeam
team2 = args.defenseTeam
binary_dir = os.path.dirname(os.path.realpath(__file__)) binary_dir = os.path.dirname(os.path.realpath(__file__))
server_port = args.port + num_agents server_port = args.port + num_agents
coach_port = args.port + num_agents + 1 coach_port = args.port + num_agents + 1
...@@ -76,12 +74,8 @@ def main(args): ...@@ -76,12 +74,8 @@ def main(args):
from Trainer import Trainer from Trainer import Trainer
trainer = Trainer(args=args, server_port=server_port, coach_port=coach_port) trainer = Trainer(args=args, server_port=server_port, coach_port=coach_port)
trainer.initComm() trainer.initComm()
# Add Team1
trainer.addTeam(team1)
# Add Team2
trainer.addTeam(team2)
# Run # Run
trainer.run(necProcesses) trainer.run(necProcesses, args.offenseTeam, args.defenseTeam)
except KeyboardInterrupt: except KeyboardInterrupt:
print '[start.py] Exiting for CTRL-C' print '[start.py] Exiting for CTRL-C'
finally: finally:
...@@ -96,6 +90,8 @@ def main(args): ...@@ -96,6 +90,8 @@ def main(args):
def parseArgs(): def parseArgs():
import argparse import argparse
team_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'teams')
installed_teams = os.listdir(team_dir)
p = argparse.ArgumentParser(description='Start Half Field Offense.', p = argparse.ArgumentParser(description='Start Half Field Offense.',
formatter_class=argparse.RawTextHelpFormatter) formatter_class=argparse.RawTextHelpFormatter)
p.add_argument('--headless', dest='headless', action='store_true', p.add_argument('--headless', dest='headless', action='store_true',
...@@ -121,9 +117,9 @@ def parseArgs(): ...@@ -121,9 +117,9 @@ def parseArgs():
p.add_argument('--defense-npcs', dest='defenseNPCs', type=int, default=0, p.add_argument('--defense-npcs', dest='defenseNPCs', type=int, default=0,
help='Number of defensive uncontrolled players. Default: 0.') help='Number of defensive uncontrolled players. Default: 0.')
p.add_argument('--offense-team', dest='offenseTeam', type=str, default='base', p.add_argument('--offense-team', dest='offenseTeam', type=str, default='base',
help='Team name to pull offensive NPCs from. Options: {base, helios} Default: base.') help='Offense team binary. Options: '+str(installed_teams)+'. Default: base.')
p.add_argument('--defense-team', dest='defenseTeam', type=str, default='base', p.add_argument('--defense-team', dest='defenseTeam', type=str, default='base',
help='Team name to pull defensive NPCs from. Options: {base, helios} Default: base') help='Defense team binary. Options: '+str(installed_teams)+'. Default: base.')
p.add_argument('--no-sync', dest='sync', action='store_false', default=True, p.add_argument('--no-sync', dest='sync', action='store_false', default=True,
help='Run server in non-sync mode.') help='Run server in non-sync mode.')
p.add_argument('--port', dest='port', type=int, default=6000, p.add_argument('--port', dest='port', type=int, default=6000,
...@@ -169,6 +165,10 @@ def parseArgs(): ...@@ -169,6 +165,10 @@ def parseArgs():
p.error('Defense players (defense-agents + defense-npcs): '\ p.error('Defense players (defense-agents + defense-npcs): '\
'invalid choice: ' + str(args.defenseAgents + args.defenseNPCs) +\ 'invalid choice: ' + str(args.defenseAgents + args.defenseNPCs) +\
' (choose from [0,11])') ' (choose from [0,11])')
if args.offenseTeam not in installed_teams:
p.error('Unrecognized offense team: ' + str(args.offenseTeam))
if args.defenseTeam not in installed_teams:
p.error('Unrecognized defense team: ' + str(args.defenseTeam))
return args return args
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -3,11 +3,12 @@ ...@@ -3,11 +3,12 @@
import os, subprocess import os, subprocess
class Team(object): class Team(object):
""" Abstract class. Handles launching players from 3rd party binaries. """ Abstract class. Handles launching players from 3rd party binaries. """
"""
def __init__(self, name, binaryPath, libDir, options, offenseOrder, defenseOrder): def __init__(self, name, binaryPath, libDir, options, offenseOrder,
defenseOrder):
""" """
Creates a team Creates a team.
name: name of the team name: name of the team
binaryPath: absolute path of the executable binaryPath: absolute path of the executable
...@@ -25,15 +26,17 @@ class Team(object): ...@@ -25,15 +26,17 @@ class Team(object):
def launch_npc(self, player_num): def launch_npc(self, player_num):
""" """
Abstract method that should be overrided by subclasses. Launches an npc with player number player_num. Abstract method that should be overrided by subclasses. Launches an
The method that overrides this should call start_npc_process. See examples below. npc with player number player_num. The method that overrides this
should call start_npc_process. See examples below.
""" """
pass pass
def start_npc_proc(self, launchOpts=None): def start_npc_proc(self, launchOpts=None):
"""Launches a player using the team-specific binary """
launchOpts should be used to append player specific options Launches a player using the team-specific binary launchOpts
(e.g., helios uses '-g' to signify launching a goalie ) should be used to append player specific options (e.g., helios
uses '-g' to signify launching a goalie )
Returns a Popen process object Returns a Popen process object
""" """
...@@ -51,16 +54,18 @@ class Team(object): ...@@ -51,16 +54,18 @@ class Team(object):
class Agent2d(Team): class Agent2d(Team):
def __init__(self, name, baseDir, libDir, binaryName, logDir, record,
def __init__(self, name, baseDir, libDir, binaryName, logDir, record, host='localhost', port=6000): host='localhost', port=6000):
binaryPath = os.path.join(baseDir, binaryName) binaryPath = os.path.join(baseDir, binaryName)
options = '-t %s -p %i --config_dir %s/config/formations-dt --log_dir %s --player-config %s/config/player.conf' % (name, port, baseDir, logDir, baseDir) options = '-t %s -p %i --config_dir %s/config/formations-dt --log_dir %s'\
'--player-config %s/config/player.conf'\
% (name, port, baseDir, logDir, baseDir)
if record: if record:
options += ' --record' options += ' --record'
offenseOrder = [11,7,8,9,10,6,3,2,4,5] offenseOrder = [11,7,8,9,10,6,3,2,4,5]
defenseOrder = [2,3,4,5,6,7,8,11,9,10] defenseOrder = [2,3,4,5,6,7,8,11,9,10]
super(Agent2d, self).__init__(name, binaryPath, libDir, options, offenseOrder, defenseOrder) super(Agent2d, self).__init__(name, binaryPath, libDir, options,
offenseOrder, defenseOrder)
def launch_npc(self, player_num): def launch_npc(self, player_num):
launchOpts = None launchOpts = None
...@@ -69,15 +74,26 @@ class Agent2d(Team): ...@@ -69,15 +74,26 @@ class Agent2d(Team):
print 'Launch npc %s-%d' % (self._name, player_num) print 'Launch npc %s-%d' % (self._name, player_num)
return self.start_npc_proc(launchOpts) return self.start_npc_proc(launchOpts)
class Helios(Team):
def __init__(self, name, baseDir, libDir, binaryName, host='localhost', port=6000):
class Helios(Team):
def __init__(self, name, baseDir, libDir, binaryName, host='localhost',
port=6000):
binaryPath = os.path.join(baseDir, binaryName) binaryPath = os.path.join(baseDir, binaryName)
options = '--player-config %s/player.conf -h %s -t %s --formation-conf-dir %s/data/formations --role-conf %s/data/role.conf --ball-table %s/data/ball_table.dat --chain-search-method BestFirstSearch --evaluator-name Default --max-chain-length 4 --max-evaluate-size 1000 --sirm-evaluator-param-dir %s/data/sirm_evaluator/ --goalie-position-dir %s/data/goalie_position/ --intercept-conf-dir %s/data/intercept_probability/ --opponent-data-dir %s/data/opponent_data/ -p %d' % (baseDir, host, name, baseDir, baseDir, baseDir, baseDir, baseDir, baseDir, baseDir, port) options = '--player-config %s/player.conf -h %s -t %s '\
'--formation-conf-dir %s/data/formations '\
'--role-conf %s/data/role.conf --ball-table %s/data/ball_table.dat '\
'--chain-search-method BestFirstSearch --evaluator-name Default '\
'--max-chain-length 4 --max-evaluate-size 1000 '\
'--sirm-evaluator-param-dir %s/data/sirm_evaluator/ '\
'--goalie-position-dir %s/data/goalie_position/ '\
'--intercept-conf-dir %s/data/intercept_probability/ '\
'--opponent-data-dir %s/data/opponent_data/ -p %d'\
% (baseDir, host, name, baseDir, baseDir, baseDir, baseDir,
baseDir, baseDir, baseDir, port)
offenseOrder = [11,7,8,9,10,6,3,2,4,5] offenseOrder = [11,7,8,9,10,6,3,2,4,5]
defenseOrder = [2,3,4,5,6,7,8,11,9,10] defenseOrder = [2,3,4,5,6,7,8,11,9,10]
super(Helios, self).__init__(name, binaryPath, libDir, options, offenseOrder, defenseOrder) super(Helios, self).__init__(name, binaryPath, libDir, options,
offenseOrder, defenseOrder)
def launch_npc(self, player_num): def launch_npc(self, player_num):
launchOpts = None launchOpts = None
...@@ -85,8 +101,3 @@ class Helios(Team): ...@@ -85,8 +101,3 @@ class Helios(Team):
launchOpts = '-g' launchOpts = '-g'
print 'Launch npc %s-%d' % (self._name, player_num) print 'Launch npc %s-%d' % (self._name, player_num)
return self.start_npc_proc(launchOpts) return self.start_npc_proc(launchOpts)
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
import sys, numpy, time, os, subprocess, teams import sys, numpy, time, os, subprocess, Teams
from Communicator import ClientCommunicator, TimeoutError from Communicator import ClientCommunicator, TimeoutError
class DoneError(Exception): class DoneError(Exception):
...@@ -97,44 +97,39 @@ class Trainer(object): ...@@ -97,44 +97,39 @@ class Trainer(object):
self.waitOnPlayer(agent_ext_num, play_offense) self.waitOnPlayer(agent_ext_num, play_offense)
return p return p
def addTeam(self, team_name): def createTeam(self, requested_team_name, play_offense):
""" Adds a team to the team list""" """ Given a team name, returns the team object. """
# Check whether team name valid, and map to a format acceptable to third party binary teams_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'teams')
nameMap = {'base':'base', 'helios':'HELIOS'} if requested_team_name == 'helios':
if team_name not in nameMap.keys(): print 'Creating team Helios'
print 'Invalid team name: ', team_name team_name = 'HELIOS_' + ('left' if play_offense else 'right')
sys.exit(1) team_dir = os.path.join(teams_dir, 'helios', 'helios-13Eindhoven')
# Create side specific team lib_dir = os.path.join(teams_dir, 'helios', 'local', 'lib')
if len(self._teams) == 0: return Teams.Helios(team_name, team_dir, lib_dir,
self._teams.append(nameMap[team_name] + '_left') binaryName='helios_player', host='localhost',
elif len(self._teams) == 1: port=self._serverPort)
self._teams.append(nameMap[team_name] + '_right') elif requested_team_name == 'base':
else:
print 'Too many teams added!'
sys.exit(1)
def createTeam(self, name):
teamDir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'teams')
if 'HELIOS' in name:
print 'Creating team HELIOS'
return teams.Helios(name, os.path.join(teamDir, 'helios', 'helios-13Eindhoven'), os.path.join(teamDir, 'helios', 'local', 'lib'), 'helios_player', host='localhost', port=self._serverPort)
elif 'base' in name:
print 'Creating team Agent2d (base)' print 'Creating team Agent2d (base)'
return teams.Agent2d(name, os.path.join(teamDir, 'base'), None, 'sample_player', self._logDir, self._record, host='localhost', port=self._serverPort) team_name = 'base_' + ('left' if play_offense else 'right')
team_dir = os.path.join(teams_dir, 'base')
lib_dir = None
return Teams.Agent2d(team_name, team_dir, lib_dir,
binaryName='sample_player', logDir=self._logDir,
record=self._record, host='localhost',
port=self._serverPort)
else: else:
print 'Invalid team found' print 'Unknown team requested: ' + requested_team_name
sys.exit(1) sys.exit(1)
def getTeams(self): def getTeams(self, offense_team_name, defense_team_name):
""" Sets the offensive and defensive teams and player rosters. """ """ Sets the offensive and defensive teams and player rosters. """
self._offenseTeamInd = 0 # Set up offense team
self._offenseTeamName = self._teams[self._offenseTeamInd] offenseTeam = self.createTeam(offense_team_name, play_offense=True)
self._defenseTeamName = self._teams[1-self._offenseTeamInd] self._offenseTeamName = offenseTeam._name
# set up offense
offenseTeam = self.createTeam(self._offenseTeamName)
self._offenseOrder = [1] + offenseTeam._offense_order # 1 for goalie self._offenseOrder = [1] + offenseTeam._offense_order # 1 for goalie
# set up defense # Set up defense team
defenseTeam = self.createTeam(self._defenseTeamName) defenseTeam = self.createTeam(defense_team_name, play_offense=False)
self._defenseTeamName = defenseTeam._name
self._defenseOrder = [1] + defenseTeam._defense_order # 1 for goalie self._defenseOrder = [1] + defenseTeam._defense_order # 1 for goalie
return (offenseTeam, defenseTeam) return (offenseTeam, defenseTeam)
...@@ -397,10 +392,10 @@ class Trainer(object): ...@@ -397,10 +392,10 @@ class Trainer(object):
return False return False
return True return True
def run(self, necProcesses): def run(self, necProcesses, offense_team_name, defense_team_name):
""" Run the trainer """ """ Run the trainer """
try: try:
(offenseTeam, defenseTeam) = self.getTeams() (offenseTeam, defenseTeam) = self.getTeams(offense_team_name, defense_team_name)
offense_unums = self._offenseOrder[1: self._numOffense + 1] offense_unums = self._offenseOrder[1: self._numOffense + 1]
sorted_offense_agent_unums = sorted(self._offenseOrder[1:self._offenseAgents+1]) sorted_offense_agent_unums = sorted(self._offenseOrder[1:self._offenseAgents+1])
defense_unums = self._defenseOrder[: self._numDefense] defense_unums = self._defenseOrder[: self._numDefense]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment