summaryrefslogtreecommitdiff
path: root/server/standard.cpp
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 /server/standard.cpp
parent56e4891bcdd693cfba540aec186f151012d96870 (diff)
Moved lots of code in Game out into a separate class.
Signed-off-by: Atle Hellvik Havsø <atle@havso.net>
Diffstat (limited to 'server/standard.cpp')
-rw-r--r--server/standard.cpp418
1 files changed, 418 insertions, 0 deletions
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;
+ }
+}