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

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

public class CombList
extends java.lang.Object

SRS 4.3.1, 4.3.7, 4.3.8

The CombList class' main responsibility will be to search through the entire concealed hand of a Player and extract all the possible combinations that the hand can take.

Taking a Player's concealed hand, CombList will search across the hand until a tile has been found. Tiles are then both "grouped across" and "grouped up". Group across refers to collecting tiles with consecutive numbered faces. For example: bamboo 1, 2 and 3 form a group of tiles that have consecutive numbered faces. Group up refers to the collection of tiles with similar faces. For example: 3 similar tiles of circles 1. Honour tiles are only grouped up.

The Comb class is used to store one particular combination. While tiles being grouped up are inserted at the one time, tiles grouped across are inserted individually. Therefore the Comb class is needed to be able to insert tiles into the next available space in an array.

The Comb is stored as a Vector. This was chosen as the list of combinations for any hand can be vary in size and any elements can easily be added to the end of the list. CombList also has the responsibility of checking for special Mahjong and Fishing hands. These include the Wriggly Snake, Unique Wonder and the Gates of Heaven.

Once a player has won with a Mahjong hand and if the hand doesn't form a special Mahjong, then the class will be called to convert the combinations into Sets that can be used by the Payout class. As a hand can take on several winning combinations each will need to be checked for the highest possible score.

Author:
Dean Cortinovis

Field Summary
static int ACROSS
           
private  int[] bestComb
          Array storing the location of the best found combinations.
private  java.util.Vector combinations
          Storage for the combinations
private  boolean createdFlag
          Flag to signal if first combination has been created
private  int noBestComb
          Number of best combinations found
static int UP
           
 
Constructor Summary
CombList()
          Class constuctor.
 
Method Summary
 int checkMahjong(int[][] hand)
          Given a concealed hand extracts all the combinations and tries to determine if the hand is fishing or can Mahjong.
 void close()
          Clears the combinations list.
 void convertCombSets(Set[][] conHand, Set[][] expHand, Tile lastDiscard)
          Converts the best combinations into Sets that can be used to calculate the score at the end of the game.
 int extractBestComb()
          Searches through all combinations and extracts the Mahjong combinations.
 int gatesOfHeaven(int[][] hand)
          Given a concealed hand tries to determine if it forms a fishing or Mahjong gatesOfHeaven.
 int groupAcross(int[][] hand, int curNum, int curSuit, int groupNo)
          Starting from the given location, this operation moves across the concealed hand and inserts the tiles into the current combination being looked at.
 int groupUp(int[][] hand, int curNum, int curSuit, int groupNo)
          Starting from the given location, this operation moves up the concealed hand and inserts the tiles into the current combination being looked at.
 int lookAcross(int[][] hand, int curNum, int curSuit, int groupNo)
          The function, starting from the given initial position, searches across the concealed hand for the next tile that is present.
 int uniqueWonder(int[][] hand)
          Given a concealed hand tries to determine if it forms a fishing or Mahjong uniqueWonder.
 int wrigglySnake(int[][] combinedHand)
          Given a combined concealed and exposed hand tries to determine if it forms a fishing or Mahjong wrigglySnake.
 
Methods inherited from class java.lang.Object
, clone, equals, finalize, getClass, hashCode, notify, notifyAll, registerNatives, toString, wait, wait, wait
 

Field Detail

ACROSS

public static final int ACROSS

UP

public static final int UP

createdFlag

private boolean createdFlag
Flag to signal if first combination has been created

combinations

private java.util.Vector combinations
Storage for the combinations

noBestComb

private int noBestComb
Number of best combinations found

bestComb

private int[] bestComb
Array storing the location of the best found combinations.
Constructor Detail

CombList

public CombList()
Class constuctor.
Method Detail

close

public void close()
Clears the combinations list.

groupUp

public int groupUp(int[][] hand,
                   int curNum,
                   int curSuit,
                   int groupNo)
Starting from the given location, this operation moves up the concealed hand and inserts the tiles into the current combination being looked at. If the current location contains four tiles then the function will only insert 3 tiles into the current combination. CombList will then lookAcross() the hand from the current location, since the remaining 4th tile needs to be taken into consideration. If the current location contains less than four tiles, all are inserted into the current combination. CombList will then lookAcross() the hand from the current location + 1 tile number, since all tiles at the current location have been removed.

 int groupUp(int[][] hand, int curNum, int curSuit, int groupNo) {
     if hand at current location == 4 then {
         insert 3 of the current location into the current group;
         hand at current location = 1;
         current group number = lookAcross hand from the current 
         location;
     }
     else {
         insert all of the tiles at the current location into the current 
         group; 
         clear the contents at the current location; 
         current group number = lookAcross hand from the current suit, 
         current tile number + 1; 
     }
     return current group number;
 }

