/* * Copyright (C) 2016 Olivier Gayot * * 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 #include #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 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_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::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::iterator it = _games.find(game_name); if (it != _games.end()) return it->second; return _games[game_name] = new game(black_deck, white_deck); } /* }}} */ };