Commit 5c4bd316 authored by drallensmith's avatar drallensmith

Merge branch 'randomization' into add_preprocess_action - bring in program cleanup

parents 23b0dde7 e9a54b78
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
#MODIFIED# #MODIFIED#
# First Start the server: $> bin/start.py # First Start the server: $> bin/start.py
import random, threading, argparse import argparse
import itertools import random
try: try:
from hfo import * import hfo
except: except ImportError:
print('Failed to import hfo. To install hfo, in the HFO directory'\ print('Failed to import hfo. To install hfo, in the HFO directory'\
' run: \"pip install .\"') ' run: \"pip install .\"')
exit() exit()
...@@ -16,79 +16,87 @@ params = {'SHT_DST':0.136664020547, 'SHT_ANG':-0.747394386098, ...@@ -16,79 +16,87 @@ params = {'SHT_DST':0.136664020547, 'SHT_ANG':-0.747394386098,
'PASS_ANG':0.464086704478, 'DRIB_DST':-0.999052871962} 'PASS_ANG':0.464086704478, 'DRIB_DST':-0.999052871962}
def can_shoot(goal_dist, goal_angle): def can_shoot(goal_dist, goal_angle):
"""Returns True if if player can have a good shot at goal""" """Returns True if if player may have a good shot at the goal"""
if goal_dist < params['SHT_DST'] and goal_angle > params['SHT_ANG']: return bool((goal_dist < params['SHT_DST']) and (goal_angle > params['SHT_ANG']))
return True
else:
return False
def has_better_pos(dist_to_op, goal_angle, pass_angle, curr_goal_angle): def has_better_pos(dist_to_op, goal_angle, pass_angle, curr_goal_angle):
"""Returns True if teammate is in a better attacking position""" """Returns True if teammate is in a better attacking position"""
if curr_goal_angle > goal_angle or dist_to_op<params['DRIB_DST']: if (curr_goal_angle > goal_angle) or (dist_to_op < params['DRIB_DST']):
return False return False
if pass_angle < params['PASS_ANG']: if pass_angle < params['PASS_ANG']:
return False return False
return True return True
def can_dribble(dist_to_op): def can_dribble(dist_to_op):
if dist_to_op > params['DRIB_DST']: return bool(dist_to_op > params['DRIB_DST'])
return True
else:
return False
def get_action(state,hfo_env,num_teammates): def get_action(state,hfo_env,num_teammates,rand_pass):
"""Returns the action to be taken by the agent""" """Decides and performs the action to be taken by the agent."""
goal_dist = float(state[6]) goal_dist = float(state[6])
goal_op_angle = float(state[8]) goal_op_angle = float(state[8])
if can_shoot(goal_dist, goal_op_angle): if can_shoot(goal_dist, goal_op_angle):
hfo_env.act(SHOOT) hfo_env.act(hfo.SHOOT)
return return
for i in range(num_teammates): if rand_pass and (num_teammates > 1):
team_list = random.shuffle(range(num_teammates))
else:
team_list = range(num_teammates)
for i in team_list:
teammate_uniform_number=state[10 + 3*num_teammates + 3*i +2] teammate_uniform_number=state[10 + 3*num_teammates + 3*i +2]
if has_better_pos(dist_to_op = float(state[10 + num_teammates + i]), if has_better_pos(dist_to_op = float(state[10 + num_teammates + i]),
goal_angle = float(state[10 + i]), goal_angle = float(state[10 + i]),
pass_angle = float(state[10 + 2*num_teammates + i]), pass_angle = float(state[10 + 2*num_teammates + i]),
curr_goal_angle = goal_op_angle): curr_goal_angle = goal_op_angle):
hfo_env.act(PASS, teammate_uniform_number) hfo_env.act(hfo.PASS, teammate_uniform_number)
return return
# not sure if below check is needed - doDribble in agent.cpp includes # not sure if below check is needed - doDribble in agent.cpp includes
# (via doPreprocess) doForceKick, which may cover this situation depending # (via doPreprocess) doForceKick, which may cover this situation depending
# on what existKickableOpponent returns. # on what existKickableOpponent returns.
if can_dribble(dist_to_op = state[9]): if can_dribble(dist_to_op = state[9]):
hfo_env.act(DRIBBLE) hfo_env.act(hfo.DRIBBLE)
return else:
# If nothing can be done, do not do anything # If nothing can be done, do not do anything
hfo_env.act(NOOP) hfo_env.act(hfo.NOOP)
return
def main(): def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('--port', type=int, default=6000) parser.add_argument('--port', type=int, default=6000, help="Server port")
parser.add_argument('--seed', type=int, default=None,
help="Seed for randomization; uses machine default if 0 or not given")
parser.add_argument('--rand-pass', action="store_true",
help="Randomize order of checking teammates for a possible pass")
parser.add_argument('--eps', type=float, default=0,
help="Probability of a random action if has the ball, to adjust difficulty")
parser.add_argument('--numTeammates', type=int, default=0) parser.add_argument('--numTeammates', type=int, default=0)
parser.add_argument('--numOpponents', type=int, default=1) parser.add_argument('--numOpponents', type=int, default=1)
args=parser.parse_args() args=parser.parse_args()
hfo_env = HFOEnvironment() if args.seed:
hfo_env.connectToServer(HIGH_LEVEL_FEATURE_SET, random.seed(args.seed)
hfo_env = hfo.HFOEnvironment()
hfo_env.connectToServer(hfo.HIGH_LEVEL_FEATURE_SET,
'bin/teams/base/config/formations-dt', args.port, 'bin/teams/base/config/formations-dt', args.port,
'localhost', 'base_left', False) 'localhost', 'base_left', False)
#itertools.count() counts forever status=hfo.IN_GAME
for episode in itertools.count(): while status != hfo.SERVER_DOWN:
status=IN_GAME
count=0
while status==IN_GAME:
state = hfo_env.getState() state = hfo_env.getState()
#print(state) #print(state)
if int(state[5]) == 1: # state[5] is 1 when player has the ball if int(state[5]) == 1: # state[5] is 1 when player has the ball
tmp = get_action(state,hfo_env,args.numTeammates) if (args.eps > 0) and (random.random() < args.eps):
#print(tmp) if random.random() < 0.5:
#hfo_env.act(tmp) hfo_env.act(hfo.SHOOT)
else: else:
hfo_env.act(MOVE) hfo_env.act(hfo.DRIBBLE)
else:
get_action(state,hfo_env,args.numTeammates,args.rand_pass)
else:
hfo_env.act(hfo.MOVE)
status=hfo_env.step() status=hfo_env.step()
#print(status) #print(status)
if status == SERVER_DOWN:
hfo_env.act(QUIT) hfo_env.act(hfo.QUIT)
exit() exit()
......
...@@ -4,34 +4,53 @@ ...@@ -4,34 +4,53 @@
# Before running this program, first Start HFO server: # Before running this program, first Start HFO server:
# $> ./bin/HFO --offense-agents 1 # $> ./bin/HFO --offense-agents 1
import random, itertools import argparse
from hfo import * import itertools
import random
try:
import hfo
except ImportError:
print('Failed to import hfo. To install hfo, in the HFO directory'\
' run: \"pip install .\"')
exit()
def main(): def main():
parser = argparse.ArgumentParser()
parser.add_argument('--port', type=int, default=6000,
help="Server port")
parser.add_argument('--seed', type=int, default=None,
help="Randomization seed (uses machine default if 0 or not given")
args=parser.parse_args()
if args.seed:
random.seed(args.seed)
# Create the HFO Environment # Create the HFO Environment
hfo = HFOEnvironment() hfo_env = hfo.HFOEnvironment()
# Connect to the server with the specified # Connect to the server with the specified
# feature set. See feature sets in hfo.py/hfo.hpp. # feature set. See feature sets in hfo.py/hfo.hpp.
hfo.connectToServer(HIGH_LEVEL_FEATURE_SET, hfo_env.connectToServer(hfo.HIGH_LEVEL_FEATURE_SET,
'bin/teams/base/config/formations-dt', 6000, 'bin/teams/base/config/formations-dt', args.port,
'localhost', 'base_left', False) 'localhost', 'base_left', False)
for episode in itertools.count(): for episode in itertools.count():
status = IN_GAME status = hfo.IN_GAME
while status == IN_GAME: while status == hfo.IN_GAME:
# Get the vector of state features for the current state # Get the vector of state features for the current state
state = hfo.getState() state = hfo_env.getState()
# Perform the action # Perform the action
if state[5] == 1: # State[5] is 1 when the player can kick the ball if state[5] == 1: # State[5] is 1 when the player can kick the ball
hfo.act(random.choice([SHOOT, DRIBBLE])) if random.random() < 0.5: # more efficient than random.choice for 2
hfo_env.act(hfo.SHOOT)
else:
hfo_env.act(hfo.DRIBBLE)
else: else:
hfo.act(MOVE) hfo_env.act(hfo.MOVE)
# Advance the environment and get the game status # Advance the environment and get the game status
status = hfo.step() status = hfo_env.step()
# Check the outcome of the episode # Check the outcome of the episode
print(('Episode %d ended with %s'%(episode, hfo.statusToString(status)))) print(('Episode %d ended with %s'%(episode, hfo.statusToString(status))))
# Quit if the server goes down # Quit if the server goes down
if status == SERVER_DOWN: if status == hfo.SERVER_DOWN:
hfo.act(QUIT) hfo_env.act(hfo.QUIT)
exit() exit()
if __name__ == '__main__': if __name__ == '__main__':
......
# Run this file to create an executable of hand_coded_defense_agent.cpp
g++ -c hand_coded_defense_agent.cpp -I ../src/ -std=c++0x -pthread
g++ -L ../lib/ hand_coded_defense_agent.o -lhfo -pthread -o hand_coded_defense_agent -Wl,-rpath,../lib
#!/bin/bash
./bin/HFO --offense-agents=2 --defense-npcs=3 --offense-npcs=1 --trials 20 --headless &
sleep 5
# -x is needed to skip first line - otherwise whatever default python version is will run
python2.7 -x ./example/high_level_custom_agent.py --eps 0.2 --numTeammates=2 --numOpponents=3 --port 6000 &> agent1.txt &
sleep 5
python3 -x ./example/high_level_custom_agent.py --eps 0.2 --numTeammates=2 --numOpponents=3 --port 6000 &> agent2.txt &
# The magic line
# $$ holds the PID for this script
# Negation means kill by process group id instead of PID
trap "kill -TERM -$$" SIGINT
wait
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