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
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)
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)
......
#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):
while status == HFO_Status.IN_GAME:
state = hfo_env.getState()
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:
status = hfo_env.act(HFO_Actions.MOVE)
hfo_env.act(HFO_Actions.MOVE)
status = hfo_env.step()
except:
pass
finally:
......
......@@ -21,9 +21,10 @@ int main() {
while (status == IN_GAME) {
// Get the vector of state features for the current state
const std::vector<float>& feature_vec = hfo.getState();
// Create a dash action
// Perform the dash and recieve the current game status
status = hfo.act(DASH, 20.0);
// Perform the dash
hfo.act(DASH, 20.0);
// Advance the environment and recieve current game status
status = hfo.step();
}
// Check what the outcome of the episode was
cout << "Episode " << episode << " ended with status: ";
......
......@@ -31,8 +31,10 @@ int main(int argc, char** argv) {
while (status == IN_GAME) {
// Get the vector of state features for the current state
const vector<float>& feature_vec = hfo.getState();
// Perform the action and recieve the current game status
status = hfo.act(get_random_high_lv_action());
// Perform the action
hfo.act(get_random_high_lv_action());
// Advance the environment and get the game status
status = hfo.step();
}
}
hfo.act(QUIT);
......
......@@ -56,7 +56,9 @@ int main(int argc, char** argv) {
// Get the vector of state features for the current state
const vector<float>& feature_vec = hfo.getState();
// 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) {
// Dribble in a circle around center field
float target_x = sin((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;
}
}
......
......@@ -35,14 +35,16 @@ int main(int argc, char** argv) {
// Valid kick speed varies in the range [0, 3]
if (dist_to_target < .1) {
// Max power kick to goal
status = hfo.act(KICK_TO, 1., 0., 3.0);
hfo.act(KICK_TO, 1., 0., 3.0);
} else {
// 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 {
status = hfo.act(INTERCEPT);
hfo.act(INTERCEPT);
}
// Advance the environment and get the game status
status = hfo.step();
}
}
hfo.act(QUIT);
......
......@@ -33,8 +33,10 @@ int main(int argc, char** argv) {
while (status == IN_GAME) {
// Get the vector of state features for the current state
const vector<float>& feature_vec = hfo.getState();
// Perform the action and recieve the current game status
status = hfo.act(MOVE_TO, target_x, target_y);
// Perform the action
hfo.act(MOVE_TO, target_x, target_y);
// Advance the environment and get the game status
status = hfo.step();
}
}
hfo.act(QUIT);
......
......@@ -41,9 +41,12 @@ class HFOEnvironment(object):
'''
def __init__(self):
self.socket = None # Socket connection to server
self.numFeatures = None # Given by the server in handshake
self.features = None # The state features
self.socket = None # Socket connection to server
self.numFeatures = None # Given by the server in handshake
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):
''' Returns the number of required parameters for each action type. '''
......@@ -125,7 +128,24 @@ class HFOEnvironment(object):
n_params = self.NumParams(action_type)
assert n_params == len(args) - 1, 'Incorrect number of params to act: '\
'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
data = self.socket.recv(struct.calcsize("i"))
status = struct.unpack("i", data)[0]
......@@ -136,6 +156,8 @@ class HFOEnvironment(object):
self.cleanup()
exit(1)
self.features = struct.unpack('f'*self.numFeatures, state_data)
self.hear_msg = ''
# TODO: [Sanmit] Receive self.hear_msg
return status
def cleanup(self):
......
......@@ -247,31 +247,50 @@ const std::vector<float>& HFOEnvironment::getState() {
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;
// 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");
close(sockfd);
exit(1);
}
// Send the arguments
int n_args = NumParams(action);
int n_args = NumParams(requested_action);
if (n_args > 0) {
float params[n_args];
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) {
if (send(sockfd, action_params.data(), sizeof(float) * n_args, 0) < 0) {
perror("[Agent Client] ERROR sending from socket");
close(sockfd);
exit(1);
}
}
// TODO: [Sanmit] Send say_msg
say_msg.clear();
// Get the game status
if (recv(sockfd, &game_status, sizeof(status_t), 0) < 0) {
perror("[Agent Client] ERROR recieving from socket");
......@@ -284,5 +303,8 @@ status_t HFOEnvironment::act(action_t action, ...) {
close(sockfd);
exit(1);
}
hear_msg.clear();
// TODO: [Sanmit] Receive comm_msg
return game_status;
}
......@@ -85,13 +85,24 @@ class HFOEnvironment {
// Get the current state of the domain. Returns a reference to feature_vec.
const std::vector<float>& getState();
// Take an action and recieve the resulting game status
status_t act(action_t action, ...);
// Specify action type to take followed by parameters for that 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:
int numFeatures; // The number of features in this domain
int sockfd; // Socket file desriptor for connection to agent server
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
// passed. Also sets the number of features to expect.
......
......@@ -424,6 +424,7 @@ void Agent::actionImpl() {
perror("[Agent Server] ERROR sending state features from socket");
exit(1);
}
// TODO: [Sanmit] Send the communication heard by the agent
// Get the action type
action_t action;
......@@ -442,6 +443,9 @@ void Agent::actionImpl() {
exit(1);
}
}
// TODO: [Sanmit] Receive the outgoing communication
// TODO: [Sanmit] "Say" in the actual game
if (action == SHOOT) {
const ShootGenerator::Container & cont =
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