From 44e1ff4182f6983f2f363f12ff12970749ae8b46 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Wed, 1 Dec 2010 15:23:25 +0100 Subject: Move hand calculations to a new file. --- server/hand.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ server/hand.h | 23 +++++++++++++++++ server/player.cpp | 55 +++------------------------------------- 3 files changed, 103 insertions(+), 51 deletions(-) create mode 100644 server/hand.cpp create mode 100644 server/hand.h (limited to 'server') diff --git a/server/hand.cpp b/server/hand.cpp new file mode 100644 index 0000000..393a6c0 --- /dev/null +++ b/server/hand.cpp @@ -0,0 +1,76 @@ +#include "hand.h" + +bool Hand::agari(const Tiles& tiles) { + return basic_format(tiles); +} + +bool Hand::basic_format(const Tiles& tiles, bool pair_eaten) { + if(!tiles) { + return true; // All tiles eaten. + } + + if(!pair_eaten) { + if(Tiles rest = eat_pair(tiles)) { + if(basic_format(rest, true)) { + return true; + } + } + } + + if(tiles.size() < 3) { + return false; + } + + if(Tiles rest = eat_pon(tiles)) { + if(basic_format(rest, pair_eaten)) { + return true; + } + } + + if(Tiles rest = eat_chi(tiles)) { + return basic_format(rest, pair_eaten); + } + + return false; +} + +Tiles Hand::eat_pair(Tiles tiles) { + if(tiles[0] == tiles[1]) { + tiles.erase(tiles.begin(), tiles.begin() + 2); + return tiles; + } + return Tiles(); +} + +Tiles Hand::eat_pon(Tiles tiles) { + if(tiles[0] == tiles[2]) { + tiles.erase(tiles.begin(), tiles.begin() + 3); + return tiles; + } + return Tiles(); +} + +Tiles Hand::eat_chi(Tiles tiles) { + Tile::Set set = tiles[0].get_set(); + int num = tiles[0].get_num(); + + if(set == Tile::Honor || num > 7) { + // Can't be chi-ed. + return Tiles(); + } + + Tiles::iterator it1 = std::find(tiles.begin(), tiles.end(), Tile(set, num + 1)); + if(it1 != tiles.end()) { + Tiles::iterator it2 = std::find(tiles.begin(), tiles.end(), Tile(set, num + 2)); + if(it2 != tiles.end()) { + // We can eat a chi of tiles. + tiles.erase(it2); + tiles.erase(it1); + tiles.erase(tiles.begin()); + return tiles; + } + } + return Tiles(); +} + + diff --git a/server/hand.h b/server/hand.h new file mode 100644 index 0000000..46ae40a --- /dev/null +++ b/server/hand.h @@ -0,0 +1,23 @@ +#ifndef HAND_H +#define HAND_H + +#include "../common/tile.h" + +namespace Hand { + //! Check if the tiles constitute a complete hand. Also valid for the concealed part of an open hand. + bool agari(const Tiles& tiles); + + // Check if the tiles is matching the normal format of one pair and rest triplets. + bool basic_format(const Tiles& tiles, bool pair_eaten = false); + + // Eat a pair from beginning of list if possible and return rest, else return empty list. + Tiles eat_pair(Tiles tiles); + + // Eat a pon from beginning of list if possible and return rest, else return empty list. + Tiles eat_pon(Tiles tiles); + + // Eat a chi from beginning of list if possible and return rest, else return empty list. + Tiles eat_chi(Tiles tiles); +} + +#endif diff --git a/server/player.cpp b/server/player.cpp index 61f5831..4407095 100644 --- a/server/player.cpp +++ b/server/player.cpp @@ -1,5 +1,7 @@ #include "game.h" +#include "hand.h" + void Game::Player::round_start() { // Reset contents. hand.clear(); @@ -151,64 +153,15 @@ bool Game::Player::can_kan(Tile tile, int target) { return false; } -//! Recursive function that eats away sets from a hand to determine if it's valid or not. -bool complete_hand(Tiles tiles, bool pair_eaten = false) { - if(!tiles) { - return true; // All tiles eaten. - } - - if(tiles[0] == tiles[1]) { - if(!pair_eaten) { - // We can eat a pair of tiles. - Tiles t = tiles; - t.erase(t.begin(), t.begin() + 2); - if(complete_hand(t, true)) { - return true; - } - } - - if(tiles[1] == tiles[2]) { - // We can eat a pon of tiles. - Tiles t = tiles; - t.erase(t.begin(), t.begin() + 3); - if(complete_hand(t, pair_eaten)) { - return true; - } - } - } - - Tile::Set set = tiles[0].get_set(); - int num = tiles[0].get_num(); - - if(set == Tile::Honor || num > 7) { - // Can't be chi-ed. - return false; - } - - Tiles::iterator it1 = std::find(tiles.begin(), tiles.end(), Tile(set, num + 1)); - if(it1 != tiles.end()) { - Tiles::iterator it2 = std::find(tiles.begin(), tiles.end(), Tile(set, num + 2)); - if(it2 != tiles.end()) { - // We can eat a chi of tiles. - tiles.erase(it2); - tiles.erase(it1); - tiles.erase(tiles.begin()); - return complete_hand(tiles, pair_eaten); - } - } - - return false; -} - bool Game::Player::can_tsumo() { - return complete_hand(hand); + return Hand::agari(hand); } bool Game::Player::can_ron(Tile tile) { Tiles tiles = hand; tiles.push_back(tile); tiles.sort(); - return complete_hand(tiles); + return Hand::agari(tiles); } void Game::Player::draw(Tile tile) { -- cgit v1.2.3