Support reconnecting to agents

Agents do not die immediately on disconnect anymore. Instead, agent_id
is sent at birth and can be sent during negotiation to attach to a
disconnected agent.
This commit is contained in:
Petr Baudis 2011-12-08 02:01:56 +01:00
parent 417a5235a0
commit 8ae6051e97
4 changed files with 52 additions and 7 deletions

19
README
View file

@ -20,6 +20,9 @@ CRLF ("\r\n"), not just LF ("\n")!
The following inputs (in no particular order) are supported: The following inputs (in no particular order) are supported:
agent_id <id>
unique id of agent; may be sent only once at the beginning
(you can use it to reconnect to the same agent later)
tick <ticknum> tick <ticknum>
BUMP BUMP
if received, the agent's move failed if received, the agent's move failed
@ -62,9 +65,10 @@ The following outputs are supported:
energy required is proportional to phintensity energy required is proportional to phintensity
After connecting, the client specifies its desired attributes, When new agent connects, the client first enters the "negotiation"
in the same format as in normal output (line-based, terminated phase, specifying its desired attributes, in the same format as in
by empty line), but with these commands instead: normal output (line-based, terminated by empty line), but with
these commands instead:
move <rate> move <rate>
<rate> between 0 and 1, describing probability <rate> between 0 and 1, describing probability
@ -76,3 +80,12 @@ by empty line), but with these commands instead:
In general, higher rate means higher energy maintenance of the In general, higher rate means higher energy maintenance of the
appropriate actuators. appropriate actuators.
Alternately, the client may send a single command in the negotiation
phase:
agent_id <id>
If the id corresponds to a disconnected agent, the connection
is immediately attached to that agent. Combining this with other
negotiation commands is undefined.

View file

@ -126,7 +126,6 @@ agent::on_action_takes(void)
return; return;
if (conn->error) { if (conn->error) {
if (!dead) die();
conn->cancel(); conn->cancel();
conn = NULL; conn = NULL;
return; return;

View file

@ -143,9 +143,14 @@ $socket = IO::Socket::INET->new(
print "[ii] connected\r\n"; print "[ii] connected\r\n";
# negotiate attributs # negotiate attributs
print $socket "move 1.0\r\n"; if ($ARGV[1]) {
print $socket "attack 1.0\r\n"; print "[ii] recovering agent $ARGV[1]\r\n";
print $socket "defense 1.0\r\n"; print $socket "agent_id $ARGV[1]\r\n";
} else {
print $socket "move 1.0\r\n";
print $socket "attack 1.0\r\n";
print $socket "defense 1.0\r\n";
}
print $socket "\r\n"; print $socket "\r\n";
print "[ii] agent created\r\n"; print "[ii] agent created\r\n";

View file

@ -2,6 +2,7 @@
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <sstream>
#include <sys/select.h> #include <sys/select.h>
#include <pthread.h> #include <pthread.h>
@ -9,6 +10,7 @@
#include "agent.h" #include "agent.h"
#include "connection.h" #include "connection.h"
#include "main.h"
#define buf_incomplete(buf) \ #define buf_incomplete(buf) \
(buf.find("\r\n") == std::string::npos || (buf.find("\r\n") > 0 && buf.find("\r\n\r\n") == std::string::npos)) (buf.find("\r\n") == std::string::npos || (buf.find("\r\n") > 0 && buf.find("\r\n\r\n") == std::string::npos))
@ -120,6 +122,28 @@ connection::actions(class agent &agent)
if (rate >= 0 && rate <= 1) if (rate >= 0 && rate <= 1)
agent.attr.defense = rate; agent.attr.defense = rate;
} else if (negotiation && !cmd.compare("agent_id")) {
int id = -1;
sscanf(line.c_str(), "%d", &id);
if (id < 0) {
bump_negot:
bump(); out_buf.append("\r\n");
} else {
class agent *a2 = NULL;
for (std::list<class agent *>::iterator ai = agents.begin(); ai != agents.end(); ai++) {
if ((*ai)->id == id) {
a2 = *ai;
break;
}
}
if (!a2 || a2->conn || !a2->tile || (dynamic_cast<herb *> (a2)))
goto bump_negot;
/* Round and round she goes, where she stops, nobody knows. */
a2->conn = this;
agent.conn = NULL;
negotiation = false;
}
} else if (!negotiation && !cmd.compare("move_dir") && !(mask & 1)) { } else if (!negotiation && !cmd.compare("move_dir") && !(mask & 1)) {
int x = 0, y = 0; int x = 0, y = 0;
sscanf(line.c_str(), "%d %d", &x, &y); sscanf(line.c_str(), "%d %d", &x, &y);
@ -154,6 +178,10 @@ connection::actions(class agent &agent)
if (negotiation) { if (negotiation) {
negotiation = false; negotiation = false;
agent.spawn(); agent.spawn();
std::stringstream s;
s << "agent_id " << agent.id << "\r\n";
out_buf.append(s.str());
} }
pthread_mutex_unlock(&buf_lock); pthread_mutex_unlock(&buf_lock);