From e82316cb64f759917c00a63a1b8e02da25b0343f Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Sat, 11 Dec 2010 05:29:09 +0100 Subject: Add Hand::get_breakdowns() and extend eat_*() to support it. --- server/hand.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- server/hand.h | 8 ++++++ 2 files changed, 95 insertions(+), 1 deletion(-) (limited to 'server') diff --git a/server/hand.cpp b/server/hand.cpp index 07777fb..bc4fb7a 100644 --- a/server/hand.cpp +++ b/server/hand.cpp @@ -8,6 +8,14 @@ bool Hand::tenpai(const Tiles& tiles) { return basic_format_tenpai(tiles); } +List Hand::get_breakdowns(const Tiles& tiles) { + List hands; + + basic_format(tiles, hands); + + return hands; +} + bool Hand::basic_format(const Tiles& tiles, bool pair_eaten) { if(!tiles) { return true; // All tiles eaten. @@ -39,6 +47,40 @@ bool Hand::basic_format(const Tiles& tiles, bool pair_eaten) { return false; } +void Hand::basic_format(const Tiles& tiles, List& hands, const Sets& hand, bool pair_eaten) { + if(!tiles) { + hands.push_back(hand); + return; // All tiles eaten. + } + + Tiles rest; + Sets new_hand; + + if(!pair_eaten) { + rest = tiles; + new_hand = hand; + if(eat_pair(rest, new_hand)) { + basic_format(rest, hands, new_hand, true); + } + } + + if(tiles.size() < 3) { + return; + } + + rest = tiles; + new_hand = hand; + if(eat_pon(rest, new_hand)) { + basic_format(rest, hands, new_hand, pair_eaten); + } + + rest = tiles; + new_hand = hand; + if(eat_chi(rest, new_hand)) { + basic_format(rest, hands, new_hand, pair_eaten); + } +} + bool Hand::basic_format_tenpai(const Tiles& tiles, bool pair_eaten, bool wait_eaten) { if(!tiles) { return true; @@ -132,6 +174,15 @@ bool Hand::eat_pair(Tiles& tiles) { return false; } +bool Hand::eat_pair(Tiles& tiles, Sets& hand) { + if(tiles[0] == tiles[1]) { + hand.push_back(Set(Set::Pair, Tiles(tiles.begin(), tiles.begin() + 2), false)); + tiles.erase(tiles.begin(), tiles.begin() + 2); + return true; + } + return false; +} + bool Hand::eat_pon(Tiles& tiles) { if(tiles[0] == tiles[2]) { tiles.erase(tiles.begin(), tiles.begin() + 3); @@ -140,6 +191,15 @@ bool Hand::eat_pon(Tiles& tiles) { return false; } +bool Hand::eat_pon(Tiles& tiles, Sets& hand) { + if(tiles[0] == tiles[2]) { + hand.push_back(Set(Set::Pon, Tiles(tiles.begin(), tiles.begin() + 3), false)); + tiles.erase(tiles.begin(), tiles.begin() + 3); + return true; + } + return false; +} + bool Hand::eat_chi(Tiles& tiles) { Tile::Set set = tiles.front().get_set(); int num = tiles.front().get_num(); @@ -163,4 +223,30 @@ bool Hand::eat_chi(Tiles& tiles) { return false; } - +bool Hand::eat_chi(Tiles& tiles, Sets& hand) { + Tile::Set set = tiles.front().get_set(); + int num = tiles.front().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 chi; + chi.push_back(tiles.front()); + chi.push_back(*it1); + chi.push_back(*it2); + hand.push_back(Set(Set::Chi, chi, false)); + tiles.erase(it2); + tiles.erase(it1); + tiles.erase(tiles.begin()); + return true; + } + } + return false; +} diff --git a/server/hand.h b/server/hand.h index 879bc8d..b7ae8d2 100644 --- a/server/hand.h +++ b/server/hand.h @@ -2,6 +2,7 @@ #define HAND_H #include "../common/tile.h" +#include "../common/set.h" namespace Hand { //! Check if the tiles constitute a complete hand. Also valid for the concealed part of an open hand. @@ -10,8 +11,12 @@ namespace Hand { //! Check if the tiles miss only one from constituting a complete hand. Also valid for the concealed part of an open hand. bool tenpai(const Tiles& tiles); + //! Get list of possible breakdowns of a complete hand. + List get_breakdowns(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); + void basic_format(const Tiles& tiles, List& hands, const Sets& hand = Sets(), bool pair_eaten = false); // Check if the tiles is matching the normal format but missing one. bool basic_format_tenpai(const Tiles& tiles, bool pair_eaten = false, bool wait_eaten = false); @@ -24,12 +29,15 @@ namespace Hand { // Eat a pair from beginning of list if possible and return success flag. bool eat_pair(Tiles& tiles); + bool eat_pair(Tiles& tiles, Sets& hand); // Eat a pon from beginning of list if possible and return success flag. bool eat_pon(Tiles& tiles); + bool eat_pon(Tiles& tiles, Sets& hand); // Eat a chi from beginning of list if possible and return success flag. bool eat_chi(Tiles& tiles); + bool eat_chi(Tiles& tiles, Sets& hand); } #endif -- cgit v1.2.3