private void TehaiCreate(Hand Hand) { int i; WaitingCount = 0; for (i = 0; i < 38; i++) { Waitings[i] = 0; Tehai[i] = 0; TehaiUsage[i] = 0; } for (i = 0; i < 14; i++) { if (Hand.Tiles[i] != -1) { Tile T = new Tile(Hand.Tiles[i]); Tehai[T.TileId]++; TehaiUsage[T.TileId]++; } } // Count naki's tiles usage for (i = 0; i < Hand.Naki.Count; i++) { Mahjong.Naki N = Hand.Naki[i]; if (N.Type == NakiType.NUKI) continue; for (int j = 0; j < N.Tiles.Count; j++) { Tile T = new Tile(N.Tiles[j]); TehaiUsage[T.TileId]++; } } }
// Get all hands in round public void ReplayGame() { Hand[] TempHands = new Hand[PlayerCount]; List<int>[] TempWaitings = new List<int>[PlayerCount]; List<int>[] Discard = new List<int>[PlayerCount]; for (int i = 0; i < PlayerCount; i++) { TempWaitings[i] = new List<int>(); Discard[i] = new List<int>(); } int LastTile = -1; // Init hands for (int i = 0; i < PlayerCount; i++) { Hands[i].Clear(); Hands[i].Add(StartHands[i]); Shanten[i].Add(StartHands[i].Shanten); TempHands[i] = new Hand(StartHands[i]); } for (int i = 0; i < Steps.Count; i++) { Step S = Steps[i]; switch (S.Type) { case StepType.STEP_NEWDORA: { DoraCount++; } break; case StepType.STEP_DRAWTILE: { TempHands[S.Player].Draw(S.Tile); // analyze danger tiles S.Danger = AnalyzeDangerTiles(TempHands, TempWaitings, S.Player); } break; case StepType.STEP_DRAWDEADTILE: { LastTile = S.Tile; TempHands[S.Player].Draw(S.Tile); // analyze danger tiles S.Danger = AnalyzeDangerTiles(TempHands, TempWaitings, S.Player); } break; case StepType.STEP_DISCARDTILE: { TempHands[S.Player].Discard(S.Tile); Hands[S.Player].Add(new Hand(TempHands[S.Player])); int TShanten = TempHands[S.Player].Shanten; if(TShanten == 0) Tempai[S.Player] = true; S.Shanten = TShanten; Shanten[S.Player].Add(TShanten); Discard[S.Player].Add(new Tile(S.Tile).TileId); if (TShanten == 0) // Tempai { TempWaitings[S.Player] = TempHands[S.Player].WaitingList; S.Waiting = TempWaitings[S.Player].ToArray(); S.Furiten = IsFuriten(Discard[S.Player], S.Waiting); } } break; case StepType.STEP_NAKI: { Hand H = TempHands[S.Player]; if (S.NakiData.Type == NakiType.CHAKAN) { Tile T = new Tile(S.NakiData.Tiles[0]); // Remove pon with this tiles for (int n = 0; n < H.Naki.Count; n++) { if (new Tile(H.Naki[n].Tiles[0]).TileId == T.TileId) { H.Naki.RemoveAt(n); } } } TempHands[S.Player].Naki.Add(S.NakiData); TempHands[S.Player].OpenTiles(S.NakiData.Tiles); // analyze danger tiles S.Danger = AnalyzeDangerTiles(TempHands, TempWaitings, S.Player); } break; case StepType.STEP_TSUMO: { WinWaiting[S.Player] = Hands[S.Player][Hands[S.Player].Count - 1].WaitingList; Hands[S.Player].Add(new Hand(TempHands[S.Player])); Shanten[S.Player].Add(-1); } break; case StepType.STEP_RON: { WinWaiting[S.Player] = Hands[S.Player][Hands[S.Player].Count - 1].WaitingList; TempHands[S.Player].Draw(LastTile); Hands[S.Player].Add(new Hand(TempHands[S.Player])); Shanten[S.Player].Add(-1); } break; } } }
private int[] AnalyzeDangerTiles(Hand[] Hands, List<int>[] Waitings, int Player) { List<int> DangerTiles = new List<int>(); // Build danger tiles list List<int> Danger = new List<int>(); for (int j = 0; j < PlayerCount; j++) { if (Player == j) continue; // Skip player's self hand if(Waitings[j] == null) continue; // Skip noten hands for(int k = 0; k < Waitings[j].Count; k++) { if (Waitings[j][k] == -1) continue; // Skip exists if (Danger.Contains(Waitings[j][k])) continue; Danger.Add(Waitings[j][k]); } } for (int j = 0; j < Hands[Player].Tiles.Length; j++) { if (Hands[Player].Tiles[j] == -1) continue; Tile T = new Tile(Hands[Player].Tiles[j]); if (Danger.Contains(T.TileId)) DangerTiles.Add(T.Index); } return (DangerTiles.Count > 0) ? DangerTiles.ToArray() : null; }
public void Load(string FileName) { FileName = "round/" + FileName; XmlLoad X = new XmlLoad(); if (!X.Load(FileName)) return; this.FileName = FileName; while (X.Read()) { switch (X.ElementName) { case "hash": Hash = X.GetAttribute("value"); break; case "playercount": PlayerCount = X.GetIntAttribute("value"); break; case "lobby": Lobby = X.GetIntAttribute("value"); break; case "lobbytype": LobbyType = (LobbyType)X.GetIntAttribute("value"); break; case "game": Index = X.GetIntAttribute("index"); break; case "round": CurrentRound = X.GetIntAttribute("index"); break; case "result": StringResult = X.GetAttribute("value"); break; case "drawreason": DrawReason = X.GetIntAttribute("value"); break; case "riichistick": RiichiStick = X.GetIntAttribute("value"); break; case "renchanstick": RenchanStick = X.GetIntAttribute("value"); break; case "balancebefore": BalanceBefore = X.ReadIntArray(); break; case "balanceafter": BalanceAfter = X.ReadIntArray(); break; case "pay": Pay = X.ReadIntArray(); break; case "winner": Winner = X.ReadBoolArray(); break; case "loser": Loser = X.ReadBoolArray(); break; case "openedsets": OpenedSets = X.ReadIntArray(); break; case "naki": Naki = X.ReadIntArray(); break; case "riichi": Riichi = X.ReadIntArray(); break; case "dealer": Dealer = X.ReadBoolArray(); break; case "tempai": Tempai = X.ReadBoolArray(); break; case "wind": Wind = X.ReadIntArray(); break; case "stepcount": StepCount = X.ReadIntArray(); break; case "firstdora": FirstDora = X.GetIntAttribute("pointer"); break; case "wall": { if (Wall == null) Wall = new Mahjong.Wall(); Wall.Dice = DecompositeIntList(X.GetAttribute("dice")); Wall.Tiles = DecompositeIntList(X.GetAttribute("tiles")); } break; case "steps": { int Count = X.GetIntAttribute("count"); XmlLoad Subtree = X.GetSubtree(); for (int j = 0; j < Count; j++) { Step NewStep = new Step(-1); NewStep.ReadXml(Subtree); Steps.Add(NewStep); } Subtree.Close(); } break; case "hands": { XmlLoad Subtree = X.GetSubtree(); while (Subtree.Read()) { switch (Subtree.ElementName) { case "hand": { int Player = Subtree.GetIntAttribute("player"); XmlLoad HandData = Subtree.GetSubtree(); StartHands[Player] = new Hand(); StartHands[Player].ReadXml(HandData); HandData.Close(); } break; } } Subtree.Close(); } break; case "shantenlist": { XmlLoad Subtree = X.GetSubtree(); while (Subtree.Read()) { switch (Subtree.ElementName) { case "shanten": { int Player = Subtree.GetIntAttribute("player"); int Count = Subtree.GetIntAttribute("shanten"); XmlLoad ShantenData = Subtree.GetSubtree(); while (ShantenData.Read()) { switch (ShantenData.ElementName) { case "step": { int Value = ShantenData.GetIntAttribute("value"); Shanten[Player].Add(Value); } break; } } ShantenData.Close(); } break; } } Subtree.Close(); } break; case "agari": { int Player = X.GetIntAttribute("player"); HanCount[Player] = X.GetIntAttribute("han"); FuCount[Player] = X.GetIntAttribute("fu"); Cost[Player] = X.GetIntAttribute("cost"); XmlLoad Subtree = X.GetSubtree(); while (Subtree.Read()) { switch (Subtree.ElementName) { case "yakulist": { int Count = Subtree.GetIntAttribute("count"); XmlLoad YakuList = Subtree.GetSubtree(); while (YakuList.Read()) { switch (YakuList.ElementName) { case "yaku": Yaku Y = new Yaku(); Y.Cost = YakuList.GetIntAttribute("cost"); Y.Index = YakuList.GetIntAttribute("index"); Yaku[Player].Add(Y); break; } } YakuList.Close(); } break; case "waitings": { int Count = Subtree.GetIntAttribute("count"); XmlLoad WaitList = Subtree.GetSubtree(); while (WaitList.Read()) { switch (WaitList.ElementName) { case "waiting": WinWaiting[Player].Add(WaitList.GetIntAttribute("value")); break; } } WaitList.Close(); } break; } } Subtree.Close(); } break; case "dora": { int Count = X.GetIntAttribute("count"); Dora.Clear(); XmlLoad Doras = X.GetSubtree(); while (Doras.Read()) { switch (Doras.ElementName) { case "dora": Dora.Add(Doras.GetIntAttribute("pointer")); break; } } Doras.Close(); } break; case "uradora": { int Count = X.GetIntAttribute("count"); UraDora.Clear(); XmlLoad Doras = X.GetSubtree(); while (Doras.Read()) { switch (Doras.ElementName) { case "dora": UraDora.Add(Doras.GetIntAttribute("pointer")); break; } } Doras.Close(); } break; } } }
public Hand(Hand H) { for (int i = 0; i < Tiles.Length; i++) this.Tiles[i] = H.Tiles[i]; for (int i = 0; i < H.Naki.Count; i++) Naki.Add(H.Naki[i]); }
public bool KaratenNotenHand = false; // Waiting only on 5th tile public ShantenCalculator(Hand Hand) { this.Hand = Hand; TehaiCreate(Hand); }