Commit a02aa143 authored by Matthew Hausknecht's avatar Matthew Hausknecht Committed by GitHub

Merge pull request #41 from drallensmith/add_reorient

Add reorient - should be separated out from feedback
parents 8fc485f3 732c2b99
...@@ -16,13 +16,14 @@ RoboCup 2D Half Field Offense ...@@ -16,13 +16,14 @@ RoboCup 2D Half Field Offense
- numpy - numpy
## Install ## Install
Note: There is no need for 'sudo' with 'make install' - the files will be installed below the starting directory.
``` ```
mkdir build && cd build mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=RelwithDebInfo .. cmake -DCMAKE_BUILD_TYPE=RelwithDebInfo ..
make -j4 make -j4
make install make install
``` ```
Note: There is no need for 'sudo' with 'make install' - the files will be installed below the starting directory.
#### Python Install [required for python interface] #### Python Install [required for python interface]
From the main HFO directory: `pip install [--user] .` From the main HFO directory: `pip install [--user] .`
......
No preview for this file type
...@@ -573,9 +573,9 @@ faithfully report which action spaces were used. ...@@ -573,9 +573,9 @@ faithfully report which action spaces were used.
\label{sec:high_level_actions} \label{sec:high_level_actions}
\begin{itemize}[noitemsep] \begin{itemize}[noitemsep]
\item{\textbf{Move}(): Re-positions the agent according to the \item{\textbf{Move}(): Re-positions the agent according to the
strategy given by Agent2D. The \textit{move} command works only when strategy given by Agent2D. The \textit{Move} command works only when
agent does not have the ball. If the agent has the ball, another the agent does not have the ball. If the agent has the ball, another
command such as \textit{dribble}, \textit{shoot}, or \textit{pass} command such as \textit{Dribble}, \textit{Shoot}, or \textit{Pass}
should be used.} should be used.}
\item{\textbf{Shoot}(): Executes the best available shot. This command \item{\textbf{Shoot}(): Executes the best available shot. This command
only works when the agent has the ball.} only works when the agent has the ball.}
...@@ -594,7 +594,8 @@ faithfully report which action spaces were used. ...@@ -594,7 +594,8 @@ faithfully report which action spaces were used.
\item{\textbf{Go\_To\_Ball}(): Makes the agent go towards the ball.} \item{\textbf{Go\_To\_Ball}(): Makes the agent go towards the ball.}
\item{\textbf{Mark\_Player}(uniform\_number): Moves the agent so as to mark the player \item{\textbf{Mark\_Player}(uniform\_number): Moves the agent so as to mark the player
with the specified uniform number.} with the specified uniform number.}
\item{\textbf{Reorient}(): Deal with loss of self or ball localization information and
pay increased attention to surroundings.}
\end{itemize} \end{itemize}
\subsection{Special Actions} \subsection{Special Actions}
...@@ -611,29 +612,29 @@ below the table for the action abbreviations and notes. ...@@ -611,29 +612,29 @@ below the table for the action abbreviations and notes.
\begin{center} \begin{center}
{\footnotesize {\footnotesize
\begin{tabular}{r | c c c c | c c c c | c c c c c c c c c} \begin{tabular}{r | c c c c | c c c c | c c c c c c c c c c}
Action & Da & Tu & Ta & K & KT & MT & DT & I & M & S & P & D & C & RG & DG & G & MP \\ Action & Da & Tu & Ta & K & KT & MT & DT & I & M & S & P & D & C & RG & DG & G & MP & Re \\
\hline \hline \hline \hline
Self position invalid & Y & Y & Y & Y & N & N & N & N & N & N & N & Y & Y & N & N & N & N \\ Self position invalid & Y & Y & Y & Y & N & N & N & N & N & N & N & Y & Y & N & N & N & N & Y \\
Self velocity invalid & N & Y & Y & Y & N & N & N & N & N & N & Y & Y & Y & N & N & N & N \\ Self velocity invalid & N & Y & Y & Y & N & N & N & N & N & N & Y & Y & Y & N & N & N & N & Y \\
Ball position invalid & Y & Y & Y & N & N & Y & Y & N & N & N & N & Y & N & N & N & N & N \\ Ball position invalid & Y & Y & Y & N & N & Y & Y & N & N & N & N & Y & N & N & N & N & N & Y \\
Ball velocity invalid & Y & Y & Y & Y & N & Y & N & Y & Y & N & N & Y & Y & Y & Y & Y & Y \\ Ball velocity invalid & Y & Y & Y & Y & N & Y & N & Y & Y & N & N & Y & Y & Y & Y & Y & Y & Y \\
Teammate loc invalid & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & N & Y & Y & Y & Y & Y & Y \\ Teammate loc invalid & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & N & Y & Y & Y & Y & Y & Y & Y \\
Team. unum invalid & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & N & Y & Y & Y & Y & Y & Y \\ Team. unum invalid & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & N & Y & Y & Y & Y & Y & Y & Y \\
Opponent loc invalid & Y & Y & Y & Y & Y & Y & N & Y & N & Y & Y & N & Y & Y & Y & Y & N \\ Opponent loc invalid & Y & Y & Y & Y & Y & Y & N & Y & N & Y & Y & N & Y & Y & Y & Y & N & Y \\
Opp. unum invalid & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & N \\ Opp. unum invalid & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & N & Y \\
\hline \hline
Ball kickable & Y & Y & Y & Y & Y & N & Y & N & * & Y & Y & Y & Y & N & N & N & Y \\ Ball kickable & Y & Y & Y & Y & Y & N & Y & N & * & Y & Y & Y & Y & N & N & N & Y & N \\
Ball not kickable & Y & Y & Y & N & N & Y & Y & Y & Y & N & N & N & Y & Y & Y & Y & Y \\ Ball not kickable & Y & Y & Y & N & N & Y & Y & Y & Y & N & N & N & Y & Y & Y & Y & Y & Y \\
\hline \hline
Frozen & N & N & N & N & N & N & N & N & N & N & N & N & N & N & N & N & N \\ Frozen & N & N & N & N & N & N & N & N & N & N & N & N & N & N & N & N & N & Y \\
Colliding w/ball & Y & Y & N & N & Y & N & Y & Y & Y & Y & Y & Y & Y & N & N & N & N \\ Colliding w/ball & Y & Y & N & N & Y & N & Y & Y & Y & Y & Y & Y & Y & N & N & N & N & N \\
Colliding w/player & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & N & Y & Y & Y & Y & Y & Y \\ Colliding w/player & Y & Y & Y & Y & Y & Y & Y & Y & Y & Y & N & Y & Y & Y & Y & Y & Y & Y \\
Colliding w/post & Y & Y & Y & Y & Y & Y & N & Y & Y & Y & N & Y & Y & Y & Y & Y & Y \\ Colliding w/post & Y & Y & Y & Y & Y & Y & N & Y & Y & Y & N & Y & Y & Y & Y & Y & Y & Y \\
\hline \hline
Offense & Y & Y & N & Y & Y & Y & Y & Y & Y & Y & Y & Y & N & N & N & Y & N \\ Offense & Y & Y & N & Y & Y & Y & Y & Y & Y & Y & Y & Y & N & N & N & Y & N & Y \\
Defense, not goalie & Y & Y & Y & N & N & Y & N & Y & Y & N & N & N & N & Y & Y & Y & Y \\ Defense, not goalie & Y & Y & Y & N & N & Y & N & Y & Y & N & N & N & N & Y & Y & Y & Y & Y \\
Goalie (defense) & Y & Y & Y & N & N & Y & N & Y & Y & N & N & N & Y & N & Y & N & N \\ Goalie (defense) & Y & Y & Y & N & N & Y & N & Y & Y & N & N & N & Y & N & Y & N & N & Y \\
\end{tabular} \end{tabular}
} }
\end{center} \end{center}
...@@ -641,7 +642,7 @@ Goalie (defense) & Y & Y & Y & N & N & Y & N & Y & Y & N & N & N & ...@@ -641,7 +642,7 @@ Goalie (defense) & Y & Y & Y & N & N & Y & N & Y & Y & N & N & N &
\begin{itemize}[noitemsep] \begin{itemize}[noitemsep]
\item{Da:\,Dash; Tu:\,Turn; Ta:\,Tackle; K:\,Kick} \item{Da:\,Dash; Tu:\,Turn; Ta:\,Tackle; K:\,Kick}
\item{KT:\,Kick\_To; MT:\,Move\_To; DT:\,Dribble\_To; I:\,Intercept} \item{KT:\,Kick\_To; MT:\,Move\_To; DT:\,Dribble\_To; I:\,Intercept}
\item{M:\,Move; S:\,Shoot; P:\,Pass; D:\,Dribble; C:\,Catch; RG:\,Reduce\_Angle\_To\_Goal; DG:\,Defend\_Goal; G:\,Go\_To\_Ball; MP:\,Mark\_Player} \item{M:\,Move; S:\,Shoot; P:\,Pass; D:\,Dribble; C:\,Catch; RG:\,Reduce\_Angle\_To\_Goal; DG:\,Defend\_Goal; G:\,Go\_To\_Ball; MP:\,Mark\_Player; Re: Reorient}
\end{itemize} \end{itemize}
\section{Developing a New Agent} \section{Developing a New Agent}
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# Change to a different seed for different experiments! # Change to a different seed for different experiments!
./bin/HFO --offense-npcs=2 --defense-agents=1 --defense-npcs=1 --trials 5000 --headless --seed 1500348586 --no-logging --hfo-logging & ./bin/HFO --offense-npcs=2 --defense-agents=1 --defense-npcs=1 --trials 5000 --headless --seed 1500348586 --no-logging --hfo-logging &
# Sleep is needed to make sure doesn't get connected too soon, as unum 1 (goalie) # Sleep is needed to make sure doesn't get connected too soon, as unum 1 (goalie)
sleep 15 sleep 15
./example/hand_coded_defense_agent.py &> agent1.txt & ./example/hand_coded_defense_agent.py &> agent1.txt &
......
...@@ -104,7 +104,7 @@ def do_defense_action(state_vec, hfo_env, ...@@ -104,7 +104,7 @@ def do_defense_action(state_vec, hfo_env,
# if get high_level working for invalid # if get high_level working for invalid
if (min(agent_pos_x,agent_pos_y,ball_pos_x,ball_pos_y) < -1): if (min(agent_pos_x,agent_pos_y,ball_pos_x,ball_pos_y) < -1):
hfo_env.act(hfo.MOVE) # will be Reorient in that version hfo_env.act(add_num_times(hfo.REORIENT,num_times_overall))
return return
ball_toward_goal = ball_moving_toward_goal(ball_pos_x, ball_pos_y, ball_toward_goal = ball_moving_toward_goal(ball_pos_x, ball_pos_y,
...@@ -118,11 +118,16 @@ def do_defense_action(state_vec, hfo_env, ...@@ -118,11 +118,16 @@ def do_defense_action(state_vec, hfo_env,
if not ball_sorted_list: # unknown opponent positions/unums if not ball_sorted_list: # unknown opponent positions/unums
print("No known opponent locations (btg {0!r}; bng {1!r}; ".format(ball_toward_goal, print("No known opponent locations (btg {0!r}; bng {1!r}; ".format(ball_toward_goal,
ball_nearer_goal) + ball_nearer_goal) +
"ball xy {0:n}, {1:n}; ball old xy {2:n}, {3:n})".format(ball_pos_x, "ball xy {0:n}, {1:n}; ball old xy {2:n}, {3:n}; kickable {4:n})".format(ball_pos_x,
ball_pos_y, ball_pos_y,
old_ball_pos_x, old_ball_pos_x,
old_ball_pos_y)) old_ball_pos_y,
if ball_toward_goal: state_vec[5]))
if ((min(agent_pos_x,agent_pos_y,ball_pos_x,ball_pos_y) <= -1) or
(max(agent_pos_x,agent_pos_y,ball_pos_x,ball_pos_y) >= 1)):
# remove if get high-level working for invalid
hfo_env.act(add_num_times(hfo.REORIENT,num_times_overall))
elif ball_toward_goal:
if ball_nearer_goal: if ball_nearer_goal:
hfo_env.act(add_num_times(hfo.REDUCE_ANGLE_TO_GOAL,num_times_overall)) hfo_env.act(add_num_times(hfo.REDUCE_ANGLE_TO_GOAL,num_times_overall))
else: else:
......
#!/usr/bin/env python
from __future__ import print_function
# encoding: utf-8
# Before running this program, first Start HFO server:
# $> ./bin/HFO --offense-agents 1
import argparse
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():
parser = argparse.ArgumentParser()
parser.add_argument('--port', type=int, default=6000,
help="Server port")
parser.add_argument('--seed', type=int, default=None,
help="Python randomization seed; uses python default if 0 or not given")
parser.add_argument('--no-reorient', action='store_true',
help="Do not use the new Reorient action")
parser.add_argument('--record', action='store_true',
help="Doing HFO --record")
parser.add_argument('--rdir', type=str, default='log/',
help="Set directory to use if doing HFO --record")
args=parser.parse_args()
if args.seed:
random.seed(args.seed)
# Create the HFO Environment
hfo_env = hfo.HFOEnvironment()
# Connect to the server with the specified
# feature set. See feature sets in hfo.py/hfo.hpp.
if args.record:
hfo_env.connectToServer(hfo.LOW_LEVEL_FEATURE_SET,
'bin/teams/base/config/formations-dt', args.port,
'localhost', 'base_left', False,
record_dir=args.rdir)
else:
hfo_env.connectToServer(hfo.LOW_LEVEL_FEATURE_SET,
'bin/teams/base/config/formations-dt', args.port,
'localhost', 'base_left', False)
if args.seed:
print("Python randomization seed: {0:d}".format(args.seed))
for episode in itertools.count():
num_reorient = 0
num_move = 0
num_had_ball = 0
status = hfo.IN_GAME
while status == hfo.IN_GAME:
# Get the vector of state features for the current state
state = hfo_env.getState()
# Perform the action
# 8 is frozen; 0 is self position valid, 1 is self velocity valid, 54 is ball velocity valid
if (((state[8] > 0) or (min(state[0],state[1],state[54]) < 0)) and not args.no_reorient):
hfo_env.act(hfo.REORIENT)
num_reorient += 1
elif state[12] > 0: # State[12] is 1 when the player can kick the ball
if random.random() < 0.5: # more efficient than random.choice for 2
hfo_env.act(hfo.SHOOT)
else:
hfo_env.act(hfo.DRIBBLE)
num_had_ball += 1
# 50 is ball position valild
elif (state[50] < 0) and not args.no_reorient:
hfo_env.act(hfo.REORIENT)
num_reorient += 1
else:
hfo_env.act(hfo.MOVE)
num_move += 1
# Advance the environment and get the game status
status = hfo_env.step()
# Check the outcome of the episode
print("Episode {0:d} ended with status {1}".format(episode,
hfo_env.statusToString(status)))
print("\tHad ball: {0:d}; Reorient: {1:d}; Move: {2:d}".format(num_had_ball,
num_reorient,
num_move))
# Quit if the server goes down
if status == hfo.SERVER_DOWN:
hfo_env.act(hfo.QUIT)
exit()
if __name__ == '__main__':
main()
#!/usr/bin/env python #!/usr/bin/env python
from __future__ import print_function
# encoding: utf-8 # encoding: utf-8
# Before running this program, first Start HFO server: # Before running this program, first Start HFO server:
...@@ -23,9 +24,9 @@ def main(): ...@@ -23,9 +24,9 @@ def main():
parser.add_argument('--seed', type=int, default=None, parser.add_argument('--seed', type=int, default=None,
help="Python randomization seed; uses python default if 0 or not given") help="Python randomization seed; uses python default if 0 or not given")
parser.add_argument('--record', action='store_true', parser.add_argument('--record', action='store_true',
help="Doing HFO --record") help="If doing HFO --record")
parser.add_argument('--rdir', type=str, default='log/', parser.add_argument('--rdir', type=str, default='log/',
help="Set directory to use if doing HFO --record") help="Set directory to use if doing --record")
args=parser.parse_args() args=parser.parse_args()
if args.seed: if args.seed:
random.seed(args.seed) random.seed(args.seed)
...@@ -42,6 +43,10 @@ def main(): ...@@ -42,6 +43,10 @@ def main():
hfo_env.connectToServer(hfo.HIGH_LEVEL_FEATURE_SET, 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)
if args.seed:
print("Python randomization seed: {0:d}".format(args.seed))
for episode in itertools.count(): for episode in itertools.count():
status = hfo.IN_GAME status = hfo.IN_GAME
while status == hfo.IN_GAME: while status == hfo.IN_GAME:
...@@ -59,8 +64,9 @@ def main(): ...@@ -59,8 +64,9 @@ def main():
status = hfo_env.step() status = hfo_env.step()
# Check the outcome of the episode # Check the outcome of the episode
end_status = hfo_env.statusToString(status) end_status = hfo_env.statusToString(status)
print("Episode {} ended with {}".format(episode, end_status)) print("Episode {0:n} ended with {1:s}".format(episode, end_status))
# Quit if the server goes down # Quit if the server goes down
if status == hfo.SERVER_DOWN: if status == hfo.SERVER_DOWN:
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
./bin/HFO --offense-agents=2 --defense-npcs=3 --offense-npcs=1 --trials 20 --headless & ./bin/HFO --offense-agents=2 --defense-npcs=3 --offense-npcs=1 --trials 20 --headless &
sleep 5 sleep 5
# -x is needed to skip first line - otherwise whatever default python version is will run # -x is needed to skip first line - otherwise whatever default python version is will run
python -x ./example/high_level_custom_agent.py --port 6000 &> agent1.txt & python ./example/high_level_custom_agent.py --port 6000 &> agent1.txt &
sleep 5 sleep 5
python -x ./example/high_level_custom_agent.py --port 6000 &> agent2.txt & python ./example/high_level_custom_agent.py --port 6000 &> agent2.txt &
# The magic line # The magic line
# $$ holds the PID for this script # $$ holds the PID for this script
......
...@@ -2,10 +2,12 @@ ...@@ -2,10 +2,12 @@
./bin/HFO --offense-agents=2 --defense-npcs=3 --offense-npcs=1 --trials 20 --headless & ./bin/HFO --offense-agents=2 --defense-npcs=3 --offense-npcs=1 --trials 20 --headless &
sleep 5 sleep 5
# -x is needed to skip first line - otherwise whatever default python version is will run
python -x ./example/high_level_custom_agent.py --eps 0.2 --port 6000 &> agent1.txt & # If wanting to test below with different python versions, add -x to avoid
# the #!/usr/bin/env python initial line.
python ./example/high_level_custom_agent.py --eps 0.2 --port 6000 &> agent1.txt &
sleep 5 sleep 5
python -x ./example/high_level_custom_agent.py --eps 0.2 --port 6000 &> agent2.txt & python ./example/high_level_custom_agent.py --eps 0.2 --port 6000 &> agent2.txt &
# The magic line # The magic line
# $$ holds the PID for this script # $$ holds the PID for this script
......
#!/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 --numTeammates=2 --numOpponents=3 --rand-pass --port 6000 &> agent1.txt &
sleep 5
python3 -x ./example/high_level_custom_agent.py --numTeammates=2 --numOpponents=3 --rand-pass --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
#!/bin/bash
./bin/HFO --offense-agents=2 --defense-npcs=1 --trials 20 --headless &
sleep 5
python2.7 -x example/high_action_random_agent.py --port 6000 &> agent1.txt &
sleep 5
python3 -x example/high_action_random_agent.py --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
...@@ -2,9 +2,13 @@ ...@@ -2,9 +2,13 @@
./bin/HFO --offense-agents=2 --defense-npcs=1 --trials 20 --headless & ./bin/HFO --offense-agents=2 --defense-npcs=1 --trials 20 --headless &
sleep 5 sleep 5
python -x example/high_level_random_agent.py --port 6000 &> agent1.txt &
# If wanting to test below with different python versions, add -x to avoid
# the #!/usr/bin/env python initial line.
python example/high_level_random_agent.py --port 6000 &> agent1.txt &
sleep 5 sleep 5
python -x example/high_level_random_agent.py --port 6000 &> agent2.txt & python example/high_level_random_agent.py --port 6000 &> agent2.txt &
# The magic line # The magic line
# $$ holds the PID for this script # $$ holds the PID for this script
......
...@@ -26,10 +26,10 @@ LOW_LEVEL_FEATURE_SET, HIGH_LEVEL_FEATURE_SET = list(range(NUM_FEATURE_SETS)) ...@@ -26,10 +26,10 @@ LOW_LEVEL_FEATURE_SET, HIGH_LEVEL_FEATURE_SET = list(range(NUM_FEATURE_SETS))
[High-Level] Catch(): Catch the ball (Goalie Only) [High-Level] Catch(): Catch the ball (Goalie Only)
NOOP(): Do Nothing NOOP(): Do Nothing
QUIT(): Quit the game ''' QUIT(): Quit the game '''
NUM_HFO_ACTIONS = 19 NUM_HFO_ACTIONS = 20
DASH, TURN, TACKLE, KICK, KICK_TO, MOVE_TO, DRIBBLE_TO, INTERCEPT, \ DASH, TURN, TACKLE, KICK, KICK_TO, MOVE_TO, DRIBBLE_TO, INTERCEPT, \
MOVE, SHOOT, PASS, DRIBBLE, CATCH, NOOP, QUIT, REDUCE_ANGLE_TO_GOAL,MARK_PLAYER,DEFEND_GOAL,GO_TO_BALL = list(range(NUM_HFO_ACTIONS)) MOVE, SHOOT, PASS, DRIBBLE, CATCH, NOOP, QUIT, REDUCE_ANGLE_TO_GOAL,MARK_PLAYER,DEFEND_GOAL,GO_TO_BALL,REORIENT = list(range(NUM_HFO_ACTIONS))
ACTION_STRINGS = ["Dash", "Turn", "Tackle", "Kick", "KickTo", "MoveTo", "DribbleTo", "Intercept", "Move", "Shoot", "Pass", "Dribble", "Catch", "No-op", "Quit", "Reduce_Angle_To_Goal", "Mark_Player", "Defend_Goal", "Go_To_Ball"] ACTION_STRINGS = ["Dash", "Turn", "Tackle", "Kick", "KickTo", "MoveTo", "DribbleTo", "Intercept", "Move", "Shoot", "Pass", "Dribble", "Catch", "No-op", "Quit", "Reduce_Angle_To_Goal", "Mark_Player", "Defend_Goal", "Go_To_Ball", "Reorient"]
''' Possible game status ''' Possible game status
[IN_GAME] Game is currently active [IN_GAME] Game is currently active
...@@ -98,7 +98,7 @@ class HFOEnvironment(object): ...@@ -98,7 +98,7 @@ class HFOEnvironment(object):
play_goalie=False, play_goalie=False,
record_dir=''): record_dir=''):
""" """
Connect to the server on the specified port. The Connects to the server on the specified port. The
following information is provided by the ./bin/HFO following information is provided by the ./bin/HFO
feature_set: High or low level state features feature_set: High or low level state features
...@@ -130,7 +130,7 @@ class HFOEnvironment(object): ...@@ -130,7 +130,7 @@ class HFOEnvironment(object):
hfo_lib.act(self.obj, action_type, params.ctypes.data_as(POINTER(c_float))) hfo_lib.act(self.obj, action_type, params.ctypes.data_as(POINTER(c_float)))
def say(self, message): def say(self, message):
""" Transmit a message """ """ Transmits a message """
hfo_lib.say(self.obj, message.encode('utf-8')) hfo_lib.say(self.obj, message.encode('utf-8'))
def hear(self): def hear(self):
...@@ -154,7 +154,7 @@ class HFOEnvironment(object): ...@@ -154,7 +154,7 @@ class HFOEnvironment(object):
return STATUS_STRINGS[status] return STATUS_STRINGS[status]
def getUnum(self): def getUnum(self):
""" Return the uniform number of the agent """ """ Returns the uniform number of the agent """
return hfo_lib.getUnum(self.obj) return hfo_lib.getUnum(self.obj)
def getNumTeammates(self): def getNumTeammates(self):
......
...@@ -247,6 +247,13 @@ void Agent::actionImpl() { ...@@ -247,6 +247,13 @@ void Agent::actionImpl() {
<< " parameters, given " << params.size() << std::endl; << " parameters, given " << params.size() << std::endl;
exit(1); exit(1);
} }
// For now let's not worry about turning the neck or setting the vision.
// However, do this now so doesn't override anything changed by the requested action.
// TODO for librcsc: setViewActionDefault, setNeckActionDefault that will not overwrite if already set.
this->setViewAction(new View_Tactical());
this->setNeckAction(new Neck_TurnToBallOrScan());
switch(requested_action) { switch(requested_action) {
case DASH: case DASH:
this->doDash(params[0], params[1]); this->doDash(params[0], params[1]);
...@@ -317,14 +324,15 @@ void Agent::actionImpl() { ...@@ -317,14 +324,15 @@ void Agent::actionImpl() {
case GO_TO_BALL: case GO_TO_BALL:
this->doGoToBall(); this->doGoToBall();
break; break;
case REORIENT:
this->doReorient();
break;
default: default:
std::cerr << "ERROR: Unsupported Action: " std::cerr << "ERROR: Unsupported Action: "
<< requested_action << std::endl; << requested_action << std::endl;
exit(1); exit(1);
} }
// For now let's not worry about turning the neck or setting the vision.
this->setViewAction(new View_Tactical());
this->setNeckAction(new Neck_TurnToBallOrScan());
} }
void void
...@@ -600,7 +608,7 @@ Agent::doPreprocess() ...@@ -600,7 +608,7 @@ Agent::doPreprocess()
__FILE__": (doPreProcess)" ); __FILE__": (doPreProcess)" );
// //
// freezed by tackle effect // frozen by tackle effect
// //
if ( wm.self().isFrozen() ) if ( wm.self().isFrozen() )
{ {
...@@ -698,6 +706,115 @@ Agent::doPreprocess() ...@@ -698,6 +706,115 @@ Agent::doPreprocess()
return false; return false;
} }
/*-------------------------------------------------------------------*/
/*!
Alternative high-level action to always doing "Move"; usable by either side, although
probably more useful for offense. Variant of doPreprocess (above), which is called by doDribble.
*/
bool
Agent::doReorient()
{
// check tackle expires
// check self position accuracy
// ball search
// check queued intention
const WorldModel & wm = this->world();
dlog.addText( Logger::TEAM,
__FILE__": (doPreProcessAsAction)" );
//
// frozen by tackle effect
//
if ( wm.self().isFrozen() )
{
dlog.addText( Logger::TEAM,
__FILE__": tackle wait. expires= %d",
wm.self().tackleExpires() );
return Bhv_Emergency().execute( this ); // includes change view
}
//
// BeforeKickOff or AfterGoal. jump to the initial position
//
if ( wm.gameMode().type() == GameMode::BeforeKickOff
|| wm.gameMode().type() == GameMode::AfterGoal_ )
{
dlog.addText( Logger::TEAM,
__FILE__": before_kick_off" );
Vector2D move_point = Strategy::i().getPosition( wm.self().unum() );
Bhv_CustomBeforeKickOff( move_point ).execute( this );
this->setViewAction( new View_Tactical() );
return true;
}
//
// self localization error
//
if ( ! ( wm.self().posValid() && wm.self().velValid() ) )
{
if (! wm.self().posValid() ) {
dlog.addText( Logger::TEAM,
__FILE__": invalid my pos" );
} else {
dlog.addText( Logger::TEAM,
__FILE__": invalid my vel" );
}
return Bhv_Emergency().execute( this ); // includes change view
}
//
// set default change view
//
this->setViewAction( new View_Tactical() );
//
// ball localization error
//
const int count_thr = ( wm.self().goalie()
? 10
: 5 );
if ( wm.ball().posCount() > count_thr
|| ( wm.gameMode().type() != GameMode::PlayOn
&& wm.ball().seenPosCount() > count_thr + 10 ) )
{
dlog.addText( Logger::TEAM,
__FILE__": search ball" );
return Bhv_NeckBodyToBall().execute( this );
}
//
// check pass message
//
if ( doHeardPassReceive() )
{
return true;
}
const BallObject& ball = wm.ball();
if (! ( ball.rposValid() && ball.velValid() )) {
dlog.addText( Logger::TEAM,
__FILE__": search ball" );
return Bhv_NeckBodyToBall().execute( this );
}
//
// check queued action
//
if ( this->doIntention() )
{
dlog.addText( Logger::TEAM,
__FILE__": do queued intention" );
return true;
}
return false;
}
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
/*! /*!
......
...@@ -80,6 +80,7 @@ protected: ...@@ -80,6 +80,7 @@ protected:
private: private:
bool doPreprocess(); bool doPreprocess();
bool doReorient();
bool doSmartKick(); bool doSmartKick();
bool doShoot(); bool doShoot();
bool doPass(); bool doPass();
......
...@@ -37,7 +37,8 @@ enum action_t ...@@ -37,7 +37,8 @@ enum action_t
REDUCE_ANGLE_TO_GOAL, // [High-Level] Reduce_Angle_To_Goal : Reduces the shooting angle REDUCE_ANGLE_TO_GOAL, // [High-Level] Reduce_Angle_To_Goal : Reduces the shooting angle
MARK_PLAYER, // [High-Level] Mark_Player(opponent_unum [0,11]) : Moves to the position in between the kicker and a given player MARK_PLAYER, // [High-Level] Mark_Player(opponent_unum [0,11]) : Moves to the position in between the kicker and a given player
DEFEND_GOAL, DEFEND_GOAL,
GO_TO_BALL GO_TO_BALL,
REORIENT // [High-Level] Handle lost position of self/ball, misc other situations; variant of doPreprocess called in DRIBBLE
}; };
// Status of a HFO game // Status of a HFO game
...@@ -117,6 +118,8 @@ inline int NumParams(const action_t action) { ...@@ -117,6 +118,8 @@ inline int NumParams(const action_t action) {
return 0; return 0;
case GO_TO_BALL: case GO_TO_BALL:
return 0; return 0;
case REORIENT:
return 0;
} }
std::cerr << "Unrecognized Action: " << action << std::endl; std::cerr << "Unrecognized Action: " << action << std::endl;
return -1; return -1;
...@@ -165,6 +168,8 @@ inline std::string ActionToString(action_t action) { ...@@ -165,6 +168,8 @@ inline std::string ActionToString(action_t action) {
return "Defend_Goal"; return "Defend_Goal";
case GO_TO_BALL: case GO_TO_BALL:
return "Go_To_Ball"; return "Go_To_Ball";
case REORIENT:
return "Reorient";
default: default:
return "Unknown"; return "Unknown";
} }
......
...@@ -67,13 +67,11 @@ def test_with_server(): ...@@ -67,13 +67,11 @@ def test_with_server():
state = try_step() state = try_step()
for x in range(0,20): for x in range(0,25):
if int(state[12]) == 1: # can kick the ball if int(state[12]) == 1: # can kick the ball
hfo_env.act(hfo.DRIBBLE) hfo_env.act(hfo.DRIBBLE)
elif (x % 2) != 0: elif (state[50] < 0) or (state[0] < 0) or (state[1] < 0) or (state[54] < 0):
hfo_env.act(hfo.MOVE) hfo_env.act(hfo.REORIENT)
elif int(state[50]) == 1: # can see the ball
hfo_env.act(hfo.GO_TO_BALL)
else: else:
hfo_env.act(hfo.MOVE) hfo_env.act(hfo.MOVE)
......
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