Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
Seminar-HFO
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Shashank Suhas
Seminar-HFO
Commits
f8ec967c
You need to sign in or sign up before continuing.
Commit
f8ec967c
authored
Oct 19, 2015
by
Matthew Hausknecht
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
removed most of trainer code.
parent
23696f8a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
86 additions
and
333 deletions
+86
-333
bin/Communicator.py
bin/Communicator.py
+1
-1
bin/HFO
bin/HFO
+3
-3
bin/Trainer.py
bin/Trainer.py
+82
-329
No files found.
bin/Communicator.py
View file @
f8ec967c
...
@@ -62,7 +62,7 @@ class Communicator(object):
...
@@ -62,7 +62,7 @@ class Communicator(object):
raise
TimeoutError
raise
TimeoutError
else
:
else
:
retryCount
-=
1
retryCount
-=
1
print
'[Trainer] waiting for message
'
print
'[Trainer] waiting for message
, retry ='
,
retryCount
time
.
sleep
(
0.3
)
time
.
sleep
(
0.3
)
#raise ValueError('Error while receiving message')
#raise ValueError('Error while receiving message')
(
msg
,
sep
,
rest
)
=
msg
.
partition
(
'
\0
'
)
(
msg
,
sep
,
rest
)
=
msg
.
partition
(
'
\0
'
)
...
...
bin/HFO
View file @
f8ec967c
...
@@ -49,11 +49,12 @@ def main(args, team1='left', team2='right', rng=numpy.random.RandomState()):
...
@@ -49,11 +49,12 @@ def main(args, team1='left', team2='right', rng=numpy.random.RandomState()):
'server::game_log_dir=
%
s server::text_log_dir=
%
s '
\
'server::game_log_dir=
%
s server::text_log_dir=
%
s '
\
'server::synch_mode=
%
i server::hfo=1 '
\
'server::synch_mode=
%
i server::hfo=1 '
\
'server::fullstate_l=
%
i server::fullstate_r=
%
i '
\
'server::fullstate_l=
%
i server::fullstate_r=
%
i '
\
'server::coach_w_referee=
on server::record_messages=on
'
\
'server::coach_w_referee=
1
'
\
%
(
server_port
,
coach_port
,
olcoach_port
,
%
(
server_port
,
coach_port
,
olcoach_port
,
args
.
logging
,
args
.
logging
,
args
.
logging
,
args
.
logging
,
args
.
logging
,
args
.
logging
,
args
.
logDir
,
args
.
logDir
,
args
.
logDir
,
args
.
logDir
,
args
.
logDir
,
args
.
logDir
,
args
.
sync
,
args
.
fullstate
,
args
.
fullstate
)
args
.
sync
,
args
.
fullstate
,
args
.
fullstate
)
# server::record_messages=on -- useful for debug
try
:
try
:
# Launch the Server
# Launch the Server
server
=
launch
(
serverCommand
+
serverOptions
,
name
=
'server'
)
server
=
launch
(
serverCommand
+
serverOptions
,
name
=
'server'
)
...
@@ -67,8 +68,7 @@ def main(args, team1='left', team2='right', rng=numpy.random.RandomState()):
...
@@ -67,8 +68,7 @@ def main(args, team1='left', team2='right', rng=numpy.random.RandomState()):
launch
(
monitorCommand
+
monitorOptions
,
name
=
'monitor'
)
launch
(
monitorCommand
+
monitorOptions
,
name
=
'monitor'
)
# Launch the Trainer
# Launch the Trainer
from
Trainer
import
Trainer
from
Trainer
import
Trainer
trainer
=
Trainer
(
args
=
args
,
rng
=
rng
,
server_port
=
server_port
,
trainer
=
Trainer
(
args
=
args
,
server_port
=
server_port
,
coach_port
=
coach_port
)
coach_port
=
coach_port
)
trainer
.
initComm
()
trainer
.
initComm
()
# Add Team1
# Add Team1
trainer
.
addTeam
(
team1
)
trainer
.
addTeam
(
team1
)
...
...
bin/Trainer.py
View file @
f8ec967c
...
@@ -14,33 +14,18 @@ class DoneError(Exception):
...
@@ -14,33 +14,18 @@ class DoneError(Exception):
class
Trainer
(
object
):
class
Trainer
(
object
):
""" Trainer is responsible for setting up the players and game.
""" Trainer is responsible for setting up the players and game.
"""
"""
def
__init__
(
self
,
args
,
rng
=
numpy
.
random
.
RandomState
(),
server_port
=
6001
,
def
__init__
(
self
,
args
,
server_port
=
6001
,
coach_port
=
6002
):
coach_port
=
6002
):
self
.
_rng
=
rng
# The Random Number Generator
self
.
_serverPort
=
server_port
# The port the server is listening on
self
.
_serverPort
=
server_port
# The port the server is listening on
self
.
_coachPort
=
coach_port
# The coach port to talk with the server
self
.
_coachPort
=
coach_port
# The coach port to talk with the server
self
.
_logDir
=
args
.
logDir
# Directory to store logs
self
.
_logDir
=
args
.
logDir
# Directory to store logs
self
.
_record
=
args
.
record
# Record states + actions
self
.
_record
=
args
.
record
# Record states + actions
self
.
_numOffense
=
args
.
offenseAgents
+
args
.
offenseNPCs
# Number offensive players
self
.
_numOffense
=
args
.
offenseAgents
+
args
.
offenseNPCs
# Number offensive players
self
.
_numDefense
=
args
.
defenseAgents
+
args
.
defenseNPCs
# Number defensive players
self
.
_numDefense
=
args
.
defenseAgents
+
args
.
defenseNPCs
# Number defensive players
self
.
_maxTrials
=
args
.
numTrials
# Maximum number of trials to play
self
.
_maxFrames
=
args
.
numFrames
# Maximum number of frames to play
self
.
_maxFramesPerTrial
=
args
.
maxFramesPerTrial
# =============== FIELD DIMENSIONS =============== #
self
.
NUM_FRAMES_TO_HOLD
=
2
# Hold ball this many frames to capture
self
.
HOLD_FACTOR
=
1.5
# Gain to calculate ball control
self
.
PITCH_WIDTH
=
68.0
# Width of the field
self
.
PITCH_LENGTH
=
105.0
# Length of field in long-direction
self
.
UNTOUCHED_LENGTH
=
100
# Trial will end if ball untouched for this long
# allowedBallX, allowedBallY defines the usable area of the playfield
self
.
_allowedBallX
=
numpy
.
array
([
-
0.1
,
0.5
*
self
.
PITCH_LENGTH
])
self
.
_allowedBallY
=
numpy
.
array
([
-
0.5
*
self
.
PITCH_WIDTH
,
0.5
*
self
.
PITCH_WIDTH
])
# =============== COUNTERS =============== #
# =============== COUNTERS =============== #
self
.
_numFrames
=
0
# Number of frames seen in HFO trials
self
.
_numFrames
=
0
# Number of frames seen in HFO trials
self
.
_numGoalFrames
=
0
# Number of frames in goal-scoring HFO trials
self
.
_numGoalFrames
=
0
# Number of frames in goal-scoring HFO trials
self
.
_frame
=
0
# Current frame id
self
.
_frame
=
0
# Current frame id
self
.
_lastTrialStart
=
-
1
# Frame Id in which the last trial started
self
.
_lastTrialStart
=
-
1
# Frame Id in which the last trial started
self
.
_lastFrameBallTouched
=
-
1
# Frame Id in which ball was last touched
# =============== TRIAL RESULTS =============== #
# =============== TRIAL RESULTS =============== #
self
.
_numTrials
=
0
# Total number of HFO trials
self
.
_numTrials
=
0
# Total number of HFO trials
self
.
_numGoals
=
0
# Trials in which the offense scored a goal
self
.
_numGoals
=
0
# Trials in which the offense scored a goal
...
@@ -59,20 +44,14 @@ class Trainer(object):
...
@@ -59,20 +44,14 @@ class Trainer(object):
# =============== MISC =============== #
# =============== MISC =============== #
self
.
_offenseTeamName
=
''
# Name of the offensive team
self
.
_offenseTeamName
=
''
# Name of the offensive team
self
.
_defenseTeamName
=
''
# Name of the defensive team
self
.
_defenseTeamName
=
''
# Name of the defensive team
self
.
_playerPositions
=
numpy
.
zeros
((
11
,
2
,
2
))
# Positions of the players
self
.
_ballPosition
=
numpy
.
zeros
(
2
)
# Position of the ball
self
.
_ballHeld
=
numpy
.
zeros
((
11
,
2
))
# Track player holding the ball
self
.
_teams
=
[]
# Team indexes for offensive and defensive teams
self
.
_teams
=
[]
# Team indexes for offensive and defensive teams
self
.
_SP
=
{}
# Sever Parameters. Recieved when connecting to the server.
self
.
_isPlaying
=
False
# Is a game being played?
self
.
_isPlaying
=
False
# Is a game being played?
self
.
_teamHoldingBall
=
None
# Team currently in control of the ball
self
.
_playerHoldingBall
=
None
# Player current in control of ball
self
.
_agentPopen
=
[]
# Agent's processes
self
.
_agentPopen
=
[]
# Agent's processes
self
.
_npcPopen
=
[]
# NPC's processes
self
.
_npcPopen
=
[]
# NPC's processes
self
.
_connectedPlayers
=
[]
self
.
_connectedPlayers
=
[]
self
.
initMsgHandlers
()
self
.
initMsgHandlers
()
def
launch_
player
(
self
,
player_num
,
play_offens
e
):
def
launch_
npc
(
self
,
player_num
,
play_offense
,
wait_until_join
=
Tru
e
):
"""Launches a player using sample_player binary
"""Launches a player using sample_player binary
Returns a Popen process object
Returns a Popen process object
...
@@ -96,9 +75,11 @@ class Trainer(object):
...
@@ -96,9 +75,11 @@ class Trainer(object):
kwargs
=
{
'stdout'
:
open
(
'/dev/null'
,
'w'
),
kwargs
=
{
'stdout'
:
open
(
'/dev/null'
,
'w'
),
'stderr'
:
open
(
'/dev/null'
,
'w'
)}
'stderr'
:
open
(
'/dev/null'
,
'w'
)}
p
=
subprocess
.
Popen
(
player_cmd
.
split
(
' '
),
shell
=
False
,
**
kwargs
)
p
=
subprocess
.
Popen
(
player_cmd
.
split
(
' '
),
shell
=
False
,
**
kwargs
)
if
wait_until_join
:
self
.
waitOnPlayer
(
player_num
,
play_offense
)
return
p
return
p
def
launch_agent
(
self
,
agent_num
,
play_offense
,
port
):
def
launch_agent
(
self
,
agent_num
,
agent_ext_num
,
play_offense
,
port
,
wait_until_join
=
True
):
"""Launches a learning agent using the agent binary
"""Launches a learning agent using the agent binary
Returns a Popen process object
Returns a Popen process object
...
@@ -122,7 +103,6 @@ class Trainer(object):
...
@@ -122,7 +103,6 @@ class Trainer(object):
self
.
_agentNumInt
.
append
(
internal_player_num
)
self
.
_agentNumInt
.
append
(
internal_player_num
)
numTeammates
=
self
.
_numDefense
-
1
numTeammates
=
self
.
_numDefense
-
1
numOpponents
=
self
.
_numOffense
numOpponents
=
self
.
_numOffense
ext_num
=
self
.
convertToExtPlayer
(
team_name
,
internal_player_num
)
binary_dir
=
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
))
binary_dir
=
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
))
config_dir
=
os
.
path
.
join
(
binary_dir
,
'../config/formations-dt'
)
config_dir
=
os
.
path
.
join
(
binary_dir
,
'../config/formations-dt'
)
player_conf
=
os
.
path
.
join
(
binary_dir
,
'../config/player.conf'
)
player_conf
=
os
.
path
.
join
(
binary_dir
,
'../config/player.conf'
)
...
@@ -133,13 +113,15 @@ class Trainer(object):
...
@@ -133,13 +113,15 @@ class Trainer(object):
%
(
team_name
,
self
.
_serverPort
,
numTeammates
,
%
(
team_name
,
self
.
_serverPort
,
numTeammates
,
numOpponents
,
play_offense
,
port
,
self
.
_logDir
,
numOpponents
,
play_offense
,
port
,
self
.
_logDir
,
player_conf
,
config_dir
)
player_conf
,
config_dir
)
if
ext_num
==
1
:
if
agent_
ext_num
==
1
:
agent_cmd
+=
' -g'
agent_cmd
+=
' -g'
if
self
.
_record
:
if
self
.
_record
:
agent_cmd
+=
' --record'
agent_cmd
+=
' --record'
kwargs
=
{
'stdout'
:
open
(
'/dev/null'
,
'w'
),
kwargs
=
{
'stdout'
:
open
(
'/dev/null'
,
'w'
),
'stderr'
:
open
(
'/dev/null'
,
'w'
)}
'stderr'
:
open
(
'/dev/null'
,
'w'
)}
p
=
subprocess
.
Popen
(
agent_cmd
.
split
(
' '
),
shell
=
False
,
**
kwargs
)
p
=
subprocess
.
Popen
(
agent_cmd
.
split
(
' '
),
shell
=
False
,
**
kwargs
)
if
wait_until_join
:
self
.
waitOnPlayer
(
agent_ext_num
,
play_offense
)
return
p
return
p
def
getDefensiveRoster
(
self
,
team_name
):
def
getDefensiveRoster
(
self
,
team_name
):
...
@@ -225,8 +207,32 @@ class Trainer(object):
...
@@ -225,8 +207,32 @@ class Trainer(object):
# self.send('(eye on)')
# self.send('(eye on)')
self
.
send
(
'(ear on)'
)
self
.
send
(
'(ear on)'
)
def
_hearRef
(
self
,
body
):
""" Handles hear messages from referee. """
assert
body
[
0
]
==
'referee'
,
'Expected referee message.'
_
,
ts
,
event
=
body
self
.
_frame
=
int
(
ts
)
if
event
==
'GOAL'
:
self
.
_numGoals
+=
1
self
.
_numGoalFrames
+=
self
.
_frame
-
self
.
_lastTrialStart
elif
event
==
'OUT_OF_BOUNDS'
:
self
.
_numBallsOOB
+=
1
elif
event
==
'CAPTURED_BY_DEFENSE'
:
self
.
_numBallsCaptured
+=
1
elif
event
==
'OUT_OF_TIME'
:
self
.
_numOutOfTime
+=
1
if
event
in
{
'GOAL'
,
'OUT_OF_BOUNDS'
,
'CAPTURED_BY_DEFENSE'
,
'OUT_OF_TIME'
}:
self
.
_numTrials
+=
1
print
'[Trainer] EndOfTrial:
%
d /
%
d
%
d
%
s'
%
\
(
self
.
_numGoals
,
self
.
_numTrials
,
self
.
_frame
,
event
)
self
.
_numFrames
+=
self
.
_frame
-
self
.
_lastTrialStart
self
.
_lastTrialStart
=
self
.
_frame
def
_hear
(
self
,
body
):
def
_hear
(
self
,
body
):
""" Handle a hear message. """
""" Handle a hear message. """
if
body
[
0
]
==
'referee'
:
self
.
_hearRef
(
body
)
return
timestep
,
playerInfo
,
msg
=
body
timestep
,
playerInfo
,
msg
=
body
try
:
try
:
_
,
team
,
player
=
playerInfo
[:
3
]
_
,
team
,
player
=
playerInfo
[:
3
]
...
@@ -242,7 +248,7 @@ class Trainer(object):
...
@@ -242,7 +248,7 @@ class Trainer(object):
elif
msg
==
'DONE'
:
elif
msg
==
'DONE'
:
raise
DoneError
raise
DoneError
elif
msg
==
'ready'
:
elif
msg
==
'ready'
:
print
'[Trainer] Agent
Ready
:'
,
team
,
player
print
'[Trainer] Agent
Connected
:'
,
team
,
player
self
.
_agentReady
.
add
((
team
,
player
))
self
.
_agentReady
.
add
((
team
,
player
))
else
:
else
:
print
'[Trainer] Unhandled message from agent:
%
s'
%
msg
print
'[Trainer] Unhandled message from agent:
%
s'
%
msg
...
@@ -257,7 +263,7 @@ class Trainer(object):
...
@@ -257,7 +263,7 @@ class Trainer(object):
self
.
ignoreMsg
(
'ok'
,
'move'
)
self
.
ignoreMsg
(
'ok'
,
'move'
)
self
.
ignoreMsg
(
'ok'
,
'recover'
)
self
.
ignoreMsg
(
'ok'
,
'recover'
)
self
.
ignoreMsg
(
'ok'
,
'say'
)
self
.
ignoreMsg
(
'ok'
,
'say'
)
self
.
registerMsgHandler
(
self
.
_handleSP
,
'server_param'
)
self
.
ignoreMsg
(
'server_param'
)
self
.
registerMsgHandler
(
self
.
_hear
,
'hear'
)
self
.
registerMsgHandler
(
self
.
_hear
,
'hear'
)
def
recv
(
self
,
retryCount
=
None
):
def
recv
(
self
,
retryCount
=
None
):
...
@@ -278,10 +284,6 @@ class Trainer(object):
...
@@ -278,10 +284,6 @@ class Trainer(object):
# print >>sys.stderr,len(expectedMsg),len(msg)
# print >>sys.stderr,len(expectedMsg),len(msg)
raise
ValueError
raise
ValueError
def
extractPoint
(
self
,
msg
):
""" Extract a point from the provided message. """
return
numpy
.
array
(
map
(
float
,
msg
[:
2
]))
def
convertToExtPlayer
(
self
,
team
,
num
):
def
convertToExtPlayer
(
self
,
team
,
num
):
""" Returns the external player number for a given player. """
""" Returns the external player number for a given player. """
assert
team
==
self
.
_offenseTeamName
or
team
==
self
.
_defenseTeamName
,
\
assert
team
==
self
.
_offenseTeamName
or
team
==
self
.
_defenseTeamName
,
\
...
@@ -292,33 +294,6 @@ class Trainer(object):
...
@@ -292,33 +294,6 @@ class Trainer(object):
else
:
else
:
return
self
.
_defenseOrder
[
num
]
return
self
.
_defenseOrder
[
num
]
def
convertFromExtPlayer
(
self
,
team
,
num
):
""" Maps external player number to internal player number. """
if
team
==
self
.
_offenseTeamName
:
return
self
.
_offenseOrder
.
index
(
num
)
else
:
return
self
.
_defenseOrder
.
index
(
num
)
def
seeGlobal
(
self
,
body
):
"""Send a look message to extract global information on ball and
player positions.
"""
self
.
send
(
'(look)'
)
self
.
_frame
=
int
(
body
[
0
])
for
obj
in
body
[
1
:]:
objType
=
obj
[
0
]
objData
=
obj
[
1
:]
if
objType
[
0
]
==
'g'
:
continue
elif
objType
[
0
]
==
'b'
:
self
.
_ballPosition
=
self
.
extractPoint
(
objData
)
elif
objType
[
0
]
==
'p'
:
teamName
=
objType
[
1
]
team
=
self
.
teamToInd
(
teamName
)
playerNum
=
self
.
convertFromExtPlayer
(
teamName
,
int
(
objType
[
2
]))
self
.
_playerPositions
[
playerNum
,:,
team
]
=
self
.
extractPoint
(
objData
)
def
registerMsgHandler
(
self
,
handler
,
*
args
,
**
kwargs
):
def
registerMsgHandler
(
self
,
handler
,
*
args
,
**
kwargs
):
'''Register a message handler.
'''Register a message handler.
...
@@ -361,18 +336,6 @@ class Trainer(object):
...
@@ -361,18 +336,6 @@ class Trainer(object):
""" Ignore a certain type of message. """
""" Ignore a certain type of message. """
self
.
registerMsgHandler
(
lambda
x
:
None
,
*
args
,
**
kwargs
)
self
.
registerMsgHandler
(
lambda
x
:
None
,
*
args
,
**
kwargs
)
def
_handleSP
(
self
,
body
):
""" Handler for the sever params message. """
for
param
in
body
:
try
:
val
=
int
(
param
[
1
])
except
:
try
:
val
=
float
(
param
[
1
])
except
:
val
=
param
[
1
]
self
.
_SP
[
param
[
0
]]
=
val
def
listenAndProcess
(
self
,
retry_count
=
None
):
def
listenAndProcess
(
self
,
retry_count
=
None
):
""" Gather messages and process them. """
""" Gather messages and process them. """
msg
=
self
.
recv
(
retry_count
)
msg
=
self
.
recv
(
retry_count
)
...
@@ -380,25 +343,21 @@ class Trainer(object):
...
@@ -380,25 +343,21 @@ class Trainer(object):
msg
=
self
.
parseMsg
(
msg
)
msg
=
self
.
parseMsg
(
msg
)
self
.
handleMsg
(
msg
)
self
.
handleMsg
(
msg
)
def
_readTeamNames
(
self
,
body
):
def
waitForDisconnect
(
self
,
player_num
,
on_offense
):
""" Read the names of each of the teams. """
"""Wait on a launched player to disconnect from the server. """
self
.
_teams
=
[]
self
.
send
(
'(look)'
)
for
_
,
_
,
team
in
body
:
partial
=
[
'ok'
,
'look'
]
self
.
_teams
.
append
(
team
)
self
.
_numPlayers
=
0
time
.
sleep
(
0.1
)
def
f
(
body
):
self
.
send
(
'(team_names)'
)
for
i
in
xrange
(
4
,
len
(
body
)):
_
,
team
,
num
=
body
[
i
][
0
][:
3
]
def
waitOnTeam
(
self
,
first
):
if
(
team
,
num
)
in
self
.
_connectedPlayers
:
"""Wait on a given team. First indicates if this is the first team
self
.
_connectedPlayers
.
remove
((
team
,
num
))
connected or the second.
self
.
registerMsgHandler
(
f
,
*
partial
,
quiet
=
True
)
team_name
=
self
.
_offenseTeamName
if
on_offense
else
self
.
_defenseTeamName
"""
while
(
team_name
,
str
(
player_num
))
in
self
.
_connectedPlayers
:
self
.
send
(
'(team_names)'
)
partial
=
[
'ok'
,
'team_names'
]
self
.
registerMsgHandler
(
self
.
_readTeamNames
,
*
partial
,
quiet
=
True
)
while
len
(
self
.
_teams
)
<
(
1
if
first
else
2
):
self
.
listenAndProcess
()
self
.
listenAndProcess
()
#self.unregisterMsgHandler(*partial
)
self
.
send
(
'(look)'
)
self
.
ignoreMsg
(
*
partial
,
quiet
=
True
)
self
.
ignoreMsg
(
*
partial
,
quiet
=
True
)
def
waitOnPlayer
(
self
,
player_num
,
on_offense
):
def
waitOnPlayer
(
self
,
player_num
,
on_offense
):
...
@@ -406,6 +365,7 @@ class Trainer(object):
...
@@ -406,6 +365,7 @@ class Trainer(object):
server.
server.
"""
"""
print
'Wait on player'
,
player_num
,
on_offense
self
.
send
(
'(look)'
)
self
.
send
(
'(look)'
)
partial
=
[
'ok'
,
'look'
]
partial
=
[
'ok'
,
'look'
]
self
.
_numPlayers
=
0
self
.
_numPlayers
=
0
...
@@ -436,210 +396,8 @@ class Trainer(object):
...
@@ -436,210 +396,8 @@ class Trainer(object):
def
startGame
(
self
):
def
startGame
(
self
):
""" Starts a game of HFO. """
""" Starts a game of HFO. """
self
.
reset
()
self
.
registerMsgHandler
(
self
.
seeGlobal
,
'see_global'
)
self
.
registerMsgHandler
(
self
.
seeGlobal
,
'ok'
,
'look'
,
quiet
=
True
)
#self.registerMsgHandler(self.checkBall,'ok','check_ball')
self
.
send
(
'(look)'
)
self
.
_isPlaying
=
True
def
calcBallHolder
(
self
):
'''Calculates the ball holder, returns results in teamInd, playerInd. '''
totalHeld
=
0
for
team
in
self
.
_teams
:
for
i
in
range
(
11
):
pos
=
self
.
_playerPositions
[
i
,:,
self
.
teamToInd
(
team
)]
distBound
=
self
.
_SP
[
'kickable_margin'
]
+
self
.
_SP
[
'player_size'
]
\
+
self
.
_SP
[
'ball_size'
]
distBound
*=
self
.
HOLD_FACTOR
if
numpy
.
linalg
.
norm
(
self
.
_ballPosition
-
pos
)
<
distBound
:
self
.
_ballHeld
[
i
,
self
.
teamToInd
(
team
)]
+=
1
totalHeld
+=
1
else
:
self
.
_ballHeld
[
i
,
self
.
teamToInd
(
team
)]
=
0
# If multiple players are close to the ball, no-one is holding
if
totalHeld
>
1
:
self
.
_ballHeld
[:,:]
=
0
inds
=
numpy
.
transpose
((
self
.
_ballHeld
>=
self
.
NUM_FRAMES_TO_HOLD
)
.
nonzero
())
assert
(
len
(
inds
)
<=
1
)
if
len
(
inds
)
==
1
:
return
inds
[
0
,
1
],
inds
[
0
,
0
]
else
:
return
None
,
None
def
isGoal
(
self
):
""" Returns true if a goal has been scored. """
return
(
self
.
_ballPosition
[
0
]
>
self
.
_allowedBallX
[
1
])
\
and
(
numpy
.
abs
(
self
.
_ballPosition
[
1
])
<=
0.5
*
self
.
_SP
[
'goal_width'
])
def
isOOB
(
self
):
""" Returns true if the ball is out of bounds. """
return
self
.
_ballPosition
[
0
]
<
self
.
_allowedBallX
[
0
]
\
or
self
.
_ballPosition
[
0
]
>
self
.
_allowedBallX
[
1
]
\
or
self
.
_ballPosition
[
1
]
<
self
.
_allowedBallY
[
0
]
\
or
self
.
_ballPosition
[
1
]
>
self
.
_allowedBallY
[
1
]
def
isCaptured
(
self
):
""" Returns true if the ball is captured by defense. """
return
self
.
_teamHoldingBall
not
in
[
None
,
self
.
_offenseTeamInd
]
def
isOOT
(
self
):
""" Returns true if the trial has run out of time. """
return
self
.
_frame
-
self
.
_lastFrameBallTouched
>
self
.
UNTOUCHED_LENGTH
\
or
(
self
.
_maxFramesPerTrial
>
0
and
self
.
_frame
-
self
.
_lastTrialStart
>
self
.
_maxFramesPerTrial
)
def
movePlayer
(
self
,
team
,
internal_num
,
pos
,
convertToExt
=
True
):
""" Move a player to a specified position.
Args:
team: the team name of the player
interal_num: the player's internal number
pos: position to move player to
convertToExt: convert interal player num to external
"""
num
=
self
.
convertToExtPlayer
(
team
,
internal_num
)
if
convertToExt
\
else
internal_num
self
.
send
(
'(move (player
%
s
%
i)
%
f
%
f)'
%
(
team
,
num
,
pos
[
0
],
pos
[
1
]))
def
moveBall
(
self
,
pos
):
""" Moves the ball to a specified x,y position. """
self
.
send
(
'(move (ball)
%
f
%
f 0.0 0.0 0.0)'
%
tuple
(
pos
))
def
randomPointInBounds
(
self
,
xBounds
=
None
,
yBounds
=
None
):
"""Returns a random point inside of the box defined by xBounds,
yBounds. Where xBounds=[x_min, x_max] and yBounds=[y_min,
y_max]. Defaults to the xy-bounds of the playable HFO area.
"""
if
xBounds
is
None
:
xBounds
=
self
.
allowedBallX
if
yBounds
is
None
:
yBounds
=
self
.
allowedBallY
pos
=
numpy
.
zeros
(
2
)
bounds
=
[
xBounds
,
yBounds
]
for
i
in
range
(
2
):
pos
[
i
]
=
self
.
_rng
.
rand
()
*
(
bounds
[
i
][
1
]
-
bounds
[
i
][
0
])
+
bounds
[
i
][
0
]
return
pos
def
boundPoint
(
self
,
pos
):
"""Ensures a point is within the minimum and maximum bounds of the
HFO playing area.
"""
pos
[
0
]
=
min
(
max
(
pos
[
0
],
self
.
_allowedBallX
[
0
]),
self
.
_allowedBallX
[
1
])
pos
[
1
]
=
min
(
max
(
pos
[
1
],
self
.
_allowedBallY
[
0
]),
self
.
_allowedBallY
[
1
])
return
pos
def
reset
(
self
):
""" Resets the HFO domain by moving the ball and players. """
self
.
resetBallPosition
()
self
.
resetPlayerPositions
()
self
.
send
(
'(recover)'
)
self
.
send
(
'(change_mode play_on)'
)
self
.
send
(
'(change_mode play_on)'
)
# self.send('(say RESET)')
self
.
_isPlaying
=
True
def
resetBallPosition
(
self
):
"""Reset the position of the ball for a new HFO trial. """
self
.
_ballPosition
=
self
.
boundPoint
(
self
.
randomPointInBounds
(
.2
*
self
.
_allowedBallX
+
.05
*
self
.
PITCH_LENGTH
,
.8
*
self
.
_allowedBallY
))
self
.
moveBall
(
self
.
_ballPosition
)
def
getOffensiveResetPosition
(
self
):
""" Returns a random position for an offensive player. """
offsets
=
[
[
-
1
,
-
1
],
[
-
1
,
1
],
[
1
,
1
],
[
1
,
-
1
],
[
0
,
2
],
[
0
,
-
2
],
[
-
2
,
-
2
],
[
-
2
,
2
],
[
2
,
2
],
[
2
,
-
2
],
]
offset
=
offsets
[
self
.
_rng
.
randint
(
len
(
offsets
))]
offset_from_ball
=
0.1
*
self
.
PITCH_LENGTH
*
self
.
_rng
.
rand
(
2
)
+
\
0.1
*
self
.
PITCH_LENGTH
*
numpy
.
array
(
offset
)
return
self
.
boundPoint
(
self
.
_ballPosition
+
offset_from_ball
)
# return self._ballPosition
def
getDefensiveResetPosition
(
self
):
""" Returns a random position for a defensive player. """
return
self
.
boundPoint
(
self
.
randomPointInBounds
(
[
0.5
*
0.5
*
self
.
PITCH_LENGTH
,
0.75
*
0.5
*
self
.
PITCH_LENGTH
],
0.8
*
self
.
_allowedBallY
))
def
resetPlayerPositions
(
self
):
"""Reset the positions of the players. This is called after a trial
ends to setup for the next trial.
"""
# Move the offense
for
i
in
xrange
(
1
,
self
.
_numOffense
+
1
):
self
.
movePlayer
(
self
.
_offenseTeamName
,
i
,
self
.
getOffensiveResetPosition
())
# Move the agent to the ball
if
self
.
_agentOnBall
and
self
.
_offenseAgents
>
0
:
self
.
movePlayer
(
self
.
_offenseTeamName
,
self
.
_agentNumInt
[
0
],
self
.
_ballPosition
)
# Move the defensive goalie
if
self
.
_numDefense
>
0
:
self
.
movePlayer
(
self
.
_defenseTeamName
,
0
,
[
0.5
*
self
.
PITCH_LENGTH
,
0
])
# Move the rest of the defense
for
i
in
xrange
(
1
,
self
.
_numDefense
):
self
.
movePlayer
(
self
.
_defenseTeamName
,
i
,
self
.
getDefensiveResetPosition
())
def
step
(
self
):
""" Takes a simulated step. """
self
.
_teamHoldingBall
,
self
.
_playerHoldingBall
=
self
.
calcBallHolder
()
if
self
.
_teamHoldingBall
is
not
None
:
self
.
_lastFrameBallTouched
=
self
.
_frame
if
self
.
trialOver
():
self
.
updateResults
()
self
.
_lastFrameBallTouched
=
self
.
_frame
self
.
reset
()
def
updateResults
(
self
):
""" Updates the various members after a trial has ended. """
if
self
.
isGoal
():
self
.
_numGoals
+=
1
self
.
_numGoalFrames
+=
self
.
_frame
-
self
.
_lastTrialStart
result
=
'Goal'
self
.
send
(
'(say GOAL)'
)
elif
self
.
isOOB
():
self
.
_numBallsOOB
+=
1
result
=
'Out of Bounds'
self
.
send
(
'(say OUT_OF_BOUNDS)'
)
elif
self
.
isCaptured
():
self
.
_numBallsCaptured
+=
1
result
=
'Defense Captured'
self
.
send
(
'(say CAPTURED_BY_DEFENSE)'
)
elif
self
.
isOOT
():
self
.
_numOutOfTime
+=
1
result
=
'Ball untouched for too long'
self
.
send
(
'(say OUT_OF_TIME)'
)
else
:
print
'[Trainer] Error: Unable to detect reason for End of Trial!'
sys
.
exit
(
1
)
self
.
_numTrials
+=
1
print
'[Trainer] EndOfTrial:
%
d /
%
d
%
d
%
s'
%
\
(
self
.
_numGoals
,
self
.
_numTrials
,
self
.
_frame
,
result
)
self
.
_numFrames
+=
self
.
_frame
-
self
.
_lastTrialStart
self
.
_lastTrialStart
=
self
.
_frame
if
(
self
.
_maxTrials
>
0
)
and
(
self
.
_numTrials
>=
self
.
_maxTrials
):
raise
DoneError
if
(
self
.
_maxFrames
>
0
)
and
(
self
.
_numFrames
>=
self
.
_maxFrames
):
raise
DoneError
def
trialOver
(
self
):
"""Returns true if the trial has ended for one of the following
reasons: Goal scored, out of bounds, captured by defense, or
untouched for too long.
"""
# The trial is still being setup, it cannot be over.
if
self
.
_frame
-
self
.
_lastTrialStart
<
5
:
return
False
return
self
.
isGoal
()
or
self
.
isOOB
()
or
self
.
isCaptured
()
or
self
.
isOOT
()
def
printStats
(
self
):
def
printStats
(
self
):
print
'[Trainer] TotalFrames =
%
i, AvgFramesPerTrial =
%.1
f, AvgFramesPerGoal =
%.1
f'
\
print
'[Trainer] TotalFrames =
%
i, AvgFramesPerTrial =
%.1
f, AvgFramesPerGoal =
%.1
f'
\
...
@@ -675,56 +433,54 @@ class Trainer(object):
...
@@ -675,56 +433,54 @@ class Trainer(object):
# Launch offense
# Launch offense
agent_num
=
0
agent_num
=
0
for
player_num
in
xrange
(
1
,
12
):
for
player_num
in
xrange
(
1
,
12
):
if
agent_num
<
self
.
_offenseAgents
and
\
if
agent_num
<
self
.
_offenseAgents
:
sorted_offense_agent_unums
[
agent_num
]
==
player_num
:
agent_ext_num
=
sorted_offense_agent_unums
[
agent_num
]
port
=
self
.
_agentServerPort
+
agent_num
if
agent_ext_num
==
player_num
:
agent
=
self
.
launch_agent
(
agent_num
,
play_offense
=
True
,
port
=
port
)
port
=
self
.
_agentServerPort
+
agent_num
self
.
_agentPopen
.
append
(
agent
)
agent
=
self
.
launch_agent
(
agent_num
,
agent_ext_num
,
necProcesses
.
append
([
agent
,
'offense_agent_'
+
str
(
agent_num
)])
play_offense
=
True
,
port
=
port
)
agent_num
+=
1
self
.
_agentPopen
.
append
(
agent
)
necProcesses
.
append
([
agent
,
'offense_agent_'
+
str
(
agent_num
)])
agent_num
+=
1
else
:
else
:
player
=
self
.
launch_player
(
player_num
,
play_offense
=
True
)
player
=
self
.
launch_npc
(
player_num
,
play_offense
=
True
)
time
.
sleep
(
0.15
)
if
player_num
in
offense_unums
:
if
player_num
in
offense_unums
:
self
.
_npcPopen
.
append
(
player
)
self
.
_npcPopen
.
append
(
player
)
necProcesses
.
append
([
player
,
'offense_npc_'
+
str
(
player_num
)])
necProcesses
.
append
([
player
,
'offense_npc_'
+
str
(
player_num
)])
else
:
else
:
player
.
terminate
()
player
.
kill
()
time
.
sleep
(
0.1
)
self
.
waitForDisconnect
(
player_num
,
on_offense
=
True
)
continue
self
.
waitOnPlayer
(
player_num
,
on_offense
=
True
)
self
.
waitOnTeam
(
first
=
False
)
# Launch defense
# Launch defense
agent_num
=
0
agent_num
=
0
for
player_num
in
xrange
(
1
,
12
):
for
player_num
in
xrange
(
1
,
12
):
if
agent_num
<
self
.
_defenseAgents
and
\
if
agent_num
<
self
.
_defenseAgents
:
sorted_defense_agent_unums
[
agent_num
]
==
player_num
:
agent_ext_num
=
sorted_offense_agent_unums
[
agent_num
]
port
=
self
.
_agentServerPort
+
agent_num
+
self
.
_offenseAgents
if
agent_ext_num
==
player_num
:
agent
=
self
.
launch_agent
(
agent_num
,
play_offense
=
False
,
port
=
port
)
port
=
self
.
_agentServerPort
+
agent_num
+
self
.
_offenseAgents
self
.
_agentPopen
.
append
(
agent
)
agent
=
self
.
launch_agent
(
agent_num
,
agent_ext_num
,
necProcesses
.
append
([
agent
,
'defense_agent_'
+
str
(
agent_num
)])
play_offense
=
False
,
port
=
port
)
agent_num
+=
1
self
.
_agentPopen
.
append
(
agent
)
necProcesses
.
append
([
agent
,
'defense_agent_'
+
str
(
agent_num
)])
agent_num
+=
1
else
:
else
:
player
=
self
.
launch_player
(
player_num
,
play_offense
=
False
)
player
=
self
.
launch_npc
(
player_num
,
play_offense
=
False
)
time
.
sleep
(
0.15
)
if
player_num
in
defense_unums
:
if
player_num
in
defense_unums
:
self
.
_npcPopen
.
append
(
player
)
self
.
_npcPopen
.
append
(
player
)
necProcesses
.
append
([
player
,
'defense_npc_'
+
str
(
player_num
)])
necProcesses
.
append
([
player
,
'defense_npc_'
+
str
(
player_num
)])
else
:
else
:
player
.
terminate
()
player
.
kill
()
time
.
sleep
(
0.1
)
self
.
waitForDisconnect
(
player_num
,
on_offense
=
False
)
continue
self
.
waitOnPlayer
(
player_num
,
on_offense
=
False
)
self
.
waitOnTeam
(
first
=
False
)
self
.
checkIfAllPlayersConnected
()
self
.
checkIfAllPlayersConnected
()
print
'[Trainer] Agents awaiting your connections'
if
self
.
_numAgents
>
0
:
necOff
=
set
([(
self
.
_offenseTeamName
,
str
(
x
))
for
x
in
sorted_offense_agent_unums
])
print
'[Trainer] Agents awaiting your connections'
necDef
=
set
([(
self
.
_defenseTeamName
,
str
(
x
))
for
x
in
sorted_defense_agent_unums
])
necOff
=
set
([(
self
.
_offenseTeamName
,
str
(
x
))
for
x
in
sorted_offense_agent_unums
])
necAgents
=
necOff
.
union
(
necDef
)
necDef
=
set
([(
self
.
_defenseTeamName
,
str
(
x
))
for
x
in
sorted_defense_agent_unums
])
while
self
.
checkLive
(
necProcesses
)
and
self
.
_agentReady
!=
necAgents
:
necAgents
=
necOff
.
union
(
necDef
)
self
.
listenAndProcess
(
1000
)
while
self
.
checkLive
(
necProcesses
)
and
self
.
_agentReady
!=
necAgents
:
self
.
listenAndProcess
(
10
)
# Broadcast the HFO configuration
# Broadcast the HFO configuration
offense_nums
=
' '
.
join
([
str
(
self
.
convertToExtPlayer
(
self
.
_offenseTeamName
,
i
))
offense_nums
=
' '
.
join
([
str
(
self
.
convertToExtPlayer
(
self
.
_offenseTeamName
,
i
))
...
@@ -736,13 +492,10 @@ class Trainer(object):
...
@@ -736,13 +492,10 @@ class Trainer(object):
%
(
self
.
_offenseTeamName
,
self
.
_defenseTeamName
,
%
(
self
.
_offenseTeamName
,
self
.
_defenseTeamName
,
self
.
_numOffense
,
self
.
_numDefense
,
self
.
_numOffense
,
self
.
_numDefense
,
offense_nums
,
defense_nums
))
offense_nums
,
defense_nums
))
print
'[Trainer] Starting game'
self
.
startGame
()
self
.
startGame
()
while
self
.
checkLive
(
necProcesses
):
while
self
.
checkLive
(
necProcesses
):
prevFrame
=
self
.
_frame
prevFrame
=
self
.
_frame
self
.
listenAndProcess
()
self
.
listenAndProcess
()
# if self._frame != prevFrame:
# self.step()
except
TimeoutError
:
except
TimeoutError
:
print
'[Trainer] Haven
\'
t heard from the server for too long, Exiting'
print
'[Trainer] Haven
\'
t heard from the server for too long, Exiting'
except
(
KeyboardInterrupt
,
DoneError
):
except
(
KeyboardInterrupt
,
DoneError
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment