Commit 868d3c4b authored by Matthew Hausknecht's avatar Matthew Hausknecht

Refactored interfaces in preparation for communication.

parent 0c0d3ed6
...@@ -122,6 +122,10 @@ add_executable(mid_level_dribble_agent ${CMAKE_CURRENT_SOURCE_DIR}/example/mid_l ...@@ -122,6 +122,10 @@ add_executable(mid_level_dribble_agent ${CMAKE_CURRENT_SOURCE_DIR}/example/mid_l
set_target_properties(mid_level_dribble_agent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/example) set_target_properties(mid_level_dribble_agent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/example)
target_link_libraries(mid_level_dribble_agent hfo-lib) target_link_libraries(mid_level_dribble_agent hfo-lib)
add_executable(communication_agent ${CMAKE_CURRENT_SOURCE_DIR}/example/communication_agent.cpp)
set_target_properties(communication_agent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/example)
target_link_libraries(communication_agent hfo-lib)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/example DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/ USE_SOURCE_PERMISSIONS) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/example DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/ USE_SOURCE_PERMISSIONS)
......
#include <iostream>
#include <vector>
#include <HFO.hpp>
#include <cstdlib>
using namespace std;
using namespace hfo;
// Before running this program, first Start HFO server:
// $./bin/HFO --offense-agents 1
int main(int argc, char** argv) {
int port = 6000;
if (argc > 1) {
port = atoi(argv[1]);
}
// Create the HFO environment
HFOEnvironment hfo;
// Connect to the agent's server on port 6000 and request low-level
// feature set. See manual for more information on feature sets.
hfo.connectToAgentServer(port, HIGH_LEVEL_FEATURE_SET);
// Play 5 episodes
for (int episode=0; ; episode++) {
status_t status = IN_GAME;
while (status == IN_GAME) {
// Get the vector of state features for the current state
const vector<float>& feature_vec = hfo.getState();
// Get any incoming communication
std::string msg = hfo.hear();
// TODO: [Sanmit] Do something with incoming communication
// Perform the action
hfo.act(DASH, 0, 0);
// TODO: [Sanmit] Do something with outgoing communication
hfo.say("Message");
// Advance the environment and get the game status
status = hfo.step();
}
}
hfo.act(QUIT);
};
...@@ -25,9 +25,10 @@ def play_hfo(num): ...@@ -25,9 +25,10 @@ def play_hfo(num):
while status == HFO_Status.IN_GAME: while status == HFO_Status.IN_GAME:
state = hfo_env.getState() state = hfo_env.getState()
if state[5] == 1: #state[5] is 1 when player has the ball if state[5] == 1: #state[5] is 1 when player has the ball
status = hfo_env.act(get_random_action()) hfo_env.act(get_random_action())
else: else:
status = hfo_env.act(HFO_Actions.MOVE) hfo_env.act(HFO_Actions.MOVE)
status = hfo_env.step()
except: except:
pass pass
finally: finally:
......
...@@ -21,9 +21,10 @@ int main() { ...@@ -21,9 +21,10 @@ int main() {
while (status == IN_GAME) { while (status == IN_GAME) {
// Get the vector of state features for the current state // Get the vector of state features for the current state
const std::vector<float>& feature_vec = hfo.getState(); const std::vector<float>& feature_vec = hfo.getState();
// Create a dash action // Perform the dash
// Perform the dash and recieve the current game status hfo.act(DASH, 20.0);
status = hfo.act(DASH, 20.0); // Advance the environment and recieve current game status
status = hfo.step();
} }
// Check what the outcome of the episode was // Check what the outcome of the episode was
cout << "Episode " << episode << " ended with status: "; cout << "Episode " << episode << " ended with status: ";
......
...@@ -31,8 +31,10 @@ int main(int argc, char** argv) { ...@@ -31,8 +31,10 @@ int main(int argc, char** argv) {
while (status == IN_GAME) { while (status == IN_GAME) {
// Get the vector of state features for the current state // Get the vector of state features for the current state
const vector<float>& feature_vec = hfo.getState(); const vector<float>& feature_vec = hfo.getState();
// Perform the action and recieve the current game status // Perform the action
status = hfo.act(get_random_high_lv_action()); hfo.act(get_random_high_lv_action());
// Advance the environment and get the game status
status = hfo.step();
} }
} }
hfo.act(QUIT); hfo.act(QUIT);
......
...@@ -56,7 +56,9 @@ int main(int argc, char** argv) { ...@@ -56,7 +56,9 @@ int main(int argc, char** argv) {
// Get the vector of state features for the current state // Get the vector of state features for the current state
const vector<float>& feature_vec = hfo.getState(); const vector<float>& feature_vec = hfo.getState();
// Perform the action and recieve the current game status // Perform the action and recieve the current game status
status = hfo.act(get_random_low_lv_action(), arg1, arg2); hfo.act(get_random_low_lv_action(), arg1, arg2);
status = hfo.step();
} }
} }
}; };
...@@ -32,7 +32,9 @@ int main(int argc, char** argv) { ...@@ -32,7 +32,9 @@ int main(int argc, char** argv) {
// Dribble in a circle around center field // Dribble in a circle around center field
float target_x = sin((step % 360) * PI/180); float target_x = sin((step % 360) * PI/180);
float target_y = cos((step % 360) * PI/180); float target_y = cos((step % 360) * PI/180);
status = hfo.act(DRIBBLE_TO, target_x, target_y); hfo.act(DRIBBLE_TO, target_x, target_y);
// Advance the environment and get the game status
status = hfo.step();
step += 2; step += 2;
} }
} }
......
...@@ -35,14 +35,16 @@ int main(int argc, char** argv) { ...@@ -35,14 +35,16 @@ int main(int argc, char** argv) {
// Valid kick speed varies in the range [0, 3] // Valid kick speed varies in the range [0, 3]
if (dist_to_target < .1) { if (dist_to_target < .1) {
// Max power kick to goal // Max power kick to goal
status = hfo.act(KICK_TO, 1., 0., 3.0); hfo.act(KICK_TO, 1., 0., 3.0);
} else { } else {
// Kick to center of hfo field // Kick to center of hfo field
status = hfo.act(KICK_TO, 0., 0., dist_to_target); hfo.act(KICK_TO, 0., 0., dist_to_target);
} }
} else { } else {
status = hfo.act(INTERCEPT); hfo.act(INTERCEPT);
} }
// Advance the environment and get the game status
status = hfo.step();
} }
} }
hfo.act(QUIT); hfo.act(QUIT);
......
...@@ -33,8 +33,10 @@ int main(int argc, char** argv) { ...@@ -33,8 +33,10 @@ int main(int argc, char** argv) {
while (status == IN_GAME) { while (status == IN_GAME) {
// Get the vector of state features for the current state // Get the vector of state features for the current state
const vector<float>& feature_vec = hfo.getState(); const vector<float>& feature_vec = hfo.getState();
// Perform the action and recieve the current game status // Perform the action
status = hfo.act(MOVE_TO, target_x, target_y); hfo.act(MOVE_TO, target_x, target_y);
// Advance the environment and get the game status
status = hfo.step();
} }
} }
hfo.act(QUIT); hfo.act(QUIT);
......
...@@ -44,6 +44,9 @@ class HFOEnvironment(object): ...@@ -44,6 +44,9 @@ class HFOEnvironment(object):
self.socket = None # Socket connection to server self.socket = None # Socket connection to server
self.numFeatures = None # Given by the server in handshake self.numFeatures = None # Given by the server in handshake
self.features = None # The state features self.features = None # The state features
self.requested_action = None # Action to execute and parameters
self.say_msg = None # Outgoing message to say
self.hear_msg = None # Incoming heard message
def NumParams(self, action_type): def NumParams(self, action_type):
''' Returns the number of required parameters for each action type. ''' ''' Returns the number of required parameters for each action type. '''
...@@ -125,7 +128,24 @@ class HFOEnvironment(object): ...@@ -125,7 +128,24 @@ class HFOEnvironment(object):
n_params = self.NumParams(action_type) n_params = self.NumParams(action_type)
assert n_params == len(args) - 1, 'Incorrect number of params to act: '\ assert n_params == len(args) - 1, 'Incorrect number of params to act: '\
'Required %d provided %d'%(n_params, len(args)-1) 'Required %d provided %d'%(n_params, len(args)-1)
self.socket.send(struct.pack('i'+'f'*n_params, *args)) self.requested_action = args
def say(self, message):
''' Send a communication message to other agents. '''
self.say_msg = message
def hear(self):
''' Receive incoming communications from other players. '''
return self.hear_msg
def step(self):
''' Indicates the agent is done and the environment should
progress. Returns the game status after the step'''
# Send action and parameters
self.socket.send(struct.pack('i'+'f'*(len(self.requested_action)-1),
*self.requested_action))
# TODO: [Sanmit] Send self.say_msg
self.say_msg = ''
# Get the current game status # Get the current game status
data = self.socket.recv(struct.calcsize("i")) data = self.socket.recv(struct.calcsize("i"))
status = struct.unpack("i", data)[0] status = struct.unpack("i", data)[0]
...@@ -136,6 +156,8 @@ class HFOEnvironment(object): ...@@ -136,6 +156,8 @@ class HFOEnvironment(object):
self.cleanup() self.cleanup()
exit(1) exit(1)
self.features = struct.unpack('f'*self.numFeatures, state_data) self.features = struct.unpack('f'*self.numFeatures, state_data)
self.hear_msg = ''
# TODO: [Sanmit] Receive self.hear_msg
return status return status
def cleanup(self): def cleanup(self):
......
...@@ -247,31 +247,50 @@ const std::vector<float>& HFOEnvironment::getState() { ...@@ -247,31 +247,50 @@ const std::vector<float>& HFOEnvironment::getState() {
return feature_vec; return feature_vec;
} }
status_t HFOEnvironment::act(action_t action, ...) { void HFOEnvironment::act(action_t action, ...) {
requested_action = action;
int n_args = NumParams(action);
if (n_args > action_params.size()) {
action_params.resize(n_args);
}
va_list vl;
va_start(vl, action);
for (int i = 0; i < n_args; ++i) {
action_params[i] = va_arg(vl, double);
}
va_end(vl);
}
void HFOEnvironment::say(const std::string& message) {
// TODO: [Sanmit] Bounds check message?
say_msg = message;
}
std::string HFOEnvironment::hear() {
return hear_msg;
}
status_t HFOEnvironment::step() {
status_t game_status; status_t game_status;
// Send the action_type // Send the action_type
if (send(sockfd, &action, sizeof(action_t), 0) < 0) { if (send(sockfd, &requested_action, sizeof(action_t), 0) < 0) {
perror("[Agent Client] ERROR sending from socket"); perror("[Agent Client] ERROR sending from socket");
close(sockfd); close(sockfd);
exit(1); exit(1);
} }
// Send the arguments // Send the arguments
int n_args = NumParams(action); int n_args = NumParams(requested_action);
if (n_args > 0) { if (n_args > 0) {
float params[n_args]; if (send(sockfd, action_params.data(), sizeof(float) * n_args, 0) < 0) {
va_list vl;
va_start(vl, action);
for (int i = 0; i < n_args; ++i) {
params[i] = va_arg(vl, double);
}
va_end(vl);
// Send the arguments
if (send(sockfd, &params, sizeof(float) * n_args, 0) < 0) {
perror("[Agent Client] ERROR sending from socket"); perror("[Agent Client] ERROR sending from socket");
close(sockfd); close(sockfd);
exit(1); exit(1);
} }
} }
// TODO: [Sanmit] Send say_msg
say_msg.clear();
// Get the game status // Get the game status
if (recv(sockfd, &game_status, sizeof(status_t), 0) < 0) { if (recv(sockfd, &game_status, sizeof(status_t), 0) < 0) {
perror("[Agent Client] ERROR recieving from socket"); perror("[Agent Client] ERROR recieving from socket");
...@@ -284,5 +303,8 @@ status_t HFOEnvironment::act(action_t action, ...) { ...@@ -284,5 +303,8 @@ status_t HFOEnvironment::act(action_t action, ...) {
close(sockfd); close(sockfd);
exit(1); exit(1);
} }
hear_msg.clear();
// TODO: [Sanmit] Receive comm_msg
return game_status; return game_status;
} }
...@@ -85,13 +85,24 @@ class HFOEnvironment { ...@@ -85,13 +85,24 @@ class HFOEnvironment {
// Get the current state of the domain. Returns a reference to feature_vec. // Get the current state of the domain. Returns a reference to feature_vec.
const std::vector<float>& getState(); const std::vector<float>& getState();
// Take an action and recieve the resulting game status // Specify action type to take followed by parameters for that action
status_t act(action_t action, ...); virtual void act(action_t action, ...);
// Send/receive communication from other agents
virtual void say(const std::string& message);
virtual std::string hear();
// Indicates the agent is done and the environment should
// progress. Returns the game status after the step
virtual status_t step();
protected: protected:
int numFeatures; // The number of features in this domain int numFeatures; // The number of features in this domain
int sockfd; // Socket file desriptor for connection to agent server int sockfd; // Socket file desriptor for connection to agent server
std::vector<float> feature_vec; // Holds the features std::vector<float> feature_vec; // Holds the features
action_t requested_action; // Action requested
std::vector<float> action_params; // Action parameters
std::string say_msg, hear_msg; // Messages to hear/say
// Handshake with the agent server to ensure data is being correctly // Handshake with the agent server to ensure data is being correctly
// passed. Also sets the number of features to expect. // passed. Also sets the number of features to expect.
......
...@@ -424,6 +424,7 @@ void Agent::actionImpl() { ...@@ -424,6 +424,7 @@ void Agent::actionImpl() {
perror("[Agent Server] ERROR sending state features from socket"); perror("[Agent Server] ERROR sending state features from socket");
exit(1); exit(1);
} }
// TODO: [Sanmit] Send the communication heard by the agent
// Get the action type // Get the action type
action_t action; action_t action;
...@@ -442,6 +443,9 @@ void Agent::actionImpl() { ...@@ -442,6 +443,9 @@ void Agent::actionImpl() {
exit(1); exit(1);
} }
} }
// TODO: [Sanmit] Receive the outgoing communication
// TODO: [Sanmit] "Say" in the actual game
if (action == SHOOT) { if (action == SHOOT) {
const ShootGenerator::Container & cont = const ShootGenerator::Container & cont =
ShootGenerator::instance().courses(this->world(), false); ShootGenerator::instance().courses(this->world(), false);
......
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