From 2b29d4f8843c21b09d2e8f5183b6edba4063c191 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Thu, 25 Nov 2010 11:20:26 +0100 Subject: Replace GameVariant/RuleSet::Standard with Game::Player. --- server/game.cpp | 278 ++++++++++++++++++++++++++++++++++++++++---------------- server/game.h | 31 +++++-- 2 files changed, 224 insertions(+), 85 deletions(-) diff --git a/server/game.cpp b/server/game.cpp index f2b1c06..1f43e9b 100644 --- a/server/game.cpp +++ b/server/game.cpp @@ -3,6 +3,8 @@ #include #include +#include +#include #ifdef DEBUG #include @@ -19,20 +21,17 @@ Game::p Game::create(Client::p player_1, Client::p player_2, Client::p player_3, Game::~Game() { std::cout << "Game destroyed." << std::endl; - delete ruleset; } Game::Game(Client::p player_1, Client::p player_2, Client::p player_3, Client::p player_4) { - players.push_back(player_1); - players.push_back(player_2); - players.push_back(player_3); - players.push_back(player_4); + players[0].client = player_1; + players[1].client = player_2; + players[2].client = player_3; + players[3].client = player_4; } void Game::handle_ready() { - std::cout << "Still waiting for " << waiting_players << "." << std::endl; - - if(--waiting_players) { + if(--awaiting_players) { return; } @@ -41,80 +40,221 @@ void Game::handle_ready() { round_start(); } -void Game::round_start() { - players[0]->round_start(); - players[1]->round_start(); - players[2]->round_start(); - players[3]->round_start(); - - ruleset = new RuleSet::Standard(); - ruleset->round_start(); +void Game::start() { + std::cout << "Started a game with " + << players[0].client->nick() << ", " + << players[1].client->nick() << ", " + << players[2].client->nick() << " and " + << players[3].client->nick() << "." << std::endl; + + awaiting_players = 4; + + std::vector pl; - round_update(); + pl.push_back(players[0].client->nick()); + pl.push_back(players[1].client->nick()); + pl.push_back(players[2].client->nick()); + pl.push_back(players[3].client->nick()); + + players[0].client->game_start(boost::bind(&Game::handle_ready, shared_from_this()), pl); + players[1].client->game_start(boost::bind(&Game::handle_ready, shared_from_this()), pl); + players[2].client->game_start(boost::bind(&Game::handle_ready, shared_from_this()), pl); + players[3].client->game_start(boost::bind(&Game::handle_ready, shared_from_this()), pl); } -void Game::round_update() { +void Game::round_start() { + // Build a new wall. + wall.build(); + + // Notify players of round start. + // TODO: Tell them where wall is broken. + players[0].round_start(); + players[1].round_start(); + players[2].round_start(); + players[3].round_start(); + + // Draw hands. + for(int i = 0; i < 13; i++) { + players[0].draw(wall.take_one()); + players[1].draw(wall.take_one()); + players[2].draw(wall.take_one()); + players[3].draw(wall.take_one()); + } - State gamestate = ruleset->round_update(); - - // Send the updates state to the players - players[0]->round_state(gamestate); - players[1]->round_state(gamestate); - players[2]->round_state(gamestate); - players[3]->round_state(gamestate); + // Sort hands. + players[0].hand.sort(); + players[1].hand.sort(); + players[2].hand.sort(); + players[3].hand.sort(); + + // Give east an extra tile. + players[0].draw(wall.take_one()); + + current_player = 0; + + round_update_draw(); +} +void Game::round_update_draw() { + // Get possible actions for current player. + Actions possible_actions = players[current_player].get_actions_draw(); - // Only implemented discard so far, so only current player that needs to be able to do a action. - int smart = 0; - for(Actions::iterator it = gamestate.possible_actions.begin(); it != gamestate.possible_actions.end(); ++it) { - //smart = smart | (1 << it->player); + // Construct and send state to each client. + for(int i = 0; i < 4; i++) { + State state; + + state.players[0] = players[i].get_state(); + state.players[1] = players[(i + 1) % 4].get_state_filtered(); + state.players[2] = players[(i + 2) % 4].get_state_filtered(); + state.players[3] = players[(i + 3) % 4].get_state_filtered(); + + if(i == current_player) { + state.possible_actions = possible_actions; + } + + players[i].client->round_state(state); } - int num_player_actions = 0; + // Await action from client. + players[current_player].client->get_action(boost::bind(&Game::handle_action_draw, shared_from_this(), _1), possible_actions); +} + +void Game::round_update_discard() { + Tile discarded_tile = players[current_player].last_discard(); - if(smart & 1) { - num_player_actions++; - players[0]->get_action(boost::bind(&Game::handle_action, shared_from_this(), _1), gamestate.possible_actions); - } - if(smart & 2) { - num_player_actions++; - players[1]->get_action(boost::bind(&Game::handle_action, shared_from_this(), _1), gamestate.possible_actions); - } - if(smart & 4) { - num_player_actions++; - players[2]->get_action(boost::bind(&Game::handle_action, shared_from_this(), _1), gamestate.possible_actions); - } - if(smart & 8) { - num_player_actions++; - players[3]->get_action(boost::bind(&Game::handle_action, shared_from_this(), _1), gamestate.possible_actions); + std::map possible_actions; + + // Construct and send state to each client. + for(int i = 0; i < 4; i++) { + State state; + + state.players[0] = players[i].get_state(); + state.players[1] = players[(i + 1) % 4].get_state_filtered(); + state.players[2] = players[(i + 2) % 4].get_state_filtered(); + state.players[3] = players[(i + 3) % 4].get_state_filtered(); + + if(i != current_player) { + Actions a = players[i].get_actions_discard(discarded_tile); + if(a) { + state.possible_actions = possible_actions[i] = a; + } + } + + players[i].client->round_state(state); } - if(num_player_actions == 0) { - round_update(); + preceding_action = Action::Pass; + if(possible_actions.empty()) { + awaiting_players = 1; + handle_action_discard(Action::Pass, 0); + } else { + awaiting_players = possible_actions.size(); + for(std::map::iterator it = possible_actions.begin(); it != possible_actions.end(); it++) { + players[it->first].client->get_action(boost::bind(&Game::handle_action_discard, shared_from_this(), _1, it->first), it->second); + } } } -void Game::handle_action(Action action) { - - //players[action.player]->kill_action(); +void Game::handle_action_draw(Action action) { + switch(action.type) { + case Action::Discard: { + players[current_player].discard(action.target); + round_update_discard(); + } break; + + case Action::Riichi: + case Action::Kan: + case Action::Tsumo: + case Action::Draw: + // Not implemented yet. + + // Will never occur on draw: + case Action::Pass: + case Action::Chi: + case Action::Pon: + case Action::Ron: + break; + } +} + +void Game::handle_action_discard(Action action, int player) { + switch(preceding_action.type) { + case Action::Pass: + + case Action::Chi: + if(action.type == Action::Chi) { + preceding_action = action; + preceding_action_owner = player; + break; + } + + case Action::Kan: + if(action.type == Action::Kan) { + preceding_action = action; + preceding_action_owner = player; + break; + } + + case Action::Pon: + if(action.type == Action::Pon) { + preceding_action = action; + preceding_action_owner = player; + break; + } + + case Action::Ron: + if(action.type == Action::Ron) { + // TODO: Handle simultanous ron. + preceding_action = action; + preceding_action_owner = player; + break; + } + break; + + // Will never occur on discard: + case Action::Discard: + case Action::Riichi: + case Action::Tsumo: + case Action::Draw: + break; + } - bool done = ruleset->round_action(action); + if(--awaiting_players) { + return; + } - if(done) { - round_update(); + switch(preceding_action.type) { + case Action::Pass: { + // Tile not claimed, next player draws. + current_player = (current_player + 1) % 4; + players[current_player].draw(wall.take_one()); + round_update_draw(); + } break; + + case Action::Chi: + case Action::Kan: + case Action::Pon: + case Action::Ron: + // Not implemented yet. + std::cout << "Hei, morn, god dag!" << std::endl; + break; + + // Will never occur on discard: + case Action::Discard: + case Action::Riichi: + case Action::Tsumo: + case Action::Draw: + break; } - // Sjekk action, sjekk om endelig action er avgjort - // Oppdater state - // Evt. round_end() } void Game::round_end() { // Flere runder? round_start() // Ferdig? game_end() - players[0]->round_end(); - players[1]->round_end(); - players[2]->round_end(); - players[3]->round_end(); + players[0].client->round_end(); + players[1].client->round_end(); + players[2].client->round_end(); + players[3].client->round_end(); #ifdef DEBUG @@ -124,24 +264,6 @@ void Game::round_end() { #endif } -void Game::start() { - std::cout << "Started a game with " - << players[0]->nick() << ", " - << players[1]->nick() << ", " - << players[2]->nick() << " and " - << players[3]->nick() << "." << std::endl; - - players[0]->id = 0; - players[1]->id = 1; - players[2]->id = 2; - players[3]->id = 3; - - waiting_players = 4; - - players[0]->game_start(boost::bind(&Game::handle_ready, shared_from_this()), players); - players[1]->game_start(boost::bind(&Game::handle_ready, shared_from_this()), players); - players[2]->game_start(boost::bind(&Game::handle_ready, shared_from_this()), players); - players[3]->game_start(boost::bind(&Game::handle_ready, shared_from_this()), players); void Game::Player::round_start() { // Reset contents. hand.clear(); diff --git a/server/game.h b/server/game.h index 9c2513e..3eaac77 100644 --- a/server/game.h +++ b/server/game.h @@ -11,8 +11,6 @@ #include "../common/action.h" #include "../common/state.h" -#include "gamevariant.h" -#include "standard.h" class Game : public boost::enable_shared_from_this { public: @@ -23,7 +21,6 @@ class Game : public boost::enable_shared_from_this { ~Game(); private: - std::vector players; class Player { public: Client::p client; @@ -77,11 +74,18 @@ class Game : public boost::enable_shared_from_this { }; - int waiting_players; + Player players[4]; + + int current_player; + + int awaiting_players; + + Action preceding_action; + int preceding_action_owner; Game(Client::p player_1, Client::p player_2, Client::p player_3, Client::p player_4); - GameVariant *ruleset; + Wall wall; //! Handle Ready message from player. void handle_ready(); @@ -89,9 +93,22 @@ class Game : public boost::enable_shared_from_this { //! Start the game. void start(); + //! Start a new round. void round_start(); - void round_update(); - void handle_action(Action action); + + //! Send update after a tile is drawn. + void round_update_draw(); + + //! Send update after a tile is discarded. + void round_update_discard(); + + //! Handle action after draw. + void handle_action_draw(Action action); + + //! Handle actions after discard. + void handle_action_discard(Action action, int player); + + //! End the game. void round_end(); }; -- cgit v1.2.3