/// <summary> /// Determines the next move for this AI to make. /// </summary> /// <param name="state">The state of the game. This will be cloned so that the AI does not affect the actual game state.</param> /// <returns>Returns the next move to make based on the current game state.</returns> public MahjongMove GetNextMove(GameState <MahjongMove> state) { MahjongGameState s = state as MahjongGameState; MahjongAIPlayer ai = state.GetPlayer(Player) as MahjongAIPlayer; MahjongPlayer mp = ai as MahjongPlayer; // Pass if it's not this AI's turn if (s.ActivePlayer != Player) { return(new MahjongMove()); } if (MahjongStaticFunctions.HasMahjong(ai.CardsInHand, mp.Melds)) { return(new MahjongMove(true)); } // Pick a random tile to discard int r = rand.Next(0, (int)ai.CardsInHand.CardsInHand); rc++; return(new MahjongMove(ai.CardsInHand.Cards[r])); }
/// <summary> /// Determines the next move for this AI to make. /// </summary> /// <param name="state">The state of the game. This will be cloned so that the AI does not affect the actual game state.</param> /// <returns>Returns the next move to make based on the current game state.</returns> public MahjongMove GetNextMove(GameState <MahjongMove> state) { MahjongGameState s = state as MahjongGameState; MahjongAIPlayer ai = state.GetPlayer(Player) as MahjongAIPlayer; MahjongPlayer mp = ai as MahjongPlayer; // Pass if it's not this AI's turn and it can't meld a pung or kong if (s.ActivePlayer != Player) { if (s.AvailableTile == null) { return(new MahjongMove()); // The active player is going out, so there's nothing we can do } else { switch (ai.CardsInHand.CountCard(s.AvailableTile)) { case 1: // If this is the last tile we needed to declare mahjong, go for it if (ai.CardsInHand.CardsInHand == 1) { List <Card> eye = new List <Card>(); eye.Add(s.AvailableTile.Clone()); eye.Add(s.AvailableTile.Clone()); return(new MahjongMove(new MahjongMeld(eye, false), s.AvailableTile, true)); } // Pass otherwise return(new MahjongMove()); case 2: List <Card> p2 = new List <Card>(); p2.Add(s.AvailableTile.Clone()); p2.Add(s.AvailableTile.Clone()); p2.Add(s.AvailableTile.Clone()); Hand htemp2 = new StandardHand(ai.CardsInHand.Cards); htemp2.PlayCard(s.AvailableTile); htemp2.PlayCard(s.AvailableTile); MahjongMeld m2 = new MahjongMeld(p2, false); List <MahjongMeld> melds2 = new List <MahjongMeld>(); foreach (MahjongMeld m22 in mp.Melds) { melds2.Add(m22.Clone()); } return(new MahjongMove(m2, s.AvailableTile, MahjongStaticFunctions.HasMahjong(htemp2, melds2))); case 3: List <Card> p3 = new List <Card>(); p3.Add(s.AvailableTile.Clone()); p3.Add(s.AvailableTile.Clone()); p3.Add(s.AvailableTile.Clone()); p3.Add(s.AvailableTile.Clone()); Hand htemp3 = new StandardHand(ai.CardsInHand.Cards); htemp3.PlayCard(s.AvailableTile); htemp3.PlayCard(s.AvailableTile); htemp3.PlayCard(s.AvailableTile); MahjongMeld m3 = new MahjongMeld(p3, false); List <MahjongMeld> melds3 = new List <MahjongMeld>(); foreach (MahjongMeld m33 in mp.Melds) { melds3.Add(m33.Clone()); } return(new MahjongMove(m3, s.AvailableTile, MahjongStaticFunctions.HasMahjong(htemp3, melds3))); default: return(new MahjongMove()); // If we naturally drew a kong, it'll stick around until we're forced to discard one of the tiles or just lose } } } // If it's our turn, check if we have mahjong if (MahjongStaticFunctions.HasMahjong(ai.CardsInHand, mp.Melds)) { return(new MahjongMove(true)); } // Find all the singletons List <int> singletons = new List <int>(); for (int i = 0; i < ai.CardsInHand.CardsInHand; i++) { if (ai.CardsInHand.CountCard(ai.CardsInHand.Cards[i]) == 1) { singletons.Add(i); } } // If we don't have a singleton tile, we'll have to part with another if (singletons.Count == 0) { singletons.Add(rand.Next(0, (int)ai.CardsInHand.CardsInHand)); rc++; } // Pick a random singleton tile to discard int r = rand.Next(0, singletons.Count); rc++; return(new MahjongMove(ai.CardsInHand.Cards[r])); }