as dumb, but better structure
This commit is contained in:
parent
faee90c42b
commit
64ccef590d
171
src/main.cc
171
src/main.cc
|
@ -17,34 +17,59 @@
|
||||||
|
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
|
|
||||||
asio::awaitable<void> AsyncMain(asio::any_io_executor executor,
|
class Bot {
|
||||||
std::string_view name, std::string_view pass) {
|
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<void> Protocol();
|
||||||
|
asio::awaitable<void> Join();
|
||||||
|
asio::awaitable<bool> Move(Direction dir);
|
||||||
|
asio::awaitable<void> 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<void> Bot::Protocol() {
|
||||||
asio::ip::tcp::resolver resolver{executor};
|
asio::ip::tcp::resolver resolver{executor};
|
||||||
asio::ip::tcp::resolver::query query{"94.45.241.27", "4000"};
|
asio::ip::tcp::resolver::query query{"94.45.241.27", "4000"};
|
||||||
asio::ip::tcp::socket socket{executor};
|
|
||||||
|
|
||||||
co_await asio::async_connect(
|
co_await asio::async_connect(
|
||||||
socket, co_await resolver.async_resolve(query, asio::use_awaitable),
|
socket, co_await resolver.async_resolve(query, asio::use_awaitable),
|
||||||
asio::use_awaitable);
|
asio::use_awaitable);
|
||||||
|
|
||||||
std::random_device generator;
|
|
||||||
int goal_x, goal_y;
|
|
||||||
int x, y;
|
|
||||||
while (true) {
|
while (true) {
|
||||||
boost::asio::streambuf ibuf, obuf;
|
asio::streambuf buf;
|
||||||
ibuf.commit(co_await asio::async_read_until(socket, ibuf, '\n',
|
buf.commit(co_await asio::async_read_until(socket, buf, '\n',
|
||||||
asio::use_awaitable));
|
asio::use_awaitable));
|
||||||
std::istream is{&ibuf};
|
std::istream is{&buf};
|
||||||
std::ostream os{&obuf};
|
|
||||||
std::string field;
|
std::string field;
|
||||||
char dummy;
|
char dummy;
|
||||||
std::getline(is, field, '|');
|
std::getline(is, field, '|');
|
||||||
if (field == "motd") {
|
if (field == "motd") {
|
||||||
std::getline(is, field);
|
std::getline(is, field);
|
||||||
std::cout << "-> MotD: " << field << std::endl;
|
std::cout << "-> MotD: " << field << std::endl;
|
||||||
os << "join|" << name << '|' << pass << std::endl;
|
co_await Join();
|
||||||
co_await async_write(socket, obuf.data(), asio::use_awaitable);
|
|
||||||
std::cout << "<- Join as " << name << std::endl;
|
|
||||||
} else if (field == "error") {
|
} else if (field == "error") {
|
||||||
std::getline(is, field);
|
std::getline(is, field);
|
||||||
std::cout << "-> Error: " << field << std::endl;
|
std::cout << "-> Error: " << field << std::endl;
|
||||||
|
@ -54,7 +79,6 @@ asio::awaitable<void> AsyncMain(asio::any_io_executor executor,
|
||||||
std::cout << "-> Goal is at (" << goal_x << ", " << goal_y << ")"
|
std::cout << "-> Goal is at (" << goal_x << ", " << goal_y << ")"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
} else if (field == "pos") {
|
} else if (field == "pos") {
|
||||||
bool up, right, down, left;
|
|
||||||
is >> x >> dummy >> y >> dummy >> up >> dummy >> right >> dummy >> down >>
|
is >> x >> dummy >> y >> dummy >> up >> dummy >> right >> dummy >> down >>
|
||||||
dummy >> left;
|
dummy >> left;
|
||||||
std::cout << "-> Position at (" << x << ", " << y << ")" << std::endl;
|
std::cout << "-> Position at (" << x << ", " << y << ")" << std::endl;
|
||||||
|
@ -62,49 +86,7 @@ asio::awaitable<void> AsyncMain(asio::any_io_executor executor,
|
||||||
std::cout << " Walls are " << X(up) << X(right) << X(down) << X(left)
|
std::cout << " Walls are " << X(up) << X(right) << X(down) << X(left)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#undef X
|
#undef X
|
||||||
#define X(cond, dir) \
|
co_await ChooseMove();
|
||||||
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<int> 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
|
|
||||||
}
|
|
||||||
} else if (field == "win" || field == "lose") {
|
} else if (field == "win" || field == "lose") {
|
||||||
int win, lose;
|
int win, lose;
|
||||||
is >> win >> dummy >> lose;
|
is >> win >> dummy >> lose;
|
||||||
|
@ -119,17 +101,82 @@ asio::awaitable<void> AsyncMain(asio::any_io_executor executor,
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
asio::awaitable<void> Bot::Join() {
|
||||||
asio::io_context context;
|
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<bool> 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<void> 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<int> direction{0, 3};
|
||||||
|
while (!co_await Move(Direction{direction(generator)}))
|
||||||
|
;
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
std::cerr << "usage: " << argv[0] << " <name> <pass>" << std::endl;
|
std::cerr << "usage: " << argv[0] << " <name> <pass>" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
asio::co_spawn(
|
asio::io_context context;
|
||||||
context, std::bind(&AsyncMain, context.get_executor(), argv[1], argv[2]),
|
Bot bot{context.get_executor(), argv[1], argv[2]};
|
||||||
asio::detached);
|
|
||||||
context.run();
|
context.run();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue