diff options
Diffstat (limited to 'game.cpp')
-rw-r--r-- | game.cpp | 285 |
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); + } + + /* }}} */ +}; |