au.com.solidsoftware.multimahjong.mmc.game
Class Hand

java.lang.Object
  |
  +--au.com.solidsoftware.multimahjong.mmc.game.Hand

public class Hand
extends java.lang.Object

SRS - 4.3.1, 4.3.2, 4.3.4, 4.3.5, 4.3.6

The Hand class represents the full hand of a player(this includes both concealed and exposed) in the Game of mahjong. All functions that are necessary to maintain, observe and display the hand will be contained in this class. The Hand is re-initialised at the end of each round. After the Wall has been retrieved by the Game, tiles are drawn and inserted into the concealed hand.

During the move selection process a player's Hand will need to be checked to see if it is possible that they can Chow, Pung, Kong or Mahjong with the last discard. The Hand class will contain all these checks, and if the move is determined to have the highest priority it will need to update the hand according to the selection.

Whenever the player must discard, checks need to be made in the concealed hand for the possibility of the DeclareKong or Pung2Kong. These are again contained in the Hand class. Once the discard tile is chosen it will need to be removed from the concealed hand and then will need to check for a Fishing. The checks for both Mahjong and Fishing are conducted by the CombList class. Whenever a new concealed hand is formed the CombList is re-initialised, a new list of combinations produced and the relevant checks made. The check for Mahjong is only necessary at the start of the game(for the east Players initial hand), and whenever a Player is Fishing. Special Mahjong hands will also be included in the checks and if they conform to one of these special types a flag is set in the Payout class.

Author:
Dean Cortinovis

Field Summary
private  boolean allDrawWall
          Flag- True if all tiles except the last was drawn from Wall.
private  int[][] concealedHand
          Concealed hand of a player.
private  Tile[] copyOfHand
          Copy of the concealed hand of the player used by the PlayArea.
private  Set[] exposedHand
          Exposed hand of a player.
static int FISHING
           
private  CombList handComb
          Combination list for the concealed hand.
private  Tile lastDiscard
          Lastdiscarded tile.
static int MAHJONG
           
static int MAX_SETS
          Maximum number of Sets expected to fill the exposed Hand.
static int NEITHER_MAH_FISH
           
private  Payout payout
          Access to the Payout class.
private  boolean specialHand
          Type of hand that the concealed hand forms.
 
Constructor Summary
Hand(Payout payout)
          Constructs and initialises the player's concealed and exposed hands, and the payout.
 
Method Summary
private  void addSet(Set[] hand, Set aSet)
          Adds a set to the end of the given hand.
 boolean canChow2Down(Tile lastDiscard)
          Checks to see if the player can Chow with the current discard tile.
 boolean canChow2Sides(Tile lastDiscard)
          Checks to see if the player can Chow with the current discard tile.
 boolean canChow2Up(Tile lastDiscard)
          Checks to see if the player can Chow with the current discard tile.
 boolean canKong(Tile lastDiscard)
          Checks to see if the player can Kong with the current discard tile.
 boolean canPung(Tile lastDiscard)
          Checks to see if the player can Pung with the current discard tile.
 boolean checkFishing()
          Checks a player's hand for ordinary and special fishing hands.
 boolean checkKong(Tile selectedTile)
          Looks to see if the player can declare a concealed Kong with the selected tile.
 boolean checkMahjong(Tile lastPickUp)
          Checks a player's hand for ordinary and special Mahjong hands.
 boolean checkPung2Kong(Tile selectedTile)
          Checks the player's hand for an exposed Pung similar to the selected tile.
 void declareKong(Tile selectedTile)
          Reveals a concealed Kong in the player's hand, using the selected tile.
 void discard(Tile lastDiscard)
          Removes the given tile from the player's concealed hand. This function is called when the player discards a tile from their hand.
 boolean findKong()
          Searches through the player's concealed hand to find any Kongs that may exist.
 boolean findPung2Kong()
          Scans through all tiles in the concealed hand and then tries to match these tiles with the Set in the exposed hand.
 Set[] getSet()
          Returns players exposed hand to be displayed in the PlayArea.
 Tile[] getTiles()
          Returns players concealed hand to be displayed in the PlayArea.
 void insertTile(Tile givenTile)
          Inserts the given tile into the player's concealed hand.
 void mahjong(Game game)
          Calculates the best form that the concealed hand of the winner can take.
private  void removeSet(Set[] hand, Set aSet)
          Searches for and removes a set from the given hand.
 void removeTile(int suit, int tileNo)
          This locates and removes a tile with the given tile number and suit from the concealed hand.
 void runChow(Tile lastDiscard, int selection)
          Exposes the Chow in the player's concealed hand with the given discard.
 void runKong(Tile lastDiscard)
          Exposes a Kong in the player's hand with the given discard.
 void runMahjong(Tile lastDiscard)
          This is run whenever a player has mahjong by using the last discarded tile.
 void runPung(Tile lastDiscard)
          Exposes the Pung in the player's concealed hand with the given discard.
 void runPung2Kong(Tile selectedTile)
          This function is run if the player has selected to and can successfully add a tile to an exposed Pung.
 
Methods inherited from class java.lang.Object
, clone, equals, finalize, getClass, hashCode, notify, notifyAll, registerNatives, toString, wait, wait, wait
 

Field Detail

NEITHER_MAH_FISH

public static final int NEITHER_MAH_FISH

MAHJONG

public static final int MAHJONG

FISHING

public static final int FISHING

MAX_SETS

public static final int MAX_SETS
Maximum number of Sets expected to fill the exposed Hand.

allDrawWall

private boolean allDrawWall
Flag- True if all tiles except the last was drawn from Wall.

concealedHand

private int[][] concealedHand
Concealed hand of a player.

copyOfHand

private Tile[] copyOfHand
Copy of the concealed hand of the player used by the PlayArea.

exposedHand

private Set[] exposedHand
Exposed hand of a player.

specialHand

private boolean specialHand
Type of hand that the concealed hand forms.

handComb

private CombList handComb
Combination list for the concealed hand.

payout

private Payout payout
Access to the Payout class.

lastDiscard

private Tile lastDiscard
Lastdiscarded tile.
Constructor Detail

Hand

public Hand(Payout payout)
Constructs and initialises the player's concealed and exposed hands, and the payout.

Parameters:
payout - Reference to the Game's Payout.
Method Detail

insertTile

public void insertTile(Tile givenTile)
                throws java.lang.ArrayIndexOutOfBoundsException
Inserts the given tile into the player's concealed hand.

Parameters:
givenTile - Tile to insert into player's Hand.
Throws:
java.lang.ArrayIndexOutOfBoundsException - If there are more than Const.MAX_HAND tiles.

discard

public void discard(Tile lastDiscard)
             throws java.lang.NullPointerException,
                    java.lang.ArrayIndexOutOfBoundsException
Removes the given tile from the player's concealed hand.

This function is called when the player discards a tile from their hand.

Parameters:
lastDiscard - Tile to remove.
Throws:
java.lang.NullPointerException - If the tile is not in the hand.
java.lang.ArrayIndexOutOfBoundsException - If the tile is not in the hand.

removeTile

public void removeTile(int suit,
                       int tileNo)
This locates and removes a tile with the given tile number and suit from the concealed hand. The function is called when removing tiles from the concealed hand and placing them in the exposed Set.

Parameters:
tileNo - Number of the tile to remove.
suit - Suit of the tile to remove.

runChow

public void runChow(Tile lastDiscard,
                    int selection)
             throws java.lang.NullPointerException,
                    java.lang.ArrayIndexOutOfBoundsException
Exposes the Chow in the player's concealed hand with the given discard. If the selection was Chi2Sides, the tiles to either side of the discard are removed from the concealed hand. If the selection was Chi2Down, the two tiles below the discard are removed. If the selection was Chi2Up, then the two above are removed. A Chow is placed in the exposed hand, indicated by the first tile in the Set.

 void runChow(Tile lastDiscard, int selection) {
     get suit of tile;
     get tile number from tile;
     if selection was CHOW2SIDES then {
         remove the tile with the suit and tile number - 1 from the 
         concealedHand;
         remove the tile with the suit and tile number + 1 from the 
         concealedHand;
         create a new set;
         initialise set to Chow, with location suit and tile number 
         - 1; 
         attach new set to end of exposedHand list;
     }

     if selection was CHOW2DOWN then {
         remove the tile with the suit and tile number - 1 from the 
         concealedHand;
         remove the tile with the suit and tile number - 2 from the 
         concealedHand;
         create a new set;
         initialise set to Chow, with the suit and tile number - 2;
         attach new set to end of exposedHand list;
     }

     if selection was CHOW2UP then {
         remove the tile with the suit and tile number + 1 from the 
         concealedHand;
         remove the tile with the suit and tile number + 2 from the 
         concealedHand;
         create a new set;
         initialise set to Chow, with the suit and tile number; 
         attach new set to end of exposedHand list;
     }

     allDrawWall is false;
 }

Parameters:
lastDiscard - Tile that will be used to make up the exposed Chow.
selection - Which of the 3 Chow(chow2Down, chow2Up or chow2Sides) to run.
Throws:
java.lang.NullPointerException - If the tile is not in the hand.
java.lang.ArrayIndexOutOfBoundsException - If the tile is not in the hand.

runPung

public void runPung(Tile lastDiscard)
             throws java.lang.NullPointerException,
                    java.lang.ArrayIndexOutOfBoundsException
Exposes the Pung in the player's concealed hand with the given discard. A Pung is placed in the exposed hand with the lastDiscard to indicate the first tile in the Set.

 void runPung(Tile lastDiscard) {
     get suit of tile;
     get tile number from tile;
     remove two of the tiles with the suit and tile number from the  
     concealedHand;
     create a new set;
     initialise set to Pung, with the suit and tile number;
     attach new set to end of exposedHand list;
     allDrawWall is false;
 }

Parameters:
lastDiscard - Tile that will be used to make up the exposed Pung.
Throws:
java.lang.NullPointerException - If the tile is not in the hand.
java.lang.ArrayIndexOutOfBoundsException - If the tile is not in the hand.

findKong

public boolean findKong()
Searches through the player's concealed hand to find any Kongs that may exist. If the concealed hand contain four of any similar tile then findKong() will return true.

 boolean findKong() {
     for all locations in the concealed hand {
         if the location contains 4 tiles then
             return true;
     }

     return false;
 }

Returns:
True if any Kongs do exist in the concealed hand.

checkKong

public boolean checkKong(Tile selectedTile)
Looks to see if the player can declare a concealed Kong with the selected tile.

 boolean checkKong(Tile selectedTile) {
     get suit of tile;
     get tile number from tile;
     if the location at suit and tile number in the concealed hand 
     contains four tiles then
         return true;
     else
         return false;
 }

Parameters:
selectedTile - Tile selected by the player.
Returns:
True if the player can declare Kong with the selected tile.

runKong

public void runKong(Tile lastDiscard)
             throws java.lang.NullPointerException,
                    java.lang.ArrayIndexOutOfBoundsException
Exposes a Kong in the player's hand with the given discard. Removes all tiles similar to the selected tile from the concealed hand and inserts a Kong Set into the exposed hand.

 void runKong(Tile lastDiscard) {
    get suit of tile;
    get tile number from tile;
    remove three of the tiles with the suit and tile number from the 
    concealedHand; 
    create a new set;
    initialise set to Kong, with the suit and tile number;
    attach new set to end of exposedHand list;
    allDrawWall is false;
 }

Parameters:
lastDiscard - Tile that will be used to make up the exposed Kong.
Throws:
java.lang.NullPointerException - If the tile is not in the hand.
java.lang.ArrayIndexOutOfBoundsException - If the tile is not in the hand.

declareKong

public void declareKong(Tile selectedTile)
                 throws java.lang.NullPointerException,
                        java.lang.ArrayIndexOutOfBoundsException
Reveals a concealed Kong in the player's hand, using the selected tile. All tiles similar to the selected tile are removed from the concealed hand and inserted as a declared Kong Set into the exposed hand.

 void declareKong(Tile selectedTile) {
     get suit of tile;
     get tile number from tile;
     remove four of the tiles with the suit and tile number from the 
     concealedHand;
     create a new set;
     initialise set to declared Kong, with location suit and tile 
     number;
     attach new set to end of exposedHand list;
 }

Parameters:
selectedTile - Tiles selected to declare.
Throws:
java.lang.NullPointerException - If the tile is not in the hand.
java.lang.ArrayIndexOutOfBoundsException - If the tile is not in the hand.

findPung2Kong

public boolean findPung2Kong()
Scans through all tiles in the concealed hand and then tries to match these tiles with the Set in the exposed hand. If for any tile in the concealed hand, there is a matching Set that is a Pung then the findPung2Kong() will return true.

Returns:
True if pung2kong is possible.

runPung2Kong

public void runPung2Kong(Tile selectedTile)
                  throws java.lang.NullPointerException,
                         java.lang.ArrayIndexOutOfBoundsException
This function is run if the player has selected to and can successfully add a tile to an exposed Pung. The Set with the similar starting tile to the selectedTile is changed from a Pung to a Kong.

 void runPung2Kong(Tile selectedTile) {
     get suit of tile;
     get tile number from tile;
     while searching through exposed hand and Pung not found {
         if tile number of set = number of tile and suit of set = suit 
         of tile
             found is true;
     }

     convert set to pung2Kong();
 }

Parameters:
selectedTile - Tile to add to Pung.
Throws:
java.lang.NullPointerException - If the tile is not in the hand.
java.lang.ArrayIndexOutOfBoundsException - If the tile is not in the hand.

checkPung2Kong

public boolean checkPung2Kong(Tile selectedTile)
                       throws java.lang.NullPointerException,
                              java.lang.ArrayIndexOutOfBoundsException
Checks the player's hand for an exposed Pung similar to the selected tile. For all sets in the exposed hand if the tile number, tile suit match and the set is a Pung then it will return true.

 boolean checkPung2Kong(Tile selectedTile) {
     get suit of tile;
     get tile number from tile;
     for all locations in the exposed hand {
         if the set's suit = the tile's suit and set's tile number = 
         the tile's number then {
             if the set type is a Pung then
                 return true;
         }
     }

     return false;
 }

Parameters:
selectedTile - Tile to add to Pung.
Returns:
True if pung2Kong is possible.
Throws:
java.lang.NullPointerException - If the tile is not in the hand.
java.lang.ArrayIndexOutOfBoundsException - If the tile is not in the hand.

runMahjong

public void runMahjong(Tile lastDiscard)
This is run whenever a player has mahjong by using the last discarded tile.

Parameters:
lastDiscard - Tile used to go mahjong.

mahjong

public void mahjong(Game game)
             throws java.lang.NullPointerException,
                    java.lang.ArrayIndexOutOfBoundsException
Calculates the best form that the concealed hand of the winner can take. All flags are sent to the Payout class and if a special hand is not formed the different Mahjong combinations are sent to the Payout class to determine which produces the highest score.

 public void mahjong() {
     get suit of tile;
     get tile number from tile;
     payout.allDrawHand(allDrawHand);
     if the hand is not a special hand then {
         number of best combinations = extract best combinations out of 
         concealed hand;
         initialise a list of temporary concealed hand Sets;
         convert the best combinations into Sets;
         for all combination Sets {
             if the score is higher than the previous score then
                 best combination = this combination;
         }
     }>
 }

Parameters:
lastTile - Tile with which the player's hand has won.
Throws:
java.lang.NullPointerException - If the tile is not in the hand.
java.lang.ArrayIndexOutOfBoundsException - If the tile is not in the hand.

removeSet

private void removeSet(Set[] hand,
                       Set aSet)
Searches for and removes a set from the given hand.

Parameters:
hand - List of sets.
aSet - Set to remove.

addSet

private void addSet(Set[] hand,
                    Set aSet)
Adds a set to the end of the given hand.

Parameters:
hand - List of sets.
aSet - Set to remove.

checkMahjong

public boolean checkMahjong(Tile lastPickUp)
                     throws java.lang.NullPointerException,
                            java.lang.ArrayIndexOutOfBoundsException
Checks a player's hand for ordinary and special Mahjong hands. The concealed hand is copied twice. The first is to be used by the uniqueWonder(), gatesOfHeaven() and ordinary Mahjong checks. The copy is necessary, as tiles are removed in the ordinary Mahjong check. A second copy is made to check for the wrigglySnake(). The exposed tiles are added to the concealed hand to run the check. Once the copies have been made the lastPickUp tile is added to see if this will produce a Mahjong hand. The checkMahjong() function is only run at the beginning of the game, to check that East hasn't been dealt a Mahjong hand, and when a player is fishing during the game.

 boolean checkMahjong(Tile lastPickUp) {
     get suit of tile;
     get tile number from tile; 
     initialise two copies of the concealed hand;
     copy concealed hand into both copies;
     while there are still more sets in the exposed hand and a wriggly 
     snake is possible {
         if set is a Chow then {
             increment the first copy by one at the location of the sets 
             tile number and suit; 
             increment the first copy by one at the location of the sets 
             tile number + 1 and suit;
             increment the first copy by one at the location of the sets 
             tile number + 2 and suit;
         }

         if set is a Pung then {
             break. The wriggly snake isn't possible;
         }

         if set is a Kong then {
             break. The wriggly snake isn't possible;
         }

         if set is a declared Kong then {
             break. The wriggly snake isn't possible;
         }
    }

    if the lastPickUp exists then {
        increment both copies by one at the location of the tile's 
        number and suit;
    }
     
    if the hand is a uniquewonder- using the second copy then {
        payout.uniqeWonder();
             return true;
    }

    if the hand is a gatesOfHeaven- using the second copy then {
        payout.gatesOfHeaven();
        return true;
    }

    if a wriggly snake is possible and the hand is a wrigglySnake- 
    using the first copy then {
        payout.wrigglySnake();
        return true;
    }

    if the hand is an ordinary mahjong hand- using the second copy
    then {
        return true;
    }
 }

Returns:
True hand has Mahjong.
Throws:
java.lang.NullPointerException - If the tile is not in the hand.
java.lang.ArrayIndexOutOfBoundsException - If the tile is not in the hand.

checkFishing

public boolean checkFishing()
                     throws java.lang.NullPointerException,
                            java.lang.ArrayIndexOutOfBoundsException
Checks a player's hand for ordinary and special fishing hands. The concealed hand is copied twice. The first is to be used by the uniqueWonder(), gatesOfHeaven() and ordinary fishing checks. The copy is necessary, as tiles are removed in the ordinary fishing check. A second copy is made to check for the wrigglySnake(). The exposed tiles are added to the concealed hand to run the check. CheckFishing() is run whenever a player removes a tile for a discard or pung2Kong, or when a player reveals or declares a Kong.

 
 boolean checkFishing() {
     initialise two copies of the concealed hand;
     copy concealed hand into both copies;
     for all sets in the exposed hand {
         if set is a Chow then {
             increment the first copy by one at the location of the sets 
             tile number and suit;
             increment the first copy by one at the location of the sets 
             tile number + 1and suit;
             increment the first copy by one at the location of the sets 
             tile number +2 and suit;
         }

         if set is a Pung then {
             break. The wriggly snake isn't possible;
         }

         if set is a Kong then {
             break. The wriggly snake isn't possible;
         }

         if set is a declared Kong then {
             break. The wriggly snake isn't possible;
         }

         if the hand is a fishing uniquewonder- using the second copy 
         then {
             payout.uniqeWonder();
             return true;
         }

         if the hand is a fishing gatesOfHeaven- using the second copy 
         then {
             payout.gatesOfHeaven();
             return true;
         }

         if a wriggly snake is possible and the hand is a fishing 
         wrigglySnake- using the first copy then {
             payout.wrigglySnake();
             return true;
         }

         if the hand is an ordinary fishing hand- using the second copy
         then {
             return true;
         }
 }

Returns:
True if player is fishing.
Throws:
java.lang.NullPointerException - If the tile is not in the hand.
java.lang.ArrayIndexOutOfBoundsException - If the tile is not in the hand.

canChow2Sides

public boolean canChow2Sides(Tile lastDiscard)
Checks to see if the player can Chow with the current discard tile. If the concealed hand contains the tiles with numbers to either side of the lastDiscard then this function will return true.

 int canChow2Sides(Tile lastDiscard){
     get suit of tile;
     get tile number from tile;
     if (the tileNumber - 1 >= 0 ) and (the tile's suit is not an honour
     tile) and (the tileNumber + 1 <= MAX_TILENO) then {
         if (the concealed hand at tile number - 1 and suit >= 1) and ( 
         tileNumber + 1 and suit >= 1) then
             return true;
     }

     return false;
 }

Parameters:
lastDiscard - Last discarded tile.
Returns:
True if chow2sides is possible.

canChow2Down

public boolean canChow2Down(Tile lastDiscard)
Checks to see if the player can Chow with the current discard tile. If the concealed hand contains the tiles with two numbers below the lastDiscard then this function will return true.

 int canChow2Down(Tile lastDiscard) {
     get suit of tile;
     get tile number from tile;
     if (the tileNumber-2 >= 0 ) and (the tiles suit is not an honour 
     tile) then {
         if (the concealed hand at tile number - 2 and suit >= 1) and ( 
         tileNumber - 1 and suit >= 1) then
             return true;
     }

     return false;
 }

Parameters:
lastDiscard - Last discarded tile.
Returns:
True if chow2down is possible.

canChow2Up

public boolean canChow2Up(Tile lastDiscard)
Checks to see if the player can Chow with the current discard tile. If the concealed hand contains the tiles with two numbers above the lastDiscard then this function will return true.

 int canChow2Up(Tile lastDiscard) {
     get suit of tile;
     get tile number from tile;
     if (the tiles suit is not an honour tile) and (the tileNumber + 2 <= 
     MAX_TILENO) then {
         if (the concealed hand at tile number + 1 and suit >= 1) and
         (tileNumber + 2 and suit >= 1) then
             return true;
     }

     return false;
 }

Parameters:
lastDiscard - Last discarded tile.
Returns:
True if chow2up is possible.

canPung

public boolean canPung(Tile lastDiscard)
Checks to see if the player can Pung with the current discard tile. If the concealed hand contains 2 or more tiles similar to the discard then this function will return true.

 int canPung(Tile lastDiscard) {
     get suit of tile;
     get tile number from tile;
     if (the concealed hand at tile number and suit >= 2) then
         return true;

     return false;
 }

Parameters:
lastDiscard - Last discarded tile.
Returns:
True if Pung is possible.

canKong

public boolean canKong(Tile lastDiscard)
Checks to see if the player can Kong with the current discard tile. If the concealed hand contains 3 tiles similar to the lastDiscard the this function will return true.

Parameters:
lastDiscard - Last discarded tile.
Returns:
True if Kong is possible.

getTiles

public Tile[] getTiles()
Returns players concealed hand to be displayed in the PlayArea.

Returns:
The concealed hand.

getSet

public Set[] getSet()
Returns players exposed hand to be displayed in the PlayArea.

Returns:
The exposed hand.