From 64ccef590d745913e5b920e538be1ace5fca9c79 Mon Sep 17 00:00:00 2001 From: Thomas Lindner Date: Fri, 20 May 2022 15:12:07 +0200 Subject: [PATCH] as dumb, but better structure --- src/main.cc | 173 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 110 insertions(+), 63 deletions(-) diff --git a/src/main.cc b/src/main.cc index 38ccaa2..8a1e789 100644 --- a/src/main.cc +++ b/src/main.cc @@ -17,34 +17,59 @@ namespace asio = boost::asio; -asio::awaitable AsyncMain(asio::any_io_executor executor, - std::string_view name, std::string_view pass) { +class Bot { + asio::any_io_executor executor; + asio::ip::tcp::socket socket; + std::string name; + std::string pass; + std::random_device generator; + int goal_x, goal_y; + int x, y; + bool up, right, down, left; + + enum class Direction : int { + UP, + RIGHT, + DOWN, + LEFT, + }; + + asio::awaitable Protocol(); + asio::awaitable Join(); + asio::awaitable Move(Direction dir); + asio::awaitable ChooseMove(); + + public: + Bot(asio::any_io_executor executor, std::string_view name, + std::string_view pass); +}; + +Bot::Bot(asio::any_io_executor executor, std::string_view name, + std::string_view pass) + : executor{executor}, socket{executor}, name{name}, pass{pass} { + asio::co_spawn(executor, std::bind(&Bot::Protocol, this), asio::detached); +} + +asio::awaitable Bot::Protocol() { asio::ip::tcp::resolver resolver{executor}; asio::ip::tcp::resolver::query query{"94.45.241.27", "4000"}; - asio::ip::tcp::socket socket{executor}; co_await asio::async_connect( socket, co_await resolver.async_resolve(query, asio::use_awaitable), asio::use_awaitable); - std::random_device generator; - int goal_x, goal_y; - int x, y; while (true) { - boost::asio::streambuf ibuf, obuf; - ibuf.commit(co_await asio::async_read_until(socket, ibuf, '\n', - asio::use_awaitable)); - std::istream is{&ibuf}; - std::ostream os{&obuf}; + 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; - os << "join|" << name << '|' << pass << std::endl; - co_await async_write(socket, obuf.data(), asio::use_awaitable); - std::cout << "<- Join as " << name << std::endl; + co_await Join(); } else if (field == "error") { std::getline(is, field); std::cout << "-> Error: " << field << std::endl; @@ -54,7 +79,6 @@ asio::awaitable AsyncMain(asio::any_io_executor executor, std::cout << "-> Goal is at (" << goal_x << ", " << goal_y << ")" << std::endl; } else if (field == "pos") { - bool up, right, down, left; is >> x >> dummy >> y >> dummy >> up >> dummy >> right >> dummy >> down >> dummy >> left; std::cout << "-> Position at (" << x << ", " << y << ")" << std::endl; @@ -62,49 +86,7 @@ asio::awaitable AsyncMain(asio::any_io_executor executor, std::cout << " Walls are " << X(up) << X(right) << X(down) << X(left) << std::endl; #undef X -#define X(cond, dir) \ - if ((cond) && !dir) { \ - os << "move|" #dir << std::endl; \ - co_await async_write(socket, obuf.data(), asio::use_awaitable); \ - std::cout << "<- Go " #dir << std::endl; \ - continue; \ - } - X(x > goal_x, left); - X(y > goal_y, up); - X(x < goal_x, right); - X(y < goal_y, down); -#undef X - std::uniform_int_distribution direction{0, 3}; - switch (direction(generator)) { -#define X(n, dir) \ - case n: \ - if (!dir) { \ - os << "move|" #dir << std::endl; \ - co_await async_write(socket, obuf.data(), asio::use_awaitable); \ - std::cout << "<- Go " #dir << std::endl; \ - continue; \ - } - X(0, left); - [[fallthrough]]; - X(1, up); - [[fallthrough]]; - X(2, right); - [[fallthrough]]; - X(3, down); -#undef X -#define X(dir) \ - if (!dir) { \ - os << "move|" #dir << std::endl; \ - co_await async_write(socket, obuf.data(), asio::use_awaitable); \ - std::cout << "<- Go " #dir << std::endl; \ - continue; \ - } - X(left); - X(up); - X(right); - X(down); -#undef X - } + co_await ChooseMove(); } else if (field == "win" || field == "lose") { int win, lose; is >> win >> dummy >> lose; @@ -119,17 +101,82 @@ asio::awaitable AsyncMain(asio::any_io_executor executor, co_return; } -int main(int argc, char **argv) { - asio::io_context context; +asio::awaitable Bot::Join() { + asio::streambuf buf; + std::ostream os{&buf}; + os << "join|" << name << '|' << pass << std::endl; + std::cout << "<- Join as " << name << std::endl; + co_await async_write(socket, buf.data(), asio::use_awaitable); + co_return; +} +asio::awaitable Bot::Move(Direction direction) { + asio::streambuf buf; + std::ostream os{&buf}; + std::string_view direction_str; + switch (direction) { + case Direction::LEFT: + direction_str = "left"; + if (left) { + co_return false; + } + break; + case Direction::UP: + direction_str = "up"; + if (up) { + co_return false; + } + break; + case Direction::RIGHT: + direction_str = "right"; + if (right) { + co_return false; + } + break; + case Direction::DOWN: + direction_str = "down"; + if (down) { + co_return false; + } + break; + } + os << "move|" << direction_str << std::endl; + std::cout << "<- Go " << direction_str << std::endl; + co_await async_write(socket, buf.data(), asio::use_awaitable); + co_return true; +} + +asio::awaitable Bot::ChooseMove() { + // move closer to the goal if possible + if (x > goal_x && co_await Move(Direction::LEFT)) { + co_return; + } + if (x > goal_y && co_await Move(Direction::UP)) { + co_return; + } + if (x < goal_x && co_await Move(Direction::RIGHT)) { + co_return; + } + if (x < goal_y && co_await Move(Direction::DOWN)) { + co_return; + } + + // choose a random direction + std::uniform_int_distribution direction{0, 3}; + while (!co_await Move(Direction{direction(generator)})) + ; + + co_return; +} + +int main(int argc, char **argv) { if (argc < 3) { std::cerr << "usage: " << argv[0] << " " << std::endl; return 1; } - asio::co_spawn( - context, std::bind(&AsyncMain, context.get_executor(), argv[1], argv[2]), - asio::detached); + asio::io_context context; + Bot bot{context.get_executor(), argv[1], argv[2]}; context.run(); return 0; }