Parameters:
hand - The player's concealed hand.
curNum - Current tile number being looked at.
curSuit - Current suit being looked at.
groupNo - Current combination group inserting into.
Returns:
The new groupNo inserting into.

lookAcross

public int lookAcross(int[][] hand,
                      int curNum,
                      int curSuit,
                      int groupNo)
The function, starting from the given initial position, searches across the concealed hand for the next tile that is present. If the search has reached the last tile number, the next suit is looked at. Once the next tile has been found, the hand and location are passed to be grouped across. A copy of the hand is made, and a copy of the current group combination is made. The copy of the hand and current location is then passed to be grouped up into the next combination. If the current suit is equal to or above the HONOUR_POINT then the function only groups up the hand.

 int lookAcross(int[][] hand, int curNu,, int curSuit, int groupNo) {
     copy the hand into a new location;
     while ((not finished looking through the hand) and (contents at the 
     current location is empty)) {
         move across the column; 
         if beyond the maximum size of the column {
             move to next suit;
             start at tile number 1;
         }
     }

    if not finished looking through the hand then {
        if the current suit is not an honour suit then{
            create a new combination;
            the temporary group number = the location of the new 
            combination;
            copy the contents of the current group into the temporary 
            group number;
            current group number = groupAcross the hand from the current 
            location into the current group;
            group up the copy of the hand from the current location into 
            the temporary group number;
        }
        else {
            only groupUp the hand from the current location into the 
        }

        current group number;
    }

    return group number;
 }

Parameters:
hand - The player's concealed hand.
curNum - Current tile number being looked at.
curSuit - Current suit being looked at.
groupNo - Current combination group inserting into.
Returns:
int The new groupNo inserting into.

groupAcross

public int groupAcross(int[][] hand,
                       int curNum,
                       int curSuit,
                       int groupNo)
Starting from the given location, this operation moves across the concealed hand and inserts the tiles into the current combination being looked at. The function groups across until 3 spaces have been traversed, or the current tile number is beyond the array size. If the current space contains more than one tile, it is marked to go back to. If any of the three spaces traverse is empty then nothing is inserted into the current group.

