Commit ac50eb1d authored by drallensmith's avatar drallensmith

Merge in Reorient (add_preprocess_action) to help with testing without fullstate

parents 09d1c9f4 b9f7aa36
No preview for this file type
......@@ -594,6 +594,8 @@ faithfully report which action spaces were used.
\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
with the specified uniform number.}
\item{\textbf{Reorient}(): Deal with loss of self or ball localization information and with
some other situations; a modified version of the non-ball-dependent parts of Dribble.}
\end{itemize}
......@@ -611,29 +613,29 @@ below the table for the action abbreviations and notes.
\begin{center}
{\footnotesize
\begin{tabular}{r | 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 & Dr & C & RG & DG & G & MP \\
\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 & Dr & C & RG & DG & G & MP & Re \\
\hline \hline
Self position invalid & Y & Y & Y & Y & N & N & N? & N? & N & N? & N? & Y & ? & N & N & N & N \\
Self velocity invalid & N & Y? & Y? & Y & ? & N & N & N & N & ? & ? & Y & Y & N & N & N & N \\
Ball position invalid & Y & Y & Y? & N & N & Y & N & N & N & N & N & Y & N & N & N & N & N \\
Ball velocity invalid & Y & Y & Y & ? & ? & Y & Y & N? & ? & N & N? & Y? & Y? & Y & Y & Y & Y \\
Teammate loc invalid & Y & Y & Y & Y & Y & Y & Y & Y & N & 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 \\
Opponent loc invalid & Y & Y & Y & Y & Y & Y & Y? & Y & N & 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 \\
Self position invalid & Y & Y & Y & Y & N & N & N? & N? & N & N? & N? & Y & ? & N & N & N & N & Y \\
Self velocity invalid & N & Y? & Y? & Y & ? & N & N & N & N & ? & ? & Y & Y & N & N & N & N & Y \\
Ball position invalid & Y & Y & Y? & N & N & Y & N & N & N & N & N & Y & N & N & N & N & N & Y \\
Ball velocity invalid & Y & Y & Y & ? & ? & Y & Y & N? & ? & N & N? & Y? & Y? & Y & Y & Y & Y & Y \\
Teammate loc invalid & Y & Y & Y & Y & Y & Y & Y & Y & N & 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 & Y \\
Opponent loc invalid & Y & Y & Y & Y & Y & Y & Y? & Y & N & Y? & Y & Y? & 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 & Y \\
\hline
Ball kickable & Y & Y & Y & Y & Y & N & Y & N & * & Y & Y & Y & Y & ? & ? & N & Y \\
Ball not kickable & Y & Y & Y & N & N & Y & Y & Y & Y & N & N & N & Y & Y & Y & Y & Y \\
Ball kickable & Y & Y & Y & Y & Y & N & Y & N & * & Y & Y & Y & Y & ? & ? & N & Y & N \\
Ball not kickable & Y & Y & Y & N & N & Y & Y & Y & Y & N & N & N & Y & Y & Y & Y & Y & Y \\
\hline
Frozen & N & N & N & N & N & N & N? & N & N? & N & N & Y & N? & N & N & N & N \\
Colliding w/ball & Y & Y & ? & N & Y & N & Y & Y & Y & ? & Y & Y & ? & ? & ? & N & ? \\
Colliding w/player & Y & Y & ? & Y & Y & Y & Y & Y & Y & ? & N & Y & ? & ? & ? & Y & ? \\
Colliding w/post & Y & Y & N? & Y & Y & Y & N & Y & Y & ? & N & Y & ? & Y & Y & Y & Y \\
Frozen & N & N & N & N & N & N & N? & N & N? & N & N & Y & N? & N & N & N & N & Y \\
Colliding w/ball & Y & Y & ? & N & Y & N & Y & Y & Y & ? & Y & Y & ? & ? & ? & N & ? & N \\
Colliding w/player & Y & Y & ? & Y & Y & Y & Y & Y & Y & ? & N & Y & ? & ? & ? & Y & ? & N \\
Colliding w/post & Y & Y & N? & Y & Y & Y & N & Y & Y & ? & N & Y & ? & Y & Y & Y & Y & N \\
\hline
Offense & Y & Y & N & Y & Y & Y & Y & Y & Y & Y & Y & Y & N & N & N & Y & N \\
Defense, not goalie & Y & Y & Y & N & N & Y & N & Y & Y & N & N & N & N & Y & ? & Y & Y \\
Goalie (defense) & Y & Y & Y & N & N & Y & N & 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 \\
Goalie (defense) & Y & Y & Y & N & N & Y & N & Y & ? & N & N & N & Y & ? & ? & ? & N & Y \\
\end{tabular}
}
\end{center}
......@@ -641,7 +643,7 @@ Goalie (defense) & Y & Y & Y & N & N & Y & N & Y & ? & N & N &
\begin{itemize}[noitemsep]
\item{Da:\,Dash; Tu:\,Turn; Ta:\,Tackle; K:\,Kick}
\item{KT:\,Kick\_To; MT:\,Move\_To; DT:\,Dribble\_To; I:\,Intercept}
\item{M:\,Move; S:\,Shoot; P:\,Pass; Dr:\,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; Dr:\,Dribble; C:\,Catch; RG:\,Reduce\_Angle\_To\_Goal; DG:\,Defend\_Goal; G:\,Go\_To\_Ball; MP:\,Mark\_Player; Re: Reorient}
\end{itemize}
\section{Developing a New Agent}
......
......@@ -3,6 +3,7 @@
# 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 &
# Sleep is needed to make sure doesn't get connected too soon, as unum 1 (goalie)
sleep 15
./example/hand_coded_defense_agent.py &> agent1.txt &
......
......@@ -104,7 +104,7 @@ def do_defense_action(state_vec, hfo_env,
# if get high_level working for invalid
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
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,
if not ball_sorted_list: # unknown opponent positions/unums
print("No known opponent locations (btg {0!r}; bng {1!r}; ".format(ball_toward_goal,
ball_nearer_goal) +
"ball xy {0:n}, {1:n}; ball old xy {2:n}, {3:n})".format(ball_pos_x,
ball_pos_y,
old_ball_pos_x,
old_ball_pos_y))
if ball_toward_goal:
"ball xy {0:n}, {1:n}; ball old xy {2:n}, {3:n}; kickable {4:n})".format(ball_pos_x,
ball_pos_y,
old_ball_pos_x,
old_ball_pos_y,
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:
hfo_env.act(add_num_times(hfo.REDUCE_ANGLE_TO_GOAL,num_times_overall))
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
from __future__ import print_function
# encoding: utf-8
# Before running this program, first Start HFO server:
......@@ -23,9 +24,9 @@ def main():
parser.add_argument('--seed', type=int, default=None,
help="Python randomization seed; uses python default if 0 or not given")
parser.add_argument('--record', action='store_true',
help="Doing HFO --record")
help="If doing HFO --record")
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()
if args.seed:
random.seed(args.seed)
......@@ -42,6 +43,10 @@ def main():
hfo_env.connectToServer(hfo.HIGH_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():
status = hfo.IN_GAME
while status == hfo.IN_GAME:
......@@ -59,8 +64,9 @@ def main():
status = hfo_env.step()
# Check the outcome of the episode
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
if status == hfo.SERVER_DOWN:
......
#!/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
......@@ -28,8 +28,8 @@ An enum of the possible HFO actions, including:
NOOP(): Do Nothing
QUIT(): Quit the game
"""
NUM_HFO_ACTIONS = 19
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))
NUM_HFO_ACTIONS = 20
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,REORIENT = list(range(NUM_HFO_ACTIONS))
ACTION_STRINGS = {DASH: "Dash",
TURN: "Turn",
TACKLE: "Tackle",
......@@ -48,7 +48,8 @@ ACTION_STRINGS = {DASH: "Dash",
REDUCE_ANGLE_TO_GOAL: "Reduce_Angle_To_Goal",
MARK_PLAYER: "Mark_Player",
DEFEND_GOAL: "Defend_Goal",
GO_TO_BALL: "Go_To_Ball"}
GO_TO_BALL: "Go_To_Ball",
REORIENT: "Reorient"}
"""
Possible game statuses:
......@@ -132,7 +133,7 @@ class HFOEnvironment(object):
play_goalie=False,
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
feature_set: High or low level state features
......@@ -143,7 +144,14 @@ class HFOEnvironment(object):
play_goalie: is this player the goalie
record_dir: record agent's states/actions/rewards to this directory
"""
hfo_lib.connectToServer(self.obj, feature_set, config_dir.encode('utf-8'), server_port,server_addr.encode('utf-8'), team_name.encode('utf-8'), play_goalie, record_dir.encode('utf-8'))
hfo_lib.connectToServer(self.obj,
feature_set,
config_dir.encode('utf-8'),
server_port,server_addr.encode('utf-8'),
team_name.encode('utf-8'),
play_goalie,
record_dir.encode('utf-8'))
def getStateSize(self):
""" Returns the number of state features """
return hfo_lib.getStateSize(self.obj)
......@@ -164,7 +172,7 @@ class HFOEnvironment(object):
hfo_lib.act(self.obj, action_type, params.ctypes.data_as(POINTER(c_float)))
def say(self, message):
""" Transmit a message """
""" Transmits a message """
hfo_lib.say(self.obj, message.encode('utf-8'))
def hear(self):
......@@ -188,7 +196,7 @@ class HFOEnvironment(object):
return STATUS_STRINGS[status]
def getUnum(self):
""" Return the uniform number of the agent """
""" Returns the uniform number of the agent """
return hfo_lib.getUnum(self.obj)
def getNumTeammates(self):
......
......@@ -358,6 +358,9 @@ void Agent::actionImpl() {
case GO_TO_BALL:
addLastActionStatus(GO_TO_BALL, this->doGoToBall());
break;
case REORIENT:
addLastActionStatus(REORIENT, this->doReorient());
break;
default:
std::cerr << "ERROR: Unsupported Action: "
<< requested_action << std::endl;
......@@ -737,6 +740,131 @@ Agent::doPreprocess()
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.
*/
action_status_t
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() );
// face neck to ball
this->setViewAction( new View_Tactical() );
this->setNeckAction( new Neck_TurnToBallOrScan() );
return ACTION_STATUS_MAYBE;
}
//
// 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 ACTION_STATUS_MAYBE;
}
//
// 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" );
}
if (Bhv_Emergency().execute( this )) { // includes change view
return ACTION_STATUS_MAYBE;
} else {
return ACTION_STATUS_UNKNOWN;
}
}
//
// 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" );
if (Bhv_NeckBodyToBall().execute( this )) {
return ACTION_STATUS_MAYBE;
} else {
return ACTION_STATUS_UNKNOWN;
}
}
//
// check queued action
//
if ( this->doIntention() )
{
dlog.addText( Logger::TEAM,
__FILE__": do queued intention" );
return ACTION_STATUS_MAYBE;
}
//
// check pass message
//
if ( doHeardPassReceive() )
{
return ACTION_STATUS_MAYBE;
}
const BallObject& ball = wm.ball();
if (! ( ball.rposValid() && ball.velValid() )) {
dlog.addText( Logger::TEAM,
__FILE__": search ball" );
if (Bhv_NeckBodyToBall().execute( this )) {
return ACTION_STATUS_MAYBE;
} else {
return ACTION_STATUS_UNKNOWN;
}
}
return ACTION_STATUS_BAD;
}
/*-------------------------------------------------------------------*/
/*!
......
......@@ -85,6 +85,7 @@ protected:
private:
bool doPreprocess();
hfo::action_status_t doReorient();
hfo::action_status_t doSmartKick();
hfo::action_status_t doShoot();
bool doPass();
......
......@@ -38,7 +38,8 @@ enum action_t
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
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 an HFO game
......@@ -136,6 +137,8 @@ inline int NumParams(const action_t action) {
return 0;
case GO_TO_BALL:
return 0;
case REORIENT:
return 0;
}
std::cerr << "Unrecognized Action: " << action << std::endl;
return -1;
......@@ -184,6 +187,8 @@ inline std::string ActionToString(action_t action) {
return "Defend_Goal";
case GO_TO_BALL:
return "Go_To_Ball";
case REORIENT:
return "Reorient";
default:
return "Unknown";
}
......
......@@ -67,13 +67,11 @@ def test_with_server():
state = try_step()
for x in range(0,20):
for x in range(0,25):
if int(state[12]) == 1: # can kick the ball
hfo_env.act(hfo.DRIBBLE)
elif (x % 2) != 0:
hfo_env.act(hfo.MOVE)
elif int(state[50]) == 1: # can see the ball
hfo_env.act(hfo.GO_TO_BALL)
elif (state[50] < 0) or (state[0] < 0) or (state[1] < 0) or (state[54] < 0):
hfo_env.act(hfo.REORIENT)
else:
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