//Forms an open meld that matches the potential meld. Cannot be used for shouminkan. public void FormOpenMeld(PotentialMeld meld, int accessKey = 0) { if ((accessKey != _accessKey) && _accessKey != 0) { return; } TileID discardID = Kawa.MostRecentDiscard.Query(); List <Tile> with = new List <Tile>(); int start = 0; Meld.MeldType type = Meld.MeldType.Minkou; if (meld.Type == Meld.MeldType.Kantsu) { start = Tiles.IndexOf(discardID); with.Add(Tiles[start]); with.Add(Tiles[start + 1]); with.Add(Tiles[start + 2]); with.Add(Tiles[start + 3]); if (meld.Completed) { type = Meld.MeldType.Ankan; } else { type = Meld.MeldType.Daiminkan; } } else if (meld.Type == Meld.MeldType.Koutsu) { start = Tiles.IndexOf(discardID); with.Add(Tiles[start]); with.Add(Tiles[start + 1]); with.Add(Tiles[start + 2]); type = Meld.MeldType.Minkou; } else if (meld.Type == Meld.MeldType.Shuntsu) { //Use the self-sorting property of PotentialMeld to get the first ID PotentialMeld completed = new PotentialMeld(meld.IDs); completed.Add(discardID); with.Add(Tiles[Tiles.IndexOf(completed.IDs[0])]); with.Add(Tiles[Tiles.IndexOf(completed.IDs[1])]); with.Add(Tiles[Tiles.IndexOf(completed.IDs[2])]); type = Meld.MeldType.Minjun; } //All the tiles are found, now form the open meld Tiles.OpenTiles(with, _accessKey); OpenMeld open = new OpenMeld(type, with, PlayerNumber); OpenMelds.Add(open); EventManager.FlagEvent("Hand " + PlayerNumber + " Open Meld"); }
//Creates a PotentialMeld version of itself public PotentialMeld ConvertToPotentialMeld() { PotentialMeld meld = new PotentialMeld(); foreach (TileID tile in IDs) { meld.Add(tile); } meld.Type = Type; meld.Completed = true; meld.Fungibility = -1; return(meld); }
//Adds all the waiting versions of a completed meld. Returns the number added. private int AddPotentialVersions(PotentialMeld completed) { int count = 0; PotentialMeld meld; if (completed.Type == Meld.MeldType.Koutsu) { //Potential koutsu meld = new PotentialMeld() { Type = Meld.MeldType.Koutsu, }; meld.Add(completed.IDs[0]); meld.Add(completed.IDs[0]); meld.Waits.Add(new Wait(WaitType.Kantsu, completed.IDs[0])); AddMeld(meld); count++; } else if (completed.Type == Meld.MeldType.Shuntsu) { //Potential shuntsu lower meld = new PotentialMeld() { Type = Meld.MeldType.Shuntsu, }; TileID t1 = completed.IDs[0]; TileID t2 = completed.IDs[1]; TileID t3 = completed.IDs[2]; meld.Add(t1); meld.Add(t2); if (t1.Number == 1) { meld.Waits.Add(new Wait(WaitType.Penchan, new TileID(t1.Suit, 3))); } else { meld.Waits.Add(new Wait(WaitType.Ryanmen, new TileID(t1.Suit, (byte)(t1.Number - 1)))); meld.Waits.Add(new Wait(WaitType.Ryanmen, t3)); } AddMeld(meld); count++; //Potential shuntsu upper meld = new PotentialMeld() { Type = Meld.MeldType.Shuntsu, }; meld.Add(t2); meld.Add(t3); if (t3.Number == 9) { meld.Waits.Add(new Wait(WaitType.Penchan, new TileID(t1.Suit, 7))); } else { meld.Waits.Add(new Wait(WaitType.Ryanmen, t1)); meld.Waits.Add(new Wait(WaitType.Ryanmen, new TileID(t1.Suit, (byte)(t3.Number + 1)))); } AddMeld(meld); count++; //Potential shuntsu center (kanchan) meld = new PotentialMeld() { Type = Meld.MeldType.Shuntsu, }; meld.Add(t1); meld.Add(t3); meld.Waits.Add(new Wait(WaitType.Kanchan, t2)); AddMeld(meld); count++; } return(count); }
//Checks up to the next 3 tiles in the list and adds any potential melds to the collection //Returns the number of potential melds added. private CheckForwardResponse CheckForward(int index) { CheckForwardResponse info = new CheckForwardResponse { count = 0, }; List <TileID> list = hand.Tiles.Closed.GetTileIDList(accessKey); PotentialMeld meld; TileID t1 = TileID.Invalid, t2 = TileID.Invalid, t3 = TileID.Invalid, t4 = TileID.Invalid; t1 = list[index]; //First rule out any obvious disqualifiers if (index + 1 < list.Count) { t2 = list[index + 1]; } else { return(info); //index is last tile in list } if (t2.Suit != t1.Suit) { return(info); //next suit different } if (t1.Jihai && t1.Number != t2.Number) { return(info); //different honor } //Set the next tileIDs if (index + 2 < list.Count) { t3 = list[index + 2]; } if (index + 3 < list.Count) { t4 = list[index + 3]; } //Check for koutsu/kantsu if (t2 == t1) { if (t3 == t1) { if (t4 == t1) { //4 of the same tile //Completed kantsu meld = new PotentialMeld() { Type = Meld.MeldType.Kantsu, Completed = true }; meld.Add(t1); meld.Add(t1); meld.Add(t1); meld.Add(t1); AddMeld(meld); info.count++; //Completed koutsu meld = new PotentialMeld() { Type = Meld.MeldType.Koutsu, Completed = true }; meld.Add(t1); meld.Add(t1); meld.Add(t1); AddMeld(meld); info.count++; //Completed jantou meld = new PotentialMeld() { Type = Meld.MeldType.Jantou, Completed = true, }; meld.Add(t1); meld.Add(t1); AddMeld(meld); info.count++; LooseTiles.Remove(hand.Tiles.Closed[index], accessKey); LooseTiles.Remove(hand.Tiles.Closed[index + 1], accessKey); LooseTiles.Remove(hand.Tiles.Closed[index + 2], accessKey); LooseTiles.Remove(hand.Tiles.Closed[index + 3], accessKey); } else { //3 of the same tile. //Potential kantsu meld = new PotentialMeld() { Type = Meld.MeldType.Kantsu, }; meld.Add(t1); meld.Add(t1); meld.Add(t1); meld.Waits.Add(new Wait(WaitType.Kantsu, t1)); AddMeld(meld); info.count++; //Completed koutsu meld = new PotentialMeld() { Type = Meld.MeldType.Koutsu, Completed = true }; meld.Add(t1); meld.Add(t1); meld.Add(t1); AddMeld(meld); info.count++; //Add potential koutsu info.count += AddPotentialVersions(meld); //Completed jantou meld = new PotentialMeld() { Type = Meld.MeldType.Jantou, Completed = true, }; meld.Add(t1); meld.Add(t1); AddMeld(meld); info.count++; LooseTiles.Remove(hand.Tiles.Closed[index], accessKey); LooseTiles.Remove(hand.Tiles.Closed[index + 1], accessKey); LooseTiles.Remove(hand.Tiles.Closed[index + 2], accessKey); } } else { //2 of the same tile //Potential koutsu meld = new PotentialMeld() { Type = Meld.MeldType.Koutsu, }; meld.Add(t1); meld.Add(t1); meld.Waits.Add(new Wait(WaitType.Koutsu, t1)); AddMeld(meld); info.count++; //Completed jantou meld = new PotentialMeld() { Type = Meld.MeldType.Jantou, Completed = true, }; meld.Add(t1); meld.Add(t1); AddMeld(meld); info.count++; LooseTiles.Remove(hand.Tiles.Closed[index], accessKey); LooseTiles.Remove(hand.Tiles.Closed[index + 1], accessKey); } } //Check for shuntsu else { if (t2.Number - t1.Number == 1) { if (t3.Suit == t1.Suit && t3.Number - t2.Number == 1) { //Completed shuntsu meld = new PotentialMeld() { Type = Meld.MeldType.Shuntsu, Completed = true }; meld.Add(t1); meld.Add(t2); meld.Add(t3); AddMeld(meld); info.count++; //Add all the potential shuntsu info.count += AddPotentialVersions(meld); LooseTiles.Remove(hand.Tiles.Closed[index], accessKey); LooseTiles.Remove(hand.Tiles.Closed[index + 1], accessKey); LooseTiles.Remove(hand.Tiles.Closed[index + 2], accessKey); } else { //Potential shuntsu with an outer wait meld = new PotentialMeld() { Type = Meld.MeldType.Shuntsu, }; meld.Add(t1); meld.Add(t2); if (t1.Number == 1) { meld.Waits.Add(new Wait(WaitType.Penchan, new TileID(t1.Suit, 3))); } else if (t2.Number == 9) { meld.Waits.Add(new Wait(WaitType.Penchan, new TileID(t1.Suit, 7))); } else { meld.Waits.Add(new Wait(WaitType.Ryanmen, new TileID(t1.Suit, (byte)(t1.Number - 1)))); meld.Waits.Add(new Wait(WaitType.Ryanmen, new TileID(t1.Suit, (byte)(t2.Number + 1)))); } AddMeld(meld); info.count++; LooseTiles.Remove(hand.Tiles.Closed[index], accessKey); LooseTiles.Remove(hand.Tiles.Closed[index + 1], accessKey); } } else if (t2.Number - t1.Number == 2) { //Potential shuntsu with a kanchan (inner) wait meld = new PotentialMeld() { Type = Meld.MeldType.Shuntsu, }; meld.Add(t1); meld.Add(t2); meld.Waits.Add(new Wait(WaitType.Kanchan, new TileID(t1.Suit, (byte)(t1.Number + 1)))); AddMeld(meld); info.count++; LooseTiles.Remove(hand.Tiles.Closed[index], accessKey); LooseTiles.Remove(hand.Tiles.Closed[index + 1], accessKey); } } return(info); }