The tiles are added to the current combination one at a time. This is as apposed to the groupUp() function that inserts tiles in one group. If a blank space is reached then any of the remaining 3 spaces are filled with empty markers in the combination. Every three spaces in the combination represents a set. At the end there is a recursive call to continue looking across the concealed hand from either the current location being looked at or the location that needs to be covered.

 int groupAcross(int[][] hand, int curNum, int curSuit, int 
 groupNo) {
     while ((not outside the bounds of the maximum tile number) and 
     (the hand hasn't been traversed more than three spaces) {
         if ((there are more than one tile at the current location) and 
         (not convering another location)) then {
              record current location which must be covered;
         }

         if there is a tile at this location then {
             reduce current location by one; 
             insert current location (suit and tileno) into the current 
             group;
             count ++;
         }

         current location ++;
     }

     if (less than 3 tiles were inserted into the current group) 
     then {
         insert the empty flag into the remaining of the 3 places in the 
         current group;
     }

     if tiles need to be covered then {
         group number = lookAcross hand from the given cover location and 
         insert into group number;
     }
     else {
         group number = continue to lookAcross hand from position last
         looked at;
     }

     return current group number;
 }

Parameters:
hand - Player's concealed hand.
curNum - Current tile number being looked at.
curSuit - Current suit being looked at.
groupNo - Current combination group inserting into.
Returns:
int The new groupNo inserting into.

extractBestComb

public int extractBestComb()
Searches through all combinations and extracts the Mahjong combinations. These are placed into the bestComb list. For all combinations in the list if the current combination being looked at is a Mahjong combination it's location is added to the end of the bestComb list.

 int extractBestComb() {
 initialise list of best contents;
     for all combinations in the list {
         if this combination is a mahjong combination then {
             insert this combination to the end of the best combinations 
             list;
         }
     }

     return the total number of best combinations;
 }

Returns:
Number of best combinations.

convertCombSets

public void convertCombSets(Set[][] conHand,
                            Set[][] expHand,
                            Tile lastDiscard)
Converts the best combinations into Sets that can be used to calculate the score at the end of the game.

 void convertCombSets(Sets[][] newHand) {
     for all of the best combinations {
         convert the combination into Sets and insert it into the 
         newHand;
     }
 }

Parameters:
conHand - Concealed hand that needs to be converted into Sets.
expHand - Exposed hand of the player.
lastDiscard - Last discarded tile.

checkMahjong

public int checkMahjong(int[][] hand)
Given a concealed hand extracts all the combinations and tries to determine if the hand is fishing or can Mahjong.

 int checkMahjong(int[][] hand) {
     create combination list in lookAcross() hand, from the first tile 
     number and first suit and insert into group 0;
     for all combinations in the combination list {
         if this combination is a mahjong combination then {
              return MAHJONG;
         }

         if this combination is a fishing combination then {
             return FISHING;
         }
     }

     return NEITHER MAHJONG OR FISHING;
 }

Parameters:
hand - Concealed hand of the player.
Returns:
0- neither Mahjong or fishing.
1- is a Mahjong Hand.
2- Hand is fishing.

uniqueWonder

public int uniqueWonder(int[][] hand)
Given a concealed hand tries to determine if it forms a fishing or Mahjong uniqueWonder.

 int uniqueWonder(int[][] hand) {
     for all ordinary suits {
         add to the count the number of terminals if the terminal 
         contains less than 3 tiles;
         count all empty terminal spaces;
     }

     for all honour suits {
         add all tiles to the count; 
         count all empty spaces in the honour suits;
     }

     if the count == 13 and empty spaces <= 2 then {
         return FISHING;
     }

     if the count == 14 and empty spaces == 1 then {
         return MAHJONG;
     }

     return NEITHER MAHJONG OR FISHING;
 }

Parameters:
hand - Concealed hand of the player.
Returns:
0- neither Mahjong or fishing.
1- is a Mahjong Hand.
2- Hand is fishing.

gatesOfHeaven

public int gatesOfHeaven(int[][] hand)
Given a concealed hand tries to determine if it forms a fishing or Mahjong gatesOfHeaven.

 int gatesOfHeaven(int[][] hand) {
     for all ordinary suits {
         add to the count of terminals, the number of tiles that exist in 
         the terminal spaces if they are less than four;
         for all non terminals {
             if the space contains less than 3 then {
                 add to the non terminal count;
             }

             if the space is empty then {
                 add to the empty space count;
             }
         }

         if the terminal count == 6 and nonterminal count == 7 and empty 
         count <= 1 then {
             return FISHING;
         }

         if the terminal count == 5 and nonterminal count == 8 and empty 
         count == 0 then {
             return FISHING;
         }

         if the terminal count == 6 and nonterminal count == 8 and empty 
         count == 0 then {
             return MAHJONG;
         }

         initialise counter;
    }

    return NIETHER MAHJONG OR FISHING;
 }

Parameters:
hand - Concealed Hand of the player.
Returns:
0- neither Mahjong or fishing.
1- is a Mahjong Hand.
2- Hand is fishing.

wrigglySnake

public int wrigglySnake(int[][] combinedHand)
Given a combined concealed and exposed hand tries to determine if it forms a fishing or Mahjong wrigglySnake.

 int wrigglySnake(int[][] combinedHand) {
     for all winds {
         add to the count of winds if it is less than three;
         add to the count of empty wind spaces if empty;
     }

     for all ordinary suits {
         for all tiles in the suit {
             add to the count of tiles if it is less than 3;
             add to the count of empty spaces if empty;
         }

         add the empty wind spaces to the empty spaces count;
         if the winds count == 5 + tiles count 8 + empty spaces <= 1 
         then {
             return FISHING;
         }

         if the winds count == 4 + tiles count 9 + empty spaces <= 1 
         then {
             return FISHING;
         }

         if the winds count == 3 + tiles count 10 + empty spaces <= 1 
         then {
             return FISHING;
         }

         if the winds count == 5 + tiles count 9 + empty spaces == 0 
         then {
             return MAHJONG;
         }

         if the winds count == 4 + tiles count 10 + empty spaces == 1 
         then {
             return MAHJONG;
         }

         initialise counters;
     }
 }

Parameters:
hand - Combined concealed and exposed hand of the player.
Returns:
0- neither Mahjong or fishing.
1- is a Mahjong Hand.
2- Hand is fishing.