summaryrefslogtreecommitdiff
path: root/game.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game.cpp')
-rw-r--r--game.cpp285
1 files changed, 285 insertions, 0 deletions
diff --git a/game.cpp b/game.cpp
new file mode 100644
index 0000000..7d87e2b
--- /dev/null
+++ b/game.cpp
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2016 Olivier Gayot <olivier.gayot@sigexec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <iostream>
+#include <vector>
+#include "game.h"
+
+#define CARDS_PER_PLAYER 10
+
+namespace cao {
+ /* game {{{ */
+
+ game::game(const cards::deck &black_deck, const cards::deck &white_deck)
+ : _board(black_deck, white_deck), _state(WAITING_NEW_JUDGE),
+ _players(), _judge()
+ {
+ std::clog << "creating new game" << std::endl;
+ }
+
+ player *game::try_join(client *client)
+ {
+ if (_players.size() >= CARDS_PER_PLAYER) {
+ std::clog << "too many players in this game" << std::endl;
+ /* TODO send error */
+ return NULL;
+ }
+
+ /* pick 10 cards */
+ std::vector<const cards::card *> cards;
+
+ try {
+ for (int i = 0; i < CARDS_PER_PLAYER; ++i) {
+ cards.push_back(_board.pick_white_card());
+ }
+ } catch (std::string index_error) {
+ std::clog << "not enough white cards for player" << std::endl;
+ /* TODO send error */
+
+ /* TODO put the cards back in the pick */
+
+ return NULL;
+ }
+
+ player *p = new player(client);
+
+ for (std::vector<const cards::card *>::const_iterator it = cards.begin();
+ it != cards.end(); ++it)
+ {
+ p->receive_card(*it);
+ }
+
+ _players.push_back(p);
+
+ /* TODO send notification to other players */
+
+ /* TODO send cards and game state to player */
+
+ return p;
+ }
+
+ void game::try_become_judge(player *p)
+ {
+ if (_state != WAITING_NEW_JUDGE) {
+ std::clog << "someone is judge already" << std::endl;
+ /* TODO send error */
+ return;
+ }
+
+ _judge = p;
+ _board.reveal_black_card();
+
+ _state = WAITING_COLLECTION;
+
+ /* TODO send notification "judge designed" to other players */
+
+ /* TODO send black card back to player */
+ }
+
+ void game::try_play_card(player *p, int idx)
+ {
+ if (_state != WAITING_COLLECTION) {
+ std::clog << "Who asked you to play now ?!" << std::endl;
+ /* TODO send error */
+ return;
+ }
+
+ if (_judge == p) {
+ std::clog << "You're the judge, you silly" << std::endl;
+ /* TODO send error */
+ return;
+ }
+
+ if (p->has_played()) {
+ std::clog << "You already played, dumb ass" << std::endl;
+ /* TODO send error */
+ return;
+ }
+
+ const cards::card *c;
+
+ try {
+ c = p->pop_card(idx);
+ } catch (std::string idnex_error) {
+ std::clog << "Invalid card idx" << std::endl;
+ /* TODO send error */
+ return;
+ }
+
+ p->has_played(true);
+
+ _board.play_card(c, p);
+
+ /* TODO send notification to judge */
+
+ /* TODO return card id back to the plaeyr */
+ return;
+ }
+
+ void game::try_collect_cards(player *p)
+ {
+ if (_state != WAITING_COLLECTION) {
+ std::clog << "Do you think it's the moment for collection !?" << std::endl;
+ /* TODO send error */
+ return;
+ }
+
+ if (_judge != p) {
+ std::clog << "You are not the judge, you fool !" << std::endl;
+ /* TODO send error */
+ return;
+ }
+
+ _board.shuffle_flop();
+
+ /* we prevent the others to play */
+ _state = WAITING_DESIGNATION;
+
+ /* TODO send notification cards collected to the others */
+
+ /* TODO send the flop back to the player */
+ }
+
+ /* TODO handle when no cards are on the board */
+ void game::try_designate_card(player *p, int idx)
+ {
+ if (_state != WAITING_DESIGNATION) {
+ std::clog << "not now, moron !" << std::endl;
+ /* TODO send error */
+
+ return;
+ }
+
+ if (_judge != p) {
+ std::clog << "who do you think you are !?" << std::endl;
+ /* TODO send error */
+
+ return;
+ }
+
+ if ((idx == -1) && (!_board.get_flop().empty())) {
+ std::clog << "there are cards on the board, so pick one !" << std::endl;
+ /* TODO send error */
+ return;
+ }
+
+ if ((idx >= 0) && (!_board.get_flop().empty())) {
+ /* TODO apparently, there's an exception to check */
+ /* there are cards on the board */
+
+ player *winner;
+
+ try {
+ winner = _board.get_flop()[idx].second;
+ } catch (std::string index_error) {
+ std::clog << "invalid card" << std::endl;
+ /* TODO send error */
+ return;
+ }
+
+ winner->inc_score();
+
+ /* put the cards back in the deck */
+ _board.recycle_flop();
+
+ /* reset the state of the players */
+ for (std::vector<player *>::iterator it = _players.begin();
+ it != _players.end(); ++it)
+ {
+ player *target = (*it);
+
+ if (target->has_played()) {
+ target->receive_card(_board.pick_white_card());
+
+ /* TODO send notification to the player */
+
+ target->has_played(false);
+ }
+ }
+ }
+
+ _board.recycle_black_card();
+ _judge = NULL;
+ _state = WAITING_NEW_JUDGE;
+
+ /* TODO send notification judge needed to the other players */
+ }
+
+ void game::try_view_player_cards(const player *p) const
+ {
+ (void) p;
+ /* TODO return the cards along with their index */
+ }
+
+ void game::try_view_flop() const
+ {
+ if (_state != WAITING_DESIGNATION) {
+ std::clog << "not now, moron !" << std::endl;
+ /* TODO send error */
+ return;
+
+ }
+
+ /* TODO return the cards */
+ }
+
+ void game::try_view_black_card() const
+ {
+ const cards::card *c = _board.get_current_black_card();
+
+ if (c) {
+ /* TODO return the black card to the player */
+ return;
+ }
+
+ std::clog << "The black card has not been revealed yet" << std::endl;
+ /* TODO send error */
+ }
+
+ /* }}} */
+ /* game_manager {{{ */
+
+ game_manager *game_manager::_instance = NULL;
+
+ game_manager *game_manager::get_instance()
+ {
+ if (!_instance) {
+ _instance = new game_manager();
+ }
+
+ return _instance;
+ }
+
+ game_manager::game_manager()
+ : _games(),
+ black_deck("usr/share/cao/lang/en/cards/black"),
+ white_deck("usr/share/cao/lang/en/cards/white")
+ { }
+
+ game *game_manager::find_game_by_name(const std::string &game_name)
+ {
+ std::map<const std::string, game *>::iterator it = _games.find(game_name);
+
+ if (it != _games.end())
+ return it->second;
+
+ return _games[game_name] = new game(black_deck, white_deck);
+ }
+
+ /* }}} */
+};