diff --git a/example/high_level_random_agent.cpp b/example/high_level_random_agent.cpp index 3af6bb10b289595f209cb5688dcfd1781fdd2f3f..346afa97cb65284492c03c0a815ab747c71e68d4 100644 --- a/example/high_level_random_agent.cpp +++ b/example/high_level_random_agent.cpp @@ -17,8 +17,8 @@ string server_addr = "localhost"; string team_name = "base_left"; bool goalie = false; -// We omit PASS & CATCH actions here -action_t HIGH_LEVEL_ACTIONS[3] = { MOVE, SHOOT, DRIBBLE }; +// We omit PASS & CATCH & MOVE actions here +action_t HIGH_LEVEL_ACTIONS[2] = { SHOOT, DRIBBLE }; int main(int argc, char** argv) { // Create the HFO environment @@ -34,7 +34,11 @@ 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 - hfo.act(HIGH_LEVEL_ACTIONS[rand() % 3]); + if (feature_vec[5] == 1) { // Feature 5 is 1 when the player can kick the ball + hfo.act(HIGH_LEVEL_ACTIONS[rand() % 2]); + } else { + hfo.act(MOVE); + } // Advance the environment and get the game status status = hfo.step(); } diff --git a/example/random_2v1.sh b/example/random_2v1.sh index f1cea3a116a2a46a53d03a27a2fa21aecb71cada..9457c06f0a0554d7d2ec710971134e1088a9f311 100755 --- a/example/random_2v1.sh +++ b/example/random_2v1.sh @@ -1,10 +1,10 @@ #!/bin/bash -./bin/HFO --offense-agents=2 --defense-npcs=1 --trials 100 --headless & +./bin/HFO --offense-agents=2 --defense-npcs=1 --trials 20 --headless & sleep 5 -./example/high_level_random_agent 6000 & +./example/high_level_random_agent 6000 &> agent1.txt & sleep 5 -./example/high_level_random_agent 6000 & +./example/high_level_random_agent 6000 &> agent2.txt & # The magic line # $$ holds the PID for this script diff --git a/src/HFO.cpp b/src/HFO.cpp index 66a9a2d275198e15f62a964ef277154f349ce191..326bf7329bf2717adf33d998e9baf587f28bc042 100644 --- a/src/HFO.cpp +++ b/src/HFO.cpp @@ -60,11 +60,21 @@ void HFOEnvironment::connectToServer(feature_set_t feature_set, act(NOOP); while (agent->getState().empty()) { if (!client->isServerAlive()) { - std::cerr << "Server Down!" << std::endl; + std::cerr << "[ConnectToServer] Server Down!" << std::endl; exit(1); } - client->runStep(agent); + ready_for_action = client->runStep(agent); + if (ready_for_action) { + agent->action(); + } } + // Step until it is time to act + do { + ready_for_action = client->runStep(agent); + } while (!ready_for_action); + agent->ProcessTrainerMessages(); + agent->ProcessTeammateMessages(); + agent->UpdateFeatures(); current_cycle = agent->currentTime().cycle(); } @@ -111,12 +121,24 @@ Player HFOEnvironment::playerOnBall() { status_t HFOEnvironment::step() { assert(agent->currentTime().cycle() == current_cycle); - while (agent->statusUpdateTime() <= current_cycle) { - if (!client->isServerAlive()) { + assert(ready_for_action); + + // Execute the action + agent->action(); + + // Advance the environment by one step + do { + ready_for_action = client->runStep(agent); + if (!client->isServerAlive() || agent->getGameStatus() == SERVER_DOWN) { return SERVER_DOWN; } - client->runStep(agent); - } + agent->ProcessTrainerMessages(); + } while (agent->statusUpdateTime() <= current_cycle || !ready_for_action); + + // Update the state features + agent->ProcessTeammateMessages(); + agent->UpdateFeatures(); + assert(agent->currentTime().cycle() == (current_cycle + 1)); current_cycle = agent->currentTime().cycle(); return agent->getGameStatus(); diff --git a/src/HFO.hpp b/src/HFO.hpp index 41acfdeae0f474e1a76908894ffd4cda8006e6c3..e5b536b35a7c5ce31aacdbe5248318e2f1f486d9 100644 --- a/src/HFO.hpp +++ b/src/HFO.hpp @@ -60,6 +60,7 @@ class HFOEnvironment { rcsc::BasicClient* client; Agent* agent; long current_cycle; + bool ready_for_action; }; } // namespace hfo diff --git a/src/agent.cpp b/src/agent.cpp index 7e09650752941d31cc08c5ad02471d9f23e3c9a6..ccc94bcf5e90ac33b5fbed380c10f4206b1dbcdf 100644 --- a/src/agent.cpp +++ b/src/agent.cpp @@ -311,14 +311,9 @@ void Agent::actionImpl() { this->setNeckAction(new Neck_TurnToBallOrScan()); } -/*-------------------------------------------------------------------*/ -/*! - - */ void -Agent::handleActionStart() +Agent::ProcessTrainerMessages() { - // Process new trainer messages if (audioSensor().trainerMessageTime().cycle() > lastTrainerMessageTime) { const std::string& message = audioSensor().trainerMessage(); if (feature_extractor == NULL) { @@ -339,8 +334,11 @@ Agent::handleActionStart() hfo::ParsePlayerOnBall(message, player_on_ball); lastTrainerMessageTime = audioSensor().trainerMessageTime().cycle(); } +} - // Process new teammate message +void +Agent::ProcessTeammateMessages() +{ hear_msg.clear(); if (audioSensor().teammateMessageTime().cycle() > lastTeammateMessageTime) { const std::list<HearMessage> teammateMessages = audioSensor().teammateMessages(); @@ -353,11 +351,22 @@ Agent::handleActionStart() } lastTeammateMessageTime = audioSensor().teammateMessageTime().cycle(); } +} - // Update state features +void +Agent::UpdateFeatures() +{ if (feature_extractor != NULL) { state = feature_extractor->ExtractFeatures(this->world()); } +} + +void +Agent::handleActionStart() +{ + ProcessTrainerMessages(); + ProcessTeammateMessages(); + UpdateFeatures(); // Optionally write to logfile #ifdef ELOG diff --git a/src/agent.h b/src/agent.h index a7f7c0a291ba01a49ef2a4500274c79ead97cbbe..49e31f95f7ae386dd034eee6378e243f20028454 100644 --- a/src/agent.h +++ b/src/agent.h @@ -24,6 +24,13 @@ public: inline long statusUpdateTime() { return lastStatusUpdateTime; } + // Process incoming trainer messages. Used to update the game status. + void ProcessTrainerMessages(); + // Process incoming teammate messages. + void ProcessTeammateMessages(); + // Update the state features from the world model. + void UpdateFeatures(); + protected: // You can override this method. But you must call // PlayerAgent::initImpl() in this method. diff --git a/src/common.hpp b/src/common.hpp index 7df2cca049921330510438a6430b7ff80d3286bd..2f5dc6389794a31ea31586cc45dc7eaf958a3947 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -263,6 +263,8 @@ inline bool ParseGameStatus(const std::string& message, status_t& status) { status = OUT_OF_TIME; } else if (message.find("IN_GAME") != std::string::npos){ status = IN_GAME; + } else if (message.find("HFO_FINISHED") != std::string::npos){ + status = SERVER_DOWN; } else { return false; } diff --git a/src/feature_extractor.cpp b/src/feature_extractor.cpp index c3040f5c53c2d0ea95c1cc16190bfd5b0f009b38..237750684c770c95ee45a5913d9195a32eb6fbdb 100644 --- a/src/feature_extractor.cpp +++ b/src/feature_extractor.cpp @@ -146,7 +146,7 @@ bool FeatureExtractor::valid(const rcsc::PlayerObject& player) { pos.x < -ALLOWED_PITCH_FRAC * rcsc::ServerParam::i().pitchHalfLength()) { return false; } - return player.unum() > 0 && pos.isValid(); + return pos.isValid(); } float FeatureExtractor::angleToPoint(const rcsc::Vector2D &self,