From 11e22277288a3d8abad75b0d9963883e1e5a38a1 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Sun, 28 Nov 2010 06:52:41 +0100 Subject: Added simple can_ron() and can_tsumo() tests. No kokushi/chitoi yet. --- server/game.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ server/game.h | 8 ++++++- 2 files changed, 74 insertions(+), 1 deletion(-) (limited to 'server') diff --git a/server/game.cpp b/server/game.cpp index 268439f..65d5cf2 100644 --- a/server/game.cpp +++ b/server/game.cpp @@ -324,6 +324,10 @@ Actions Game::Player::get_actions_draw() { // Check if player can force a draw. // Check if player can tsumo. + if(can_tsumo()) { + possible_actions.push_back(Action(Action::Tsumo)); + } + // Check if player can declare a concealed kan or extend an open pon. List all possibilities. if(!riichi) { @@ -369,6 +373,9 @@ Actions Game::Player::get_actions_discard(Tile tile, PlayerNum discarder) { } // Check if tile can be ron-ed. + if(can_ron(tile)) { + possible_actions.push_back(Action(Action::Ron)); + } // If any action is possible, add option to pass. if(possible_actions) { @@ -442,6 +449,66 @@ 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); +} + +bool Game::Player::can_ron(Tile tile) { + Tiles tiles = hand; + tiles.push_back(tile); + tiles.sort(); + return complete_hand(tiles); +} + void Game::Player::draw(Tile tile) { hand.push_back(tile); } diff --git a/server/game.h b/server/game.h index 5613751..8bf89e8 100644 --- a/server/game.h +++ b/server/game.h @@ -59,9 +59,15 @@ class Game : public boost::enable_shared_from_this { //! Check if it's possible to make a concealed kan or extend an open kan. Targets can_kan(); - // Check if tile can be called to kan target. + //! Check if tile can be called to kan target. bool can_kan(Tile tile, int target); + //! Check if hand is complete. + bool can_tsumo(); + + //! Check if tile can be called to complete hand. + bool can_ron(Tile tile); + //! Draw tile. void draw(Tile tile); -- cgit v1.2.3