tictactoebot/src/bot.cpp

120 lines
3.0 KiB
C++

#include "bot.h"
#include <sstream>
Bot::Bot(TelegramAPI::Manager* tapi, Conf& conf) : tapi(tapi), conf(conf) {}
Bot::~Bot() {
for(auto it : games) {
delete it.second;
}
}
bool Bot::handleStart(TelegramAPI::Manager* api, const TelegramAPI::Message& msg) {
if(msg.chat.id > 0) {
api->sendMessage(msg.chat.id, "This bot should be used in group chats");
}
// create a game
Game* g = new Game();
// g->addPlayer(msg.from.id); // does not work
auto sendmsg = api->sendMessage(msg.chat.id, gameToMessage(g), gameToKeyboard(g));
if(sendmsg) {
int64_t chatid = sendmsg.chat.id;
uint64_t msgid = sendmsg.messageId;
g->setMessageID(msgid);
games.insert({{chatid, msgid}, g});
return true;
}
return false;
}
bool Bot::handleMessage(TelegramAPI::Manager* api, TelegramAPI::Message& msg) {
return true;
}
bool Bot::handleCallback(TelegramAPI::Manager* api, TelegramAPI::CallbackQuery& clbq) {
int64_t chatid = clbq.message.chat.id;
uint64_t msgid = clbq.message.messageId;
const std::string& data = clbq.data;
auto it = games.find({chatid, msgid});
if(it == games.end()) {
api->answerCallbackQuery(clbq.id, "Invalid game");
return true;
}
Game* g = it->second;
if(data == "join") {
if(g->addPlayer(clbq.from.id)) {
api->answerCallbackQuery(clbq.id, "You joined the game");
updateGame(chatid, msgid, g);
return true;
}
api->answerCallbackQuery(clbq.id, "You can not join");
return true;
}
// try to parse "x y"
std::istringstream datastream(data);
int x = -1, y = -1;
datastream >> x >> y;
if(x != -1 && y != -1) {
Log::info << "turn: " << (int) x << " " << (int) y << " " << clbq.from.id;
if(g->turn(x, y, clbq.from.id)) {
api->answerCallbackQuery(clbq.id, "ok");
updateGame(chatid, msgid, g);
return true;
}
api->answerCallbackQuery(clbq.id, "Error - this is not your turn");
}
api->answerCallbackQuery(clbq.id, "Error - invalid button");
return true;
}
void Bot::stop() {
}
void Bot::updateGame(int64_t chatid, uint64_t msgid, const Game* g) {
tapi->editMessageText(chatid, msgid, gameToMessage(g), gameToKeyboard(g));
}
TelegramAPI::InlineKeyboard Bot::gameToKeyboard(const Game* g) const {
static const std::string text[3] = {" ", "X", "O"};
TelegramAPI::InlineKeyboard kb;
for(uint_fast8_t row = 0; row < g->getSize(); row++) {
for(uint_fast8_t col = 0; col < g->getSize(); col++) {
Game::SYM s = g->getPos(col, row);
const std::string clb = std::to_string(col) + " " + std::to_string(row);
auto btn = TelegramAPI::InlineButton::createCallback(text[(int) s], clb);
kb.addButton(btn, row);
}
}
if(!g->ready() && !g->done()) {
// missing player
kb.addButton(TelegramAPI::InlineButton::createCallback("Join Game", "join"), g->getSize());
}
return kb;
}
std::string Bot::gameToMessage(const Game* g) const {
std::ostringstream out;
out << "X: " << g->getPlayerA() << std::endl;
out << "O: " << g->getPlayerB() << std::endl;
if(g->done()) {
out << "Winner: " << g->getWinner() << std::endl;
} else {
out << "nextturn: " << (g->getNextTurn() ? "X" : "O") << std::endl;
}
return out.str();
}