diff options
Diffstat (limited to 'server/game.cpp')
| -rw-r--r-- | server/game.cpp | 456 | 
1 files changed, 0 insertions, 456 deletions
| diff --git a/server/game.cpp b/server/game.cpp deleted file mode 100644 index e791379..0000000 --- a/server/game.cpp +++ /dev/null @@ -1,456 +0,0 @@ -#include "game.h" - -#include <boost/bind.hpp> - -#include <iostream> -#include <algorithm> -#include <map> - -#ifdef DEBUG -#include <ctime> -#endif - -Game::p Game::create(ClientBase::p player_1, ClientBase::p player_2, ClientBase::p player_3, ClientBase::p player_4) { -	Game::p p(new Game(player_1, player_2, player_3, player_4)); -	p->start(); -	return p; -} - -Game::~Game() { -	std::cout << "Game destroyed." << std::endl; -} - -Game::Game(ClientBase::p player_1, ClientBase::p player_2, ClientBase::p player_3, ClientBase::p 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() { -	if(--awaiting_players) { -		return; -	} -	 -	std::cout << "All ready!" << std::endl; -	 -	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; -	 -	round_wind = 0; -	round_num = 0; -	 -	awaiting_players = 4; -	 -	std::vector<std::string> pl; -	 -	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); -	 -	pl.erase(pl.begin()); -	pl.push_back(players[0].client->nick()); -	players[1].client->game_start(boost::bind(&Game::handle_ready, shared_from_this()), pl); -	 -	pl.erase(pl.begin()); -	pl.push_back(players[1].client->nick()); -	players[2].client->game_start(boost::bind(&Game::handle_ready, shared_from_this()), pl); -	 -	pl.erase(pl.begin()); -	pl.push_back(players[2].client->nick()); -	players[3].client->game_start(boost::bind(&Game::handle_ready, shared_from_this()), pl); -} - -void Game::round_start() { -	std::cout << "Starting a new round." << std::endl; -	 -	// Build a new wall. -	wall.build(); -	 -	// Clear previous dora and draw a new. -	dora.clear(); -	dora.push_back(wall.take_one()); -	 -	kan_dora_pending = false; -	 -	// Notify players of round start. -	// TODO: Tell them where wall is broken. -	players[0].round_start(-round_num); -	players[1].round_start(-round_num + 1); -	players[2].round_start(-round_num + 2); -	players[3].round_start(-round_num + 3); -	 -	// 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()); -	} -	 -	// 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(); -	 -	// Construct and send state to each client. -	PlayerNum player = 0; -	do { -		PlayerState state[4]; -		 -		state[0] = players[player].get_state(); -		state[1] = players[player + 1].get_state_filtered(); -		state[2] = players[player + 2].get_state_filtered(); -		state[3] = players[player + 3].get_state_filtered(); -		 -		Actions a; -		if(player == current_player) { -			a = possible_actions; -		} -		 -		GameState gstate = {dora, current_player - player, round_wind, round_num, 0, 0}; -		 -		players[player].client->round_state(state[0], state[1], state[2], state[3], gstate, a); -	} while(++player); -	 -	// 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(); -	 -	std::map<int, Actions> possible_actions; -	 -	// Construct and send state to each client. -	PlayerNum player = 0; -	do { -		PlayerState state[4]; -		 -		state[0] = players[player].get_state(); -		state[1] = players[player + 1].get_state_filtered(); -		state[2] = players[player + 2].get_state_filtered(); -		state[3] = players[player + 3].get_state_filtered(); -		 -		Actions a; -		if(player != current_player) { -			if(a = players[player].get_actions_discard(discarded_tile, current_player - player)) { -				possible_actions[player] = a; -			} -		} -		 -		GameState gstate = {dora, current_player - player, round_wind, round_num, 0, 0}; -		 -		players[player].client->round_state(state[0], state[1], state[2], state[3], gstate, a); -	} while(++player); -	 -	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_draw(Action action) { -	switch(action.type) { -		case Action::Discard: { -			players[current_player].discard(action.target_offset); -			if(kan_dora_pending) { -				kan_dora_pending = false; -				dora.push_back(wall.take_one()); -			} -			round_update_discard(); -		} break; -		 -		case Action::Tsumo: { -			players[current_player].declare_tsumo(); -			round_end(Tsumo); -		} break; -		 -		case Action::Riichi: { -			players[current_player].declare_riichi(); -			round_update_draw(); -		} break; -		 -		case Action::Kan: { -			if(action.target_type == Action::Index) { -				players[current_player].make_kan(action.target_offset - 2); -				dora.push_back(wall.take_one()); -			} else { -				players[current_player].make_kan_extend(action.target_offset); -				kan_dora_pending = true; -			} -			players[current_player].draw(wall.take_one()); -			round_update_draw(); -		} break; -		 -		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; -			} -		 -		// First ron. -			if(action.type == Action::Ron) { -				preceding_action = action; -				preceding_action_owner = player; -				break; -			} -		 -		// Multiple ron. -		case Action::Ron: -			if(action.type == Action::Ron && current_player - player > current_player - preceding_action_owner) { -				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; -	} -	 -	if(--awaiting_players) { -		return; -	} -	 -	switch(preceding_action.type) { -		case Action::Pass: { -			// Tile not claimed, next player draws. -			 -			// Check if the wall has run out. -			if(wall.remaining() <= 14) { -				round_end(Draw); -				break; -			} -			 -			players[++current_player].draw(wall.take_one()); -			round_update_draw(); -		} break; -		 -		case Action::Chi: { -			players[preceding_action_owner].make_chi(players[current_player].claim(), preceding_action.target_offset); -			current_player = preceding_action_owner; -			round_update_draw(); -		} break; -		 -		case Action::Pon: { -			players[preceding_action_owner].make_pon(players[current_player].claim(), preceding_action.target_offset - 1, current_player - preceding_action_owner); -			current_player = preceding_action_owner; -			round_update_draw(); -		} break; -		 -		case Action::Kan: { -			players[preceding_action_owner].make_kan(players[current_player].claim(), preceding_action.target_offset - 2, current_player - preceding_action_owner); -			current_player = preceding_action_owner; -			kan_dora_pending = true; -			players[current_player].draw(wall.take_one()); -			round_update_draw(); -		} break; -		 -		case Action::Ron: { -			players[preceding_action_owner].declare_ron(players[current_player].claim()); -			round_end(Ron); -		} break; -		 -		// Will never occur on discard: -		case Action::Discard: -		case Action::Riichi: -		case Action::Tsumo: -		case Action::Draw: -			break; -	} -} - -Tiles merge_hand_open(const Tiles& hand, const Sets& open) { -	Tiles tiles = hand; -	for(Sets::const_iterator it = open.begin(); it != open.end(); it++) { -		tiles.insert(tiles.end(), it->tiles.begin(), it->tiles.end()); -	} -	return tiles; -} - -void Game::round_end(Endcondition end) { -	 -	Message::RoundEnd::p msg[4] = make_shared<Message::RoundEnd>(); -	 -	for(CyclicInt<4> count_player = 0; count_player < 4; count_player++) { -		msg[count_player]->total_han = msg[count_player]->total_fu = msg[count_player]->won = msg[count_player]->score[count_player].won = 0; -		for(int i = 0; i < 4; i++) { -			msg[count_player]->score[count_player + i].score = players[count_player + i].get_state().score; -			msg[count_player]->score[count_player + i].won = 0; -		} -		 -		switch(end) { -			case Draw: -				//msg->total_han = msg->total_fu = msg->won = 0; -				break; -			 -			case Tsumo: { -					Player& player = players[current_player]; -					 -					msg[count_player]->hand = merge_hand_open(player.hand, player.open); -					 -					msg[count_player]->yakus = player.won_han; -					 -					msg[count_player]->total_han = player.won_value.han(); -					msg[count_player]->total_fu = player.won_value.fu_rounded(); -					 -					if(current_player == round_num) { -						msg[count_player]->won = 3 * player.won_value.tsumo_east(); -						 -						for(int y = 0; y < 4; y++) { -							msg[count_player]->score[current_player + y].won = -(msg[count_player]->won / 3); -						} -						msg[count_player]->score[count_player + current_player ].won = msg[count_player]->won; -						 -					} else { -						msg[count_player]->won = player.won_value.tsumo_east() + 2 * player.won_value.tsumo(); -						 -						for(int y = 0; y < 4; y++) { -							if(count_player + y == current_player) { -									msg[count_player]->score[y].won = msg[count_player]->won; -							} else if (count_player + y == round_num){ -									msg[count_player]->score[y].won = -(player.won_value.tsumo_east()); -							} else { -									msg[count_player]->score[y].won = -(player.won_value.tsumo()); -							} -						} -					} -					 -				} break; -			 -			case Ron: -				for(int i = 0; i < 4; i++) { -					if(players[current_player + i].won) { -						Player& player = players[current_player + i]; -						 -						msg[count_player]->hand = merge_hand_open(player.hand, player.open); -						 -						msg[count_player]->yakus = player.won_han; -						 -						msg[count_player]->total_han = player.won_value.han(); -						msg[count_player]->total_fu = player.won_value.fu_rounded(); -						 -						if(current_player + i == round_num) { -							msg[count_player]->won = player.won_value.ron_east(); -							msg[count_player]->score[current_player + i].won = player.won_value.ron_east(); -							msg[count_player]->score[current_player].won = -(player.won_value.ron_east()); - -						} else { -							msg[count_player]->won = player.won_value.ron(); -							msg[count_player]->score[current_player + i].won = player.won_value.ron(); -							msg[count_player]->score[current_player].won = -(player.won_value.ron()); -						} -						 -						// TODO: Support multiple wins. -						break; -					} -				} -				break; -		} -	 -	//Send med score -	msg[count_player]->game_end = false; -	if(count_player == 3) break; -	} -	 -	round_num++; -	 -	if(!round_num) { -		round_wind++; -		//Do a 4-round game for now -		for(int i = 0; i < 4; ++i) { -			msg[i]->game_end = true; -			players[i].client->round_end(msg[i], 0); -		} -		game_end(); -	} else { -		awaiting_players = 4; -		players[0].client->round_end(msg[0], boost::bind(&Game::handle_ready, shared_from_this())); -		players[1].client->round_end(msg[1], boost::bind(&Game::handle_ready, shared_from_this())); -		players[2].client->round_end(msg[2], boost::bind(&Game::handle_ready, shared_from_this())); -		players[3].client->round_end(msg[3], boost::bind(&Game::handle_ready, shared_from_this())); -	} -	 -	// Ferdig? game_end() -} - -void Game::game_end() {	 -	Message::GameEnd::p msg = make_shared<Message::GameEnd>(); -	for(int i = 0; i < 4; i++) { -		msg->scores[i].score = players[i].score; -		msg->scores[i].won = players[i].score - 25000; -	} -	 -	awaiting_players = 4; -	players[0].client->game_end(msg, boost::bind(&Game::handle_ready, shared_from_this())); -	players[1].client->game_end(msg, boost::bind(&Game::handle_ready, shared_from_this())); -	players[2].client->game_end(msg, boost::bind(&Game::handle_ready, shared_from_this())); -	players[3].client->game_end(msg, boost::bind(&Game::handle_ready, shared_from_this())); -	 - -} | 
