summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAtle Hellvik Havsø <atle@havso.net>2010-11-22 20:08:56 +0100
committerAtle Hellvik Havsø <atle@havso.net>2010-11-22 20:09:18 +0100
commit62a05732e05a25f40fbb409e49ff30e3fc8bd28c (patch)
treef01f1b3946696042e532f423b7e3435befec6f8d
parent56e4891bcdd693cfba540aec186f151012d96870 (diff)
Moved lots of code in Game out into a separate class.
Signed-off-by: Atle Hellvik Havsø <atle@havso.net>
-rw-r--r--server/game.cpp408
-rw-r--r--server/game.h21
-rw-r--r--server/gamevariant.h20
-rw-r--r--server/standard.cpp418
-rw-r--r--server/standard.h37
5 files changed, 499 insertions, 405 deletions
diff --git a/server/game.cpp b/server/game.cpp
index ed5bf3f..d13235b 100644
--- a/server/game.cpp
+++ b/server/game.cpp
@@ -3,17 +3,14 @@
#include <boost/bind.hpp>
#include <iostream>
-#include <algorithm>
+
+#ifdef DEBUG
#include <ctime>
+#endif
#include "../common/set.h"
-bool MyDataSortPredicate(const Tile& d1, const Tile& d2)
-{
- return d1.type < d2.type;
-}
-
Game::p Game::create(Player::p player_1, Player::p player_2, Player::p player_3, Player::p player_4) {
Game::p p(new Game(player_1, player_2, player_3, player_4));
p->start();
@@ -22,6 +19,7 @@ Game::p Game::create(Player::p player_1, Player::p player_2, Player::p player_3,
Game::~Game() {
std::cout << "Game destroyed." << std::endl;
+ delete ruleset;
}
Game::Game(Player::p player_1, Player::p player_2, Player::p player_3, Player::p player_4) {
@@ -49,253 +47,30 @@ void Game::round_start() {
players[2]->round_start();
players[3]->round_start();
-
- // Sett opp runden sin state
- //game_state = make_shared<State>();
-
- // Simulates drawing 4, 4 ,4 for each player
- for (int i = 0; i < 3; i++) {
- for (int player_num = 0; player_num < 4; player_num++) {
- for (int y = 0; y < 4; y++) {
- game_state.players[player_num].hand.push_back(wall.take_one());
- }
- }
- }
-
- // Simulates the second part of drawing with only 1 tile
- for (int player_num = 0; player_num < 4; player_num++) {
- game_state.players[player_num].hand.push_back(wall.take_one());
- }
-
- std::sort(game_state.players[0].hand.begin(),game_state.players[0].hand.end(), MyDataSortPredicate);
- std::sort(game_state.players[1].hand.begin(),game_state.players[1].hand.end(), MyDataSortPredicate);
- std::sort(game_state.players[2].hand.begin(),game_state.players[2].hand.end(), MyDataSortPredicate);
- std::sort(game_state.players[3].hand.begin(),game_state.players[3].hand.end(), MyDataSortPredicate);
-
-
- most_value_action.type = Action::Pass;
- current_player = 3;
- num_player_actions = 0;
- draw_phase = true;
+ ruleset = new RuleSet::Standard();
+ ruleset->round_start();
round_update();
}
void Game::round_update() {
- char smart = 0;
- // We're in the draw_phase whenever a player draws a tile from the wall
- if(draw_phase) {
- // If the wall is empty (Contains only 14 tiles) when we enter draw phase the round is over.
- if(wall.is_done()) {
- round_end();
- }
-
- // Since we've entered the draw-phase it's the next players turn
- if (current_player == 3) {
- current_player = 0;
- } else {
- current_player++;
- }
-
- #ifdef DEBUG
-
- time_t current_time = std::time(0);
- std::cout << std::ctime(&current_time) << " - Waiting for action from player: " << current_player << std::endl;
-
- #endif
-
- // Let's take a tile
- Tile from_wall = wall.take_one();
-
- // We then add the tile to the current players hand
- game_state.players[current_player].hand.push_back(from_wall);
-
- // Need to sort again.
- std::sort(game_state.players[current_player].hand.begin(),game_state.players[current_player].hand.end(), MyDataSortPredicate);
-
- // Construct the discard action that the player can do.
- Action discard;
- discard.type = Action::Discard;
- discard.player = current_player;
-
-
- game_state.possible_actions.push_back(discard);
-
- //num_player_actions++;
-
- // Enter the discard phase next loop;
- draw_phase = false;
- smart = smart | (1 << current_player);
- } else {
- //We chwck to see if player can chi from last discard
-
-
- int temp_next_player;
- if (current_player == 3) {
- temp_next_player = 0;
- } else {
- temp_next_player = current_player + 1;
- }
-
- Tiles* pond = &game_state.players[current_player].pond;
- Tile temp_tile = pond->back();
- Tiles::iterator it;
- Tile* tile_2u = NULL;
- Tile* tile_1u = NULL;
- Tile* tile_1o = NULL;
- Tile* tile_2o = NULL;
- unsigned int count = 0, tile_2u_id,tile_1u_id,tile_1o_id,tile_2o_id;
- Tile::Type check_tile;
- for(it = game_state.players[temp_next_player].hand.begin(); it != game_state.players[temp_next_player].hand.end(); ++it) {
- #ifdef DEBUG
- Tile debug = *it;
- #endif
-
- check_tile = Tile::Type(temp_tile.type - 2);
- if(it->type == check_tile) {
- tile_2u = &(*it);
- tile_2u_id = count;
- }
- check_tile = Tile::Type(temp_tile.type - 1);
- if(it->type == check_tile) {
- tile_1u = &(*it);
- tile_1u_id = count;
- }
- check_tile = Tile::Type(temp_tile.type + 1);
- if(it->type == check_tile) {
- tile_1o = &(*it);
- tile_1o_id = count;
- }
- check_tile = Tile::Type(temp_tile.type + 2);
- if(it->type == check_tile) {
- tile_2o = &(*it);
- tile_2o_id = count;
- }
- count++;
- }
-
- bool chi;
- if(tile_2u && tile_1u) {
- Action temp_action;
- chi = false;
- //Make sure we have a chi within the same series.
- if(tile_2u->type <= Tile::Man_7 && tile_2u->type >= Tile::Man_1) {
- chi = true;
- } else if(tile_2u->type <= Tile::Pin_7 && tile_2u->type >= Tile::Pin_1) {
- chi = true;
- } else if(tile_2u->type <= Tile::Sou_7 && tile_2u->type >= Tile::Sou_1) {
- chi = true;
- }
- if(chi) {
- temp_action.player = temp_next_player;
- temp_action.target = tile_2u_id;
- temp_action.type = Action::Chi;
- game_state.possible_actions.push_back(temp_action);
- #ifdef DEBUG
-
- time_t current_time = std::time(0);
- std::cout << std::ctime(&current_time) << " Player: " << temp_action.player << " Can do action: " << temp_action.type << " On target: " << temp_action.target << std::endl;
-
- #endif
- }
- }
-
- if(tile_1u && tile_1o) {
- Action temp_action;
- chi = false;
- //Make sure we have a chi within the same series.
- if(tile_1u->type <= Tile::Man_7 && tile_1u->type >= Tile::Man_1) {
- chi = true;
- } else if(tile_1u->type <= Tile::Pin_7 && tile_1u->type >= Tile::Pin_1) {
- chi = true;
- } else if(tile_1u->type <= Tile::Sou_7 && tile_1u->type >= Tile::Sou_1) {
- chi = true;
- }
- if(chi) {
- temp_action.player = temp_next_player;
- temp_action.target = tile_1u_id;
- temp_action.type = Action::Chi;
- game_state.possible_actions.push_back(temp_action);
-
- #ifdef DEBUG
-
- time_t current_time = std::time(0);
- std::cout << std::ctime(&current_time) << " Player: " << temp_action.player << " Can do action: " << temp_action.type << " On target: " << temp_action.target << std::endl;
-
- #endif
- }
- }
-
- if(tile_1o && tile_2o) {
- Action temp_action;
- chi = false;
- //Make sure we have a chi within the same series.
- if(temp_tile.type <= Tile::Man_7 && temp_tile.type >= Tile::Man_1) {
- chi = true;
- } else if(temp_tile.type <= Tile::Pin_7 && temp_tile.type >= Tile::Pin_1) {
- chi = true;
- } else if(temp_tile.type <= Tile::Sou_7 && temp_tile.type >= Tile::Sou_1) {
- chi = true;
- }
- if(chi) {
- temp_action.player = temp_next_player;
- temp_action.target = tile_1o_id;
- temp_action.type = Action::Chi;
- game_state.possible_actions.push_back(temp_action);
-
- #ifdef DEBUG
-
- time_t current_time = std::time(0);
- std::cout << std::ctime(&current_time) << " Player: " << temp_action.player << " Can do action: " << temp_action.type << " On target: " << temp_action.target << std::endl;
-
- #endif
- }
- }
-
- //Go back into draw_phase0
- draw_phase = true;
- // Not implemented yet
- for(Actions::iterator it = game_state.possible_actions.begin(); it != game_state.possible_actions.end(); ++it) {
- smart = smart | (0x0001 << it->player);
- }
-
- if(smart & 1) {
- Action pass;
- pass.type = Action::Pass;
- pass.player = 0;
- game_state.possible_actions.push_back(pass);
- }
- if(smart & 2) {
- Action pass;
- pass.type = Action::Pass;
- pass.player = 1;
- game_state.possible_actions.push_back(pass);
- }
- if(smart & 4) {
- Action pass;
- pass.type = Action::Pass;
- pass.player = 2;
- game_state.possible_actions.push_back(pass);
- }
- if(smart & 8) {
- Action pass;
- pass.type = Action::Pass;
- pass.player = 3;
- game_state.possible_actions.push_back(pass);
- }
- }
-
+ State gamestate = ruleset->round_update();
// Send the updates state to the players
- players[0]->round_state(game_state);
- players[1]->round_state(game_state);
- players[2]->round_state(game_state);
- players[3]->round_state(game_state);
+ players[0]->round_state(gamestate);
+ players[1]->round_state(gamestate);
+ players[2]->round_state(gamestate);
+ players[3]->round_state(gamestate);
// 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);
+ }
+
+ int num_player_actions = 0;
if(smart & 1) {
num_player_actions++;
@@ -321,156 +96,13 @@ void Game::round_update() {
void Game::handle_action(Action action) {
- players[action.player]->kill_action();
-
- #ifdef DEBUG
-
- time_t current_time = std::time(0);
- std::cout << std::ctime(&current_time) << " Player: " << action.player << " Did action: " << action.type << " On target: " << action.target << std::endl;
-
- #endif
+ //players[action.player]->kill_action();
- // Lots of actions to test if the player doing the action is allowed to do it
-
- // Check if we're actually waiting for actions.
- if (game_state.possible_actions.empty()) {
- return;
- }
-
- // Check if the player is allowed to do this action
- bool found_action = false;
-
- for(Actions::iterator it = game_state.possible_actions.begin(); it != game_state.possible_actions.end(); ++it) {
- if(it->player == action.player && it->type == action.type) {
- found_action = true;
- }
- }
-
- if(!found_action) {
- return;
- }
+ bool done = ruleset->round_action(action);
- switch ( action.type ) {
-
- case Action::Pass: {
-
- } break;
-
- case Action::Discard: {
- Tile discarded_tile = game_state.players[action.player].hand[action.target];
- game_state.players[action.player].pond.push_back(discarded_tile);
- game_state.players[action.player].hand.erase(game_state.players[action.player].hand.begin() + action.target);
-
- } break;
-
- case Action::Riichi: {
-
- } break;
-
- case Action::Chi: {
- if(most_value_action.type != Action::Pon && most_value_action.type != Action::Kan && most_value_action.type != Action::Ron) {
- most_value_action = action;
- }
- } break;
-
- case Action::Pon: {
- if(most_value_action.type != Action::Ron) {
- most_value_action = action;
- }
- } break;
-
- case Action::Kan: {
-
- } break;
-
- case Action::Ron: {
-
- } break;
-
- case Action::Tsumo: {
-
- } break;
-
- case Action::Draw: {
-
- } break;
-
- default:
- break;
- }
-
-
- num_player_actions--;
-
- // Remove all the actions that this player could do since he now did one.
-
- std::vector<int> positions;
- int position = 0;
- for(Actions::iterator it = game_state.possible_actions.begin(); it != game_state.possible_actions.end(); ++it) {
- if (it->player == action.player) {
- positions.push_back(position);
- }
- position++;
- }
- if (!positions.empty()) {
- int found = 0;
- for(std::vector<int>::iterator it = positions.begin(); it != positions.end(); ++it) {
- game_state.possible_actions.erase(game_state.possible_actions.begin() + (*it - found));
- found++;
- }
- }
-
- //When everyone has done their action we empty the list (just to be sure) and then do a round_update()
- if(num_player_actions == 0) {
- game_state.possible_actions.empty();
-
- if(most_value_action.type != Action::Pass) {
- switch (most_value_action.type) {
- case Action::Chi: {
- Set chi;
- Tile left_tile = game_state.players[current_player].pond.back();
- left_tile.rotated = true;
- chi.add_tile(left_tile);
-
- Tile middle_tile = game_state.players[action.player].hand[action.target];
- chi.add_tile(middle_tile);
-
- Tile right_tile;
- if(Tile::Type(game_state.players[action.player].hand[action.target].type + 1) == left_tile.type) {
- right_tile = game_state.players[action.player].hand[action.target + 2];
- } else {
- right_tile = game_state.players[action.player].hand[action.target + 1];
- }
- chi.add_tile(right_tile);
-
- game_state.players[action.player].open.push_back(chi);
- game_state.players[action.player].hand.erase(game_state.players[action.player].hand.begin() + action.target);
- game_state.players[action.player].hand.erase(game_state.players[action.player].hand.begin() + action.target);
-
-
- } break;
-
- case Action::Pon: {
-
- } break;
-
- case Action::Kan: {
-
- } break;
-
- case Action::Ron: {
-
- } break;
-
- default: break;
- }
-
- most_value_action.type = Action::Pass;
- }
-
+ if(done) {
round_update();
}
-
// Sjekk action, sjekk om endelig action er avgjort
// Oppdater state
// Evt. round_end()
diff --git a/server/game.h b/server/game.h
index f88ffd4..f0f1564 100644
--- a/server/game.h
+++ b/server/game.h
@@ -10,6 +10,9 @@
#include "player.h"
#include "../common/action.h"
+#include "gamevariant.h"
+#include "standard.h"
+
class Game : public boost::enable_shared_from_this<Game> {
public:
typedef boost::shared_ptr<Game> p;
@@ -25,23 +28,7 @@ class Game : public boost::enable_shared_from_this<Game> {
Game(Player::p player_1, Player::p player_2, Player::p player_3, Player::p player_4);
- //! The wall that belongs to this game
- Wall wall;
-
- //! The current state of the game
- State game_state;
-
- //! Current player, used when discarding etc
- int current_player;
-
- //! Are we in draw or discard phase?
- bool draw_phase;
-
- //! Number of players doing action
- int num_player_actions;
-
- //! Highest value action done
- Action most_value_action;
+ GameVariant *ruleset;
//! Handle Ready message from player.
void handle_ready();
diff --git a/server/gamevariant.h b/server/gamevariant.h
new file mode 100644
index 0000000..6fb2c56
--- /dev/null
+++ b/server/gamevariant.h
@@ -0,0 +1,20 @@
+#ifndef GAMEVARIANT_H
+#define GAMEVARIANT_H
+
+#include "../common/state.h"
+#include "../common/action.h"
+
+class GameVariant {
+ private:
+ State game_state;
+
+ public:
+ virtual ~GameVariant(){};
+
+ virtual void round_start() = 0;
+ virtual State& round_update() = 0;
+ virtual bool round_action(Action action) = 0;
+};
+
+#endif // GAMEVARIANT_H
+
diff --git a/server/standard.cpp b/server/standard.cpp
new file mode 100644
index 0000000..a45c018
--- /dev/null
+++ b/server/standard.cpp
@@ -0,0 +1,418 @@
+#include "standard.h"
+
+#include <algorithm>
+
+#ifdef DEBUG
+#include <ctime>
+#include <iostream>
+#endif
+
+using namespace RuleSet;
+bool MyDataSortPredicate(const Tile& d1, const Tile& d2) {
+ return d1.type < d2.type;
+}
+
+void Standard::round_start() {
+
+ // Sett opp runden sin state
+ //game_state = make_shared<State>();
+
+ // Simulates drawing 4, 4 ,4 for each player
+ for (int i = 0; i < 3; i++) {
+ for (int player_num = 0; player_num < 4; player_num++) {
+ for (int y = 0; y < 4; y++) {
+ game_state.players[player_num].hand.push_back(wall.take_one());
+ }
+ }
+ }
+
+ // Simulates the second part of drawing with only 1 tile
+ for (int player_num = 0; player_num < 4; player_num++) {
+ game_state.players[player_num].hand.push_back(wall.take_one());
+ }
+
+ std::sort(game_state.players[0].hand.begin(),game_state.players[0].hand.end(), MyDataSortPredicate);
+ std::sort(game_state.players[1].hand.begin(),game_state.players[1].hand.end(), MyDataSortPredicate);
+ std::sort(game_state.players[2].hand.begin(),game_state.players[2].hand.end(), MyDataSortPredicate);
+ std::sort(game_state.players[3].hand.begin(),game_state.players[3].hand.end(), MyDataSortPredicate);
+
+
+ most_value_action.type = Action::Pass;
+ current_player = 3;
+ num_player_actions = 0;
+ draw_phase = true;
+
+}
+
+
+State& Standard::round_update() {
+ char smart = 0;
+ // We're in the draw_phase whenever a player draws a tile from the wall
+ if(draw_phase) {
+ // If the wall is empty (Contains only 14 tiles) when we enter draw phase the round is over.
+
+ // Since we've entered the draw-phase it's the next players turn
+ if (current_player == 3) {
+ current_player = 0;
+ } else {
+ current_player++;
+ }
+
+ #ifdef DEBUG
+
+ time_t current_time = std::time(0);
+ std::cout << std::ctime(&current_time) << " - Waiting for action from player: " << current_player << std::endl;
+
+ #endif
+
+ // Let's take a tile
+ Tile from_wall = wall.take_one();
+
+ // We then add the tile to the current players hand
+ game_state.players[current_player].hand.push_back(from_wall);
+
+ // Need to sort again.
+ std::sort(game_state.players[current_player].hand.begin(),game_state.players[current_player].hand.end(), MyDataSortPredicate);
+
+ // Construct the discard action that the player can do.
+ Action discard;
+ discard.type = Action::Discard;
+ discard.player = current_player;
+
+
+ game_state.possible_actions.push_back(discard);
+
+ //num_player_actions++;
+
+ // Enter the discard phase next loop;
+ draw_phase = false;
+ smart = smart | (1 << current_player);
+ } else {
+ //We chwck to see if player can chi from last discard
+
+
+ int temp_next_player;
+ if (current_player == 3) {
+ temp_next_player = 0;
+ } else {
+ temp_next_player = current_player + 1;
+ }
+
+ Tiles* pond = &game_state.players[current_player].pond;
+ Tile temp_tile = pond->back();
+ Tiles::iterator it;
+ Tile* tile_2u = NULL;
+ Tile* tile_1u = NULL;
+ Tile* tile_1o = NULL;
+ Tile* tile_2o = NULL;
+ unsigned int count = 0, tile_2u_id,tile_1u_id,tile_1o_id,tile_2o_id;
+ Tile::Type check_tile;
+ for(it = game_state.players[temp_next_player].hand.begin(); it != game_state.players[temp_next_player].hand.end(); ++it) {
+ #ifdef DEBUG
+ Tile debug = *it;
+ #endif
+
+ check_tile = Tile::Type(temp_tile.type - 2);
+ if(it->type == check_tile) {
+ tile_2u = &(*it);
+ tile_2u_id = count;
+ }
+ check_tile = Tile::Type(temp_tile.type - 1);
+ if(it->type == check_tile) {
+ tile_1u = &(*it);
+ tile_1u_id = count;
+ }
+ check_tile = Tile::Type(temp_tile.type + 1);
+ if(it->type == check_tile) {
+ tile_1o = &(*it);
+ tile_1o_id = count;
+ }
+ check_tile = Tile::Type(temp_tile.type + 2);
+ if(it->type == check_tile) {
+ tile_2o = &(*it);
+ tile_2o_id = count;
+ }
+ count++;
+ }
+
+ bool chi;
+ if(tile_2u && tile_1u) {
+ Action temp_action;
+ chi = false;
+ //Make sure we have a chi within the same series.
+ if(tile_2u->type <= Tile::Man_7 && tile_2u->type >= Tile::Man_1) {
+ chi = true;
+ } else if(tile_2u->type <= Tile::Pin_7 && tile_2u->type >= Tile::Pin_1) {
+ chi = true;
+ } else if(tile_2u->type <= Tile::Sou_7 && tile_2u->type >= Tile::Sou_1) {
+ chi = true;
+ }
+ if(chi) {
+ temp_action.player = temp_next_player;
+ temp_action.target = tile_2u_id;
+ temp_action.type = Action::Chi;
+ game_state.possible_actions.push_back(temp_action);
+ #ifdef DEBUG
+
+ time_t current_time = std::time(0);
+ std::cout << std::ctime(&current_time) << " Player: " << temp_action.player << " Can do action: " << temp_action.type << " On target: " << temp_action.target << std::endl;
+
+ #endif
+ }
+ }
+
+ if(tile_1u && tile_1o) {
+ Action temp_action;
+ chi = false;
+ //Make sure we have a chi within the same series.
+ if(tile_1u->type <= Tile::Man_7 && tile_1u->type >= Tile::Man_1) {
+ chi = true;
+ } else if(tile_1u->type <= Tile::Pin_7 && tile_1u->type >= Tile::Pin_1) {
+ chi = true;
+ } else if(tile_1u->type <= Tile::Sou_7 && tile_1u->type >= Tile::Sou_1) {
+ chi = true;
+ }
+ if(chi) {
+ temp_action.player = temp_next_player;
+ temp_action.target = tile_1u_id;
+ temp_action.type = Action::Chi;
+ game_state.possible_actions.push_back(temp_action);
+
+ #ifdef DEBUG
+
+ time_t current_time = std::time(0);
+ std::cout << std::ctime(&current_time) << " Player: " << temp_action.player << " Can do action: " << temp_action.type << " On target: " << temp_action.target << std::endl;
+
+ #endif
+ }
+ }
+
+ if(tile_1o && tile_2o) {
+ Action temp_action;
+ chi = false;
+ //Make sure we have a chi within the same series.
+ if(temp_tile.type <= Tile::Man_7 && temp_tile.type >= Tile::Man_1) {
+ chi = true;
+ } else if(temp_tile.type <= Tile::Pin_7 && temp_tile.type >= Tile::Pin_1) {
+ chi = true;
+ } else if(temp_tile.type <= Tile::Sou_7 && temp_tile.type >= Tile::Sou_1) {
+ chi = true;
+ }
+ if(chi) {
+ temp_action.player = temp_next_player;
+ temp_action.target = tile_1o_id;
+ temp_action.type = Action::Chi;
+ game_state.possible_actions.push_back(temp_action);
+
+ #ifdef DEBUG
+
+ time_t current_time = std::time(0);
+ std::cout << std::ctime(&current_time) << " Player: " << temp_action.player << " Can do action: " << temp_action.type << " On target: " << temp_action.target << std::endl;
+
+ #endif
+ }
+ }
+
+ //Go back into draw_phase0
+ draw_phase = true;
+ // Not implemented yet
+
+ for(Actions::iterator it = game_state.possible_actions.begin(); it != game_state.possible_actions.end(); ++it) {
+ smart = smart | (0x0001 << it->player);
+ }
+
+ if(smart & 1) {
+ Action pass;
+ pass.type = Action::Pass;
+ pass.player = 0;
+ game_state.possible_actions.push_back(pass);
+ }
+ if(smart & 2) {
+ Action pass;
+ pass.type = Action::Pass;
+ pass.player = 1;
+ game_state.possible_actions.push_back(pass);
+ }
+ if(smart & 4) {
+ Action pass;
+ pass.type = Action::Pass;
+ pass.player = 2;
+ game_state.possible_actions.push_back(pass);
+ }
+ if(smart & 8) {
+ Action pass;
+ pass.type = Action::Pass;
+ pass.player = 3;
+ game_state.possible_actions.push_back(pass);
+ }
+ }
+
+ for(Actions::iterator it = game_state.possible_actions.begin(); it != game_state.possible_actions.end(); ++it) {
+ smart = smart | (1 << it->player);
+ }
+
+ if(smart & 1) {
+ num_player_actions++;
+ }
+ if(smart & 2) {
+ num_player_actions++;
+ }
+ if(smart & 4) {
+ num_player_actions++;
+ }
+ if(smart & 8) {
+ num_player_actions++;
+ }
+
+ return game_state;
+}
+
+bool Standard::round_action(Action action) {
+ #ifdef DEBUG
+
+ time_t current_time = std::time(0);
+ std::cout << std::ctime(&current_time) << " Player: " << action.player << " Did action: " << action.type << " On target: " << action.target << std::endl;
+
+ #endif
+
+ // Lots of actions to test if the player doing the action is allowed to do it
+
+ // Check if we're actually waiting for actions.
+ if (game_state.possible_actions.empty()) {
+ return false;
+ }
+
+ // Check if the player is allowed to do this action
+ bool found_action = false;
+
+ for(Actions::iterator it = game_state.possible_actions.begin(); it != game_state.possible_actions.end(); ++it) {
+ if(it->player == action.player && it->type == action.type) {
+ found_action = true;
+ }
+ }
+
+ if(!found_action) {
+ return false;
+ }
+
+ switch ( action.type ) {
+
+ case Action::Pass: {
+
+ } break;
+
+ case Action::Discard: {
+ Tile discarded_tile = game_state.players[action.player].hand[action.target];
+ game_state.players[action.player].pond.push_back(discarded_tile);
+ game_state.players[action.player].hand.erase(game_state.players[action.player].hand.begin() + action.target);
+
+ } break;
+
+ case Action::Riichi: {
+
+ } break;
+
+ case Action::Chi: {
+ if(most_value_action.type != Action::Pon && most_value_action.type != Action::Kan && most_value_action.type != Action::Ron) {
+ most_value_action = action;
+ }
+ } break;
+
+ case Action::Pon: {
+ if(most_value_action.type != Action::Ron) {
+ most_value_action = action;
+ }
+ } break;
+
+ case Action::Kan: {
+
+ } break;
+
+ case Action::Ron: {
+
+ } break;
+
+ case Action::Tsumo: {
+
+ } break;
+
+ case Action::Draw: {
+
+ } break;
+
+ default:
+ break;
+ }
+
+
+ num_player_actions--;
+
+ // Remove all the actions that this player could do since he now did one.
+
+ std::vector<int> positions;
+ int position = 0;
+ for(Actions::iterator it = game_state.possible_actions.begin(); it != game_state.possible_actions.end(); ++it) {
+ if (it->player == action.player) {
+ positions.push_back(position);
+ }
+ position++;
+ }
+ if (!positions.empty()) {
+ int found = 0;
+ for(std::vector<int>::iterator it = positions.begin(); it != positions.end(); ++it) {
+ game_state.possible_actions.erase(game_state.possible_actions.begin() + (*it - found));
+ found++;
+ }
+ }
+
+ //When everyone has done their action we empty the list (just to be sure) and then do a round_update()
+ if(num_player_actions == 0) {
+ game_state.possible_actions.empty();
+
+ if(most_value_action.type != Action::Pass) {
+ switch (most_value_action.type) {
+ case Action::Chi: {
+ Set chi;
+ Tile left_tile = game_state.players[current_player].pond.back();
+ left_tile.rotated = true;
+ chi.add_tile(left_tile);
+
+ Tile middle_tile = game_state.players[action.player].hand[action.target];
+ chi.add_tile(middle_tile);
+
+ Tile right_tile;
+ if(Tile::Type(game_state.players[action.player].hand[action.target].type + 1) == left_tile.type) {
+ right_tile = game_state.players[action.player].hand[action.target + 2];
+ } else {
+ right_tile = game_state.players[action.player].hand[action.target + 1];
+ }
+ chi.add_tile(right_tile);
+
+ game_state.players[action.player].open.push_back(chi);
+ game_state.players[action.player].hand.erase(game_state.players[action.player].hand.begin() + action.target);
+ game_state.players[action.player].hand.erase(game_state.players[action.player].hand.begin() + action.target);
+
+
+ } break;
+
+ case Action::Pon: {
+
+ } break;
+
+ case Action::Kan: {
+
+ } break;
+
+ case Action::Ron: {
+
+ } break;
+
+ default: break;
+ }
+ most_value_action.type = Action::Pass;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/server/standard.h b/server/standard.h
new file mode 100644
index 0000000..de81e7f
--- /dev/null
+++ b/server/standard.h
@@ -0,0 +1,37 @@
+#ifndef STANDARD_H
+#define STANDARD_H
+
+#include "gamevariant.h"
+
+#include "wall.h"
+#include "../common/set.h"
+
+namespace RuleSet {
+ class Standard : public GameVariant {
+ private:
+ //! The wall that belongs to this game
+ Wall wall;
+
+ //! The current state of the game
+ State game_state;
+
+ //! Current player, used when discarding etc
+ int current_player;
+
+ //! Are we in draw or discard phase?
+ bool draw_phase;
+
+ //! Number of players doing action
+ int num_player_actions;
+
+ //! Highest value action done
+ Action most_value_action;
+
+ public:
+ virtual void round_start();
+ virtual State& round_update();
+ virtual bool round_action(Action action);
+ };
+};
+#endif // STANDARD_H
+