summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/game.cpp278
-rw-r--r--server/game.h31
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 <boost/bind.hpp>
#include <iostream>
+#include <algorithm>
+#include <map>
#ifdef DEBUG
#include <ctime>
@@ -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<std::string> 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<int, Actions> 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<int, Actions>::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<Game> {
public:
@@ -23,7 +21,6 @@ class Game : public boost::enable_shared_from_this<Game> {
~Game();
private:
- std::vector<Client::p> players;
class Player {
public:
Client::p client;
@@ -77,11 +74,18 @@ class Game : public boost::enable_shared_from_this<Game> {
};
- 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<Game> {
//! 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();
};