auto-reconnect and don't drop messages

This commit is contained in:
Thomas Lindner 2022-05-20 18:55:22 +02:00
parent 586889f543
commit 173182f8e7

View file

@ -6,11 +6,13 @@
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/read_until.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/asio/write.hpp>
#include <iostream>
#include <random>
#include <sstream>
#include <string>
#include <string_view>
#include <utility>
@ -40,6 +42,7 @@ std::string_view DirectionToString(Direction direction) {
class Bot {
asio::any_io_executor executor;
asio::steady_timer timer;
asio::ip::tcp::socket socket;
std::string name;
std::string pass;
@ -62,6 +65,7 @@ class Bot {
Bot::Bot(asio::any_io_executor executor, std::string_view name,
std::string_view pass)
: executor{executor},
timer{executor},
socket{executor},
name{name},
pass{pass},
@ -72,49 +76,66 @@ Bot::Bot(asio::any_io_executor executor, std::string_view name,
asio::awaitable<void> Bot::Protocol() {
asio::ip::tcp::resolver resolver{executor};
asio::ip::tcp::resolver::query query{"94.45.241.27", "4000"};
co_await asio::async_connect(
socket, co_await resolver.async_resolve(query, asio::use_awaitable),
asio::use_awaitable);
auto host = co_await resolver.async_resolve(query, asio::use_awaitable);
while (true) {
asio::streambuf buf;
buf.commit(co_await asio::async_read_until(socket, buf, '\n',
asio::use_awaitable));
std::istream is{&buf};
std::string field;
char dummy;
std::getline(is, field, '|');
if (field == "motd") {
std::getline(is, field);
std::cout << "-> MotD: " << field << std::endl;
co_await Join();
} else if (field == "error") {
std::getline(is, field);
std::cout << "-> Error: " << field << std::endl;
co_return;
} else if (field == "goal") {
is >> goal_x >> dummy >> goal_y;
std::cout << "-> Goal is at (" << goal_x << ", " << goal_y << ")"
<< std::endl;
} else if (field == "pos") {
is >> x >> dummy >> y >> dummy >> up >> dummy >> right >> dummy >> down >>
dummy >> left;
std::cout << "-> Position at (" << x << ", " << y << ")" << std::endl;
while (true) {
try {
co_await asio::async_connect(socket, host, asio::use_awaitable);
break;
} catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
timer.expires_after(std::chrono::seconds(1));
co_await timer.async_wait(asio::use_awaitable);
}
try {
while (true) {
asio::streambuf buf;
co_await asio::async_read_until(socket, buf, '\n', asio::use_awaitable);
std::istream is{&buf};
std::string line;
while (std::getline(is, line)) {
std::istringstream iss{line};
std::string field;
char dummy;
std::getline(iss, field, '|');
if (field == "motd") {
std::getline(iss, field);
std::cout << "-> MotD: " << field << std::endl;
co_await Join();
} else if (field == "error") {
std::getline(iss, field);
std::cout << "-> Error: " << field << std::endl;
} else if (field == "goal") {
iss >> goal_x >> dummy >> goal_y;
std::cout << "-> Goal is at (" << goal_x << ", " << goal_y << ")"
<< std::endl;
} else if (field == "pos") {
iss >> x >> dummy >> y >> dummy >> up >> dummy >> right >> dummy >>
down >> dummy >> left;
std::cout << "-> Position at (" << x << ", " << y << ")"
<< std::endl;
#define X(b) (b ? #b ", " : "")
std::cout << " Walls are " << X(up) << X(right) << X(down) << X(left)
<< std::endl;
std::cout << " Walls are (" << X(up) << X(right) << X(down)
<< X(left) << ")" << std::endl;
#undef X
co_await ChooseMove();
} else if (field == "win" || field == "lose") {
int win, lose;
is >> win >> dummy >> lose;
std::cout << "-> You " << field << '!' << std::endl;
std::cout << " Score: " << win << '/' << lose << std::endl;
} else {
std::cout << "unhandled message: " << field << '|';
std::getline(is, field);
std::cout << field << std::endl;
co_await ChooseMove();
} else if (field == "win" || field == "lose") {
int win, lose;
iss >> win >> dummy >> lose;
std::cout << "-> You " << field << '!' << std::endl;
std::cout << " Score: " << win << '/' << lose << std::endl;
} else {
std::cout << "unhandled message: " << field << '|';
std::getline(iss, field);
std::cout << field << std::endl;
}
}
}
} catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
}
co_return;