-
-
Notifications
You must be signed in to change notification settings - Fork 98
/
main.cpp
144 lines (136 loc) · 4.82 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include "sleepy_discord/sleepy_discord.h"
#include <list>
#include <iostream>
#include <memory>
#include <mutex>
class GameClient : public SleepyDiscord::DiscordClient {
private:
enum State {
NA = 0,
GET_READY = 1, //Game is starting
SHOOT = 2, //waiting for answer
ENDED = 3
};
struct Game {
SleepyDiscord::User player;
std::shared_ptr<State> state;
SleepyDiscord::Timer endGameTimer;
std::mutex mutex;
Game(const SleepyDiscord::User& gamePlayer) :
player(gamePlayer), state(std::make_shared<State>(NA)) {}
//This is needed when we want to copy a game
Game(const Game& game) :
player(game.player), state(game.state), endGameTimer(game.endGameTimer) {}
#ifdef _DEBUG
~Game() {
std::cout << "DUBUG: game removed\n";
}
#endif
//void run(std::function<void(Game*)> startGame) {
// thread = std::thread(startGame, this);
//}
};
std::list<Game> games;
enum Weapon {
ROCK = 0,
PAPER = 1,
SCISSORS = 2
};
enum winState {
WIN = 1,
TIE = 0,
LOSE = 2
};
/*
ROCK - SCISSORS = 0 - 2 = -2 -> (-2 + 3) % 3 = WIN
PAPER - SCISSORS = 1 - 2 = -1 -> (-1 + 3) % 3 = LOSE
ROCK - PAPER = 0 - 1 = -1 -> (-1 + 3) % 3 = LOSE
PAPER - ROCK = 1 - 0 = 1 -> ( 1 + 3) % 3 = WIN
SCISSORS - PAPER = 2 - 1 = 1 -> ( 1 + 3) % 3 = WIN
SCISSORS - ROCK = 2 - 0 = 2 -> ( 2 + 3) % 3 = LOSE
*/
//#ifdef _DEBUG
void onHeartbeat() {
std::cout << "heartbeat sent\n";
}
void onHeartbeatAck() {
std::cout << "heartbeat acknowledged\n";
}
//#endif
public:
using SleepyDiscord::DiscordClient::DiscordClient;
void onMessage(SleepyDiscord::Message message) {
if (message.startsWith("test hello")) {
games.push_back(Game(message.author)); //create a game put it on the end of the list of games
#ifdef _DEBUG
std::cout << "DUBUG: New game created. Number of games: " << games.size() << '\n';
#endif
std::list<Game>::iterator game = --(games.end());
const std::lock_guard<std::mutex> lock(game->mutex);
*game->state = GET_READY;
SleepyDiscord::Message countMessage = sendMessage(message.channelID, "**ROCK!**");
schedule([this, countMessage]() {
this->editMessage(countMessage, "**PAPER!**");
}, 1000);
schedule([this, countMessage]() {
this->editMessage(countMessage, "**SCISSORS!**");
}, 2000);
schedule([this, game, countMessage]() {
const std::lock_guard<std::mutex> lock(game->mutex);
*game->state = SHOOT;
this->editMessage(countMessage, "**SHOOT!**");
}, 3000);
game->endGameTimer = schedule([this, game, message]() {
game->mutex.lock();
if (*game->state != ENDED) {
*game->state = ENDED;
sendMessage(message.channelID, "You lose.\nWhen I say ``shoot``, you pick ``rock``, ``paper``, or ``scissors``");
}
game->mutex.unlock();
this->games.erase(game);
}, 4000);
return;
}
if (games.empty()) return;
//get the player's choice
Weapon playerChoice;
if (message.content == "rock" || message.content == ":fist:" ) playerChoice = ROCK;
else if (message.content == "paper" || message.content == ":raised_hand:") playerChoice = PAPER;
else if (message.content == "scissors" || message.content == ":v:" ) playerChoice = SCISSORS;
else return; //go back if there's no choice was detected
for (Game& game : games) {
const std::lock_guard<std::mutex> lock(game.mutex);
if (game.player == message.author) {
#ifdef _DEBUG
std::cout << "DUBUG: Player detected " << game.player.username << " state: " << *game.state << '\n';
#endif
switch (*game.state) {
case SHOOT: {
*game.state = ENDED; //game state is set to end here, so that "you lose" isn't sent after a weapon was picked
Weapon botChoice = static_cast<Weapon>(rand() % 3); //random number 0 to 2
switch (botChoice) {
case ROCK: sendMessage(message.channelID, ":fist:"); break;
case PAPER: sendMessage(message.channelID, ":raised_hand:"); break;
case SCISSORS: sendMessage(message.channelID, ":v:"); break;
}
switch ((playerChoice - botChoice + 3) % 3) {
case LOSE: sendMessage(message.channelID, ":smiley: I won, and you lost!"); break;
case TIE: sendMessage(message.channelID, ":neutral_face: It's a tie"); break;
case WIN: sendMessage(message.channelID, ":frowning: I lost, and you won"); break;
}
} break;
case GET_READY: sendMessage(message.channelID, "Not yet, I didn't get to say ``shoot``."); break;
default: sendMessage(message.channelID, "Error: unknown state"); break;
}
}
}
}
};
int main() {
srand(static_cast<unsigned int>(time(0))); //create seed to make random numbers
GameClient client("Your Token Goes Here", SleepyDiscord::USER_CONTROLED_THREADS);
client.setIntents(
SleepyDiscord::Intent::SERVER_MESSAGES,
SleepyDiscord::Intent::DIRECT_MESSAGES);
client.run();
}