public static HanabiGame OGMod8Strategy(List <HanabiCard> deck = null, bool printMoves = false)
        {
            HanabiGame game = new HanabiGame();

            for (int i = 0; i < game.PlayerCount; i++)
            {
                game.Players[i] = new OGMod8HanabiPlayer(i)
                {
                    ShowPlays = printMoves
                };
            }
            if (deck == null)
            {
                game.CreateDeck();
                game.ShuffleDeck();
            }
            else
            {
                game.Deck = deck.ToList();
            }
            game.DealCards();
            while (!game.Ended)
            {
                (game.CurrentPlayer as OGMod8HanabiPlayer).DoTurn(ref game);
                game.NextTurn();
                if (printMoves)
                {
                    Console.WriteLine(game);
                }
            }
            return(game);
        }
        /// <summary>
        /// A wrapper to launch a version of Hanabi where all players are of type 'Mod8HanabiPlayer' and use advanced logic to make plays in the game.
        /// </summary>
        /// <param name="deck"></param>
        /// <param name="printMoves"></param>
        /// <param name="printGameStatus"></param>
        /// <param name="players"></param>
        /// <returns></returns>
        public static HanabiGame Mod8Strategy(Mod8Settings settings, List <HanabiCard> deck = null, int players = 4, bool printGameStatus = false)
        {
            HanabiGame game = new HanabiGame();

            game.Players = new List <HanabiPlayer>();
            for (int i = 0; i < players; i++)
            {
                game.Players.Add(new Mod8HanabiPlayer(i)
                {
                    Settings = settings
                });
            }
            if (deck == null)
            {
                game.CreateDeck();
                game.ShuffleDeck();
            }
            else
            {
                game.SetDeck(deck);
            }
            game.DealCards();
            while (!game.Ended)
            {
                (game.CurrentPlayer as Mod8HanabiPlayer).DoTurn(ref game);
                game.NextTurn();
                if (printGameStatus)
                {
                    Console.WriteLine(game);
                }
            }
            return(game);
        }
 public override void Action(HanabiGame game, HanabiCard card, bool played, bool successful = true)
 {
     if (ShowPlays)
     {
         Console.WriteLine($" Player {this.ID} {(played ? "Played" : "Discarded")} {card}. {((successful && played) ? "" : "Card was not playable.")}");
     }
 }
 public void DoTurn(ref HanabiGame game)
 {
     if (NextAction.Type == HanabiActionType.Play)
     {
         game.PlayCard(this, NextAction.CardIndex);
         NextAction.Type      = HanabiActionType.Hint;
         NextAction.Card      = null;
         NextAction.CardIndex = -1;
         CardPlayed(ref game);
     }
     else if ((NextAction.Type == HanabiActionType.Discard || NextAction.Type == HanabiActionType.Hint) && game.HintsRemaining > 0)
     {
         GiveClue(ref game);
     }
     else if (NextAction.Type == HanabiActionType.Discard && game.HintsRemaining == 0)
     {
         game.DiscardCard(this, NextAction.CardIndex);
         NextAction.Type      = HanabiActionType.Hint;
         NextAction.Card      = null;
         NextAction.CardIndex = -1;
     }
     else
     {
         game.DiscardCard(this, 0);
         NextAction.Type      = HanabiActionType.Hint;
         NextAction.Card      = null;
         NextAction.CardIndex = -1;
     }
 }
 public static bool IsDangerCard(HanabiGame g, HanabiCard c)
 {
     if (g.PlayedCards.ContainsCard(c))
     {
         return(false);
     }
     else if (c.Number == 5)
     {
         return(true);
     }
     else if (g.DiscardedCards.ContainsCard(c))
     {
         if (c.Number == 1)
         {
             return(g.DiscardedCards.Count(card => card.Color == c.Color && card.Color == c.Color) == 2);
         }
         else
         {
             return(true);
         }
     }
     else
     {
         return(false);
     }
 }
 public static List <HanabiCard> OrderedPlays(HanabiGame game, HanabiPlayer player)
 {
     return(player.Hand.Where(card => game.IsPlayable(card))
            .OrderBy(card => card.Number)
            .ThenBy(card => IsDangerCard(game, card))
            .ThenByDescending(card => player.Hand.IndexOf(card)).ToList());
 }
 //Discard priorities:
 public static IOrderedEnumerable <HanabiCard> OrderedDiscards(HanabiGame game, HanabiPlayer player)
 {
     return(player.Hand.OrderByDescending(card => game.PlayedCards.ContainsCard(card))
            .ThenBy(card => IsDangerCard(game, card))
            .ThenBy(card => player.Hand.Count(p => p.Color == card.Color && p.Number == card.Number) == 2)
            .ThenByDescending(card => card.Number)
            .ThenBy(card => player.Hand.IndexOf(card)));
 }
            /// <summary>
            /// Looks at every player's hand in the game except the current player and checks whether a player has a card that is playable in the
            /// current game state, and adds 1 to the total if they do.
            /// </summary>
            /// <param name="game">The game being played</param>
            /// <returns>Returns the number of players who have playable card.</returns>
            public int PlaysSeen(ref HanabiGame game)
            {
                int total = 0;

                foreach (Mod8HanabiPlayer player in game.Players.Where(p => p != this))
                {
                    total += Logic.PreferredPlay(game, player) == null ? 0 : 1;
                }
                return(total);
            }
Ejemplo n.º 9
0
        public static HanabiGame HintingStrategy(List <HanabiCard> deck = null)
        {
            int[,,] playerknowledge = new int[4, 4, 2];
            HanabiGame game = SetupGame(deck);

            while (!game.Ended)
            {
            }
            return(game);
        }
 public void DoTurn(ref HanabiGame game)
 {
     if (this.NextAction.Type == HanabiActionType.Hint)
     {
         if (game.HintsRemaining == 0)
         {
             var discard = Hand[0];
             game.DiscardCard(this, 0);
             if (game.IsDangerCard(discard))
             {
                 DangerCardDiscarded(ref game);
             }
         }
         else
         {
             GiveClue(ref game);
         }
     }
     else if (NextAction.Type == HanabiActionType.Play)
     {
         if (SeesCollision(ref game) && game.HintsRemaining > 0 && game.BombsUsed >= 2)
         {
             GiveClue(ref game);
         }
         else
         {
             game.PlayCard(this, NextAction.CardIndex);
             NextAction.Type      = HanabiActionType.Hint;
             NextAction.Card      = null;
             NextAction.CardIndex = -1;
         }
     }
     else // Must be discard
     {
         if (PlaysSeen(ref game) >= 2 && game.HintsRemaining > 0)
         {
             GiveClue(ref game);
         }
         else if (SeesCollision(ref game) && game.HintsRemaining > 0)
         {
             GiveClue(ref game);
         }
         else
         {
             game.DiscardCard(this, NextAction.CardIndex);
             if (game.IsDangerCard(NextAction.Card))
             {
                 DangerCardDiscarded(ref game);
             }
             NextAction.Type      = HanabiActionType.Hint;
             NextAction.Card      = null;
             NextAction.CardIndex = -1;
         }
     }
 }
 /// <summary>
 /// Triggers every time the the player plays/discards a card
 /// </summary>
 /// <param name="card">The card that the action was on.</param>
 /// <param name="played">Whether or no the card was played or discarded. True = Played, False = Discarded.</param>
 /// <param name="successful">Whether the card, if played, was played successfully or used a bomb.</param>
 public override void Action(HanabiGame game, HanabiCard card, bool played, bool successful = true)
 {
     if (Settings.PrintMoves && Settings.PrintInfoWithMoves)
     {
         Console.WriteLine($" Player {this.ID} {(played ? "Played" : "Discarded")} {card}. {((successful && played) ? "" : "Card was not playable.")} Hints: {game.HintsRemaining} Bombs: {game.BombsUsed}");
     }
     else if (Settings.PrintMoves)
     {
         Console.WriteLine($" Player {this.ID} {(played ? "Played" : "Discarded")} {card}. {((successful && played) ? "" : "Card was not playable.")}");
     }
 }
 public void DangerCardDiscarded(ref HanabiGame game)
 {
     for (int i = 0; i < game.PlayerCount; i++)
     {
         if ((game.Players[i] as Mod8HanabiPlayer).NextAction.Type == HanabiActionType.Discard)
         {
             (game.Players[i] as Mod8HanabiPlayer).NextAction.Type      = HanabiActionType.Hint;
             (game.Players[i] as Mod8HanabiPlayer).NextAction.Card      = null;
             (game.Players[i] as Mod8HanabiPlayer).NextAction.CardIndex = -1;
         }
     }
 }
            public void SetActionFromClue(HanabiPlayer cluer, ref HanabiGame game, int clueValue)
            {
                int seenvalue = 0;

                foreach (Mod8HanabiPlayer player in game.Players.Where(p => p != this && p != cluer))
                {
                    seenvalue += player.EvaluateHand(ref game).ToMod8Value();
                }
                int personalvalue = PosMod((clueValue - seenvalue), 8);

                this.NextAction = HanabiAction.FromMod8Value(this, personalvalue);
            }
            public HanabiAction EvaluateHand(ref HanabiGame game)
            {
                var preferredplay = Logic.PreferredPlay(game, this);

                if (preferredplay != null)
                {
                    return(new HanabiAction(HanabiActionType.Play, preferredplay, this.PositionInHand(preferredplay)));
                }
                var discard = Logic.PreferredDiscard(game, this);

                return(new HanabiAction(HanabiActionType.Discard, discard, this.PositionInHand(discard)));
            }
            public static HanabiCard PreferredPlay(HanabiGame game, HanabiPlayer player)
            {
                var playableCards = OrderedPlays(game, player);

                if (playableCards.Count == 0)
                {
                    return(null);
                }
                else
                {
                    return(playableCards[0]);
                }
            }
 public void CardPlayed(ref HanabiGame game)
 {
     if (game.BombsUsed >= 2)
     {
         for (int i = 0; i < game.PlayerCount; i++)
         {
             if ((game.Players[i] as OGMod8HanabiPlayer).NextAction.Type == HanabiActionType.Play)
             {
                 (game.Players[i] as OGMod8HanabiPlayer).NextAction.Type      = HanabiActionType.Hint;
                 (game.Players[i] as OGMod8HanabiPlayer).NextAction.Card      = null;
                 (game.Players[i] as OGMod8HanabiPlayer).NextAction.CardIndex = -1;
             }
         }
     }
 }
        private static HanabiGame SetupGame(List <HanabiCard> deck)
        {
            HanabiGame game = new HanabiGame()
            {
                Deck = deck
            };

            if (deck == null)
            {
                game.CreateDeck();
                game.ShuffleDeck();
            }
            game.DealCards();
            return(game);
        }
            public void GeneralLieClue(ref HanabiGame game, Mod8HanabiPlayer player, List <HanabiAction> badactions, int remainingclue)
            {
                var          badplays        = badactions.Select(a => a.Card).ToList();
                var          plays           = player.GetPlayableCards(game).Where(p => badplays.Count(c => c.Number == p.Number && c.Color == p.Color) == 0).ToList();
                var          ordereddiscards = Logic.OrderedDiscards(game, player);
                var          discards        = ordereddiscards.Where(p => badplays.Count(c => c.Number == p.Number && c.Color == p.Color) != 1 || ordereddiscards.Count(c => c.Number == p.Number && c.Color == p.Color) > 1).ToList();
                HanabiAction desiredclue     = null;

                if (plays.Count == 0)
                {
                    desiredclue = new HanabiAction(HanabiActionType.Discard, discards[0], player.Hand.LastIndexOf(discards[0]));
                }
                else
                {
                    desiredclue = new HanabiAction(HanabiActionType.Play, plays[0], player.Hand.IndexOf(plays[0]));
                }
                if (badactions.Count > 10)
                {
                    return;
                }
                if (Settings.EnsureProperClues)
                {
                    int newclue = PosMod(desiredclue.ToMod8Value() + remainingclue, 8);
                    if (IsValidClue(ref game, newclue))
                    {
                        (game.Players[player.ID] as Mod8HanabiPlayer).NextAction = desiredclue;
                        if (Settings.PrintMoves)
                        {
                            Console.WriteLine($"Player {ID} lied and gave a hint to {desiredclue.Type} { (game.Players[player.ID] as Mod8HanabiPlayer).NextAction.Card}");
                        }
                    }
                    else
                    {
                        badactions.Add(desiredclue);
                        GeneralLieClue(ref game, player, badactions, remainingclue);
                    }
                }
                else
                {
                    (game.Players[player.ID] as Mod8HanabiPlayer).NextAction = desiredclue;
                    if (Settings.PrintMoves)
                    {
                        Console.WriteLine($"Player {ID} lied and gave a hint to {desiredclue.Type} { (game.Players[player.ID] as Mod8HanabiPlayer).NextAction.Card}");
                    }
                }
            }
            public HanabiAction EvaluateHand(HanabiGame game)
            {
                var preferredplay = Hand.Where(c => game.IsPlayable(c))
                                    .OrderBy(c => c.Number == 5)
                                    .ThenBy(c => c.Number)
                                    .ThenBy(c => Hand.IndexOf(c)).ToArray();

                if (preferredplay.Length != 0)
                {
                    return(new HanabiAction(HanabiActionType.Play, preferredplay[0], Hand.IndexOf(preferredplay[0])));
                }
                var preferreddiscard = Hand.OrderByDescending(c => game.PlayedCards.ContainsCard(c))
                                       .ThenBy(c => Logic.IsDangerCard(game, c))
                                       .ThenByDescending(c => c.Number)
                                       .ThenBy(c => Hand.IndexOf(c)).ToArray();

                return(new HanabiAction(HanabiActionType.Discard, preferreddiscard[0], Hand.IndexOf(preferreddiscard[0])));
            }
            public void GiveClue(ref HanabiGame game)
            {
                List <HanabiAction> evaluations = new List <HanabiAction>();

                foreach (OGMod8HanabiPlayer player in game.Players.Where(p => p != this))
                {
                    evaluations.Add(player.EvaluateHand(game));
                }
                int cluevalue = PosMod(evaluations.Select(e => e.ToMod8Value()).Sum(), 8);

                for (int i = 0; i < game.PlayerCount; i++)
                {
                    var player = game.Players[i];
                    if (player != this)
                    {
                        (game.Players[i] as OGMod8HanabiPlayer).SetActionFromClue(this, ref game, cluevalue);
                    }
                }
                game.GiveHint();
                this.NextAction = new HanabiAction(HanabiActionType.Hint, null, -1);
            }
            public bool SeesCollision(ref HanabiGame game, int forwardplayers = 2)
            {
                var nextplayer     = game.NextPlayer as Mod8HanabiPlayer;
                var nextnextplayer = game.Players[(game.PlayerTurn + 2) % game.PlayerCount] as Mod8HanabiPlayer;

                if (nextplayer.NextAction.Type == HanabiActionType.Play)
                {
                    if (!game.IsPlayable(nextplayer.NextAction.Card))
                    {
                        return(true);
                    }
                }
                if (nextplayer.NextAction.Type == HanabiActionType.Play && nextnextplayer.NextAction.Type == HanabiActionType.Play)
                {
                    if (nextplayer.NextAction.Card.Number == nextnextplayer.NextAction.Card.Number && nextplayer.NextAction.Card.Color == nextnextplayer.NextAction.Card.Color)
                    {
                        return(true);
                    }
                }
                return(false);
            }
        public static HanabiGame RandomStrategy(List <HanabiCard> deck = null)
        {
            HanabiGame game = new HanabiGame()
            {
                Deck = deck
            };

            if (deck == null)
            {
                game.CreateDeck();
                game.ShuffleDeck();
            }
            game.DealCards();
            Random rng = new Random();

            while (!game.Ended)
            {
                var player   = game.CurrentPlayer;
                var playcard = player.Hand[rng.Next() % player.Hand.Count];
                game.PlayCard(player, player.Hand.LastIndexOf(playcard));
            }
            return(game);
        }
        public static HanabiGame BasicCheatingStrategy(List <HanabiCard> deck = null)
        {
            HanabiGame game = new HanabiGame()
            {
                Deck = deck
            };

            if (deck == null)
            {
                game.CreateDeck();
                game.ShuffleDeck();
            }
            game.DealCards();
            while (!game.Ended)
            {
                var play = Logic.PreferredPlay(game, game.CurrentPlayer);
                if (play != null)
                {
                    game.PlayCard(game.CurrentPlayer, game.CurrentPlayer.Hand.IndexOf(play));
                }
                else
                {
                    var discard = Logic.PreferredDiscard(game, game.CurrentPlayer);
                    (HanabiCard c1, HanabiCard c2) = (new HanabiCard(discard.Number - 1, discard.Color), new HanabiCard(discard.Number - 2, discard.Color));
                    if (game.Players.Select(p => p.Hand).Count(h => h.ContainsCard(c1) || h.ContainsCard(c2)) >= 1 && game.HintsRemaining > 0) //If the cards necessary to play this one are in people's hands already.
                    {
                        game.HintsRemaining--;
                    }
                    else
                    {
                        game.DiscardCard(game.CurrentPlayer, game.CurrentPlayer.Hand.IndexOf(discard));
                    }
                }
                game.NextTurn();
            }
            return(game);
        }
 public IEnumerable <HanabiCard> GetPlayableCards(HanabiGame game)
 {
     return(Hand.Where(c => game.IsPlayable(c)));
 }
            public static HanabiCard PreferredDiscard(HanabiGame game, HanabiPlayer player)
            {
                var discards = OrderedDiscards(game, player).ToList();

                return(discards[0]);
            }
            /// <summary>
            /// Called when someone wants to give a clue on their turn.
            /// </summary>
            /// <param name="game"></param>
            public void GiveClue(ref HanabiGame game)
            {
                bool cluegiven = false;
                List <HanabiAction> evaluations = new List <HanabiAction>();

                foreach (Mod8HanabiPlayer player in game.Players.Where(p => p != this).OrderBy(p => p.ID))
                {
                    evaluations.Add(player.EvaluateHand(ref game));
                }

                int cluevalue             = PosMod(evaluations.Select(e => e.ToMod8Value()).Sum(), 8);
                List <HanabiAction> plays = evaluations.Where(a => a.Type == HanabiActionType.Play).ToList();

                if (!IsValidClue(ref game, cluevalue))
                {
                    game.BadClues++;
                    if (Settings.EnsureProperClues)
                    {
                        GeneralLieClue(ref game, game.NextPlayer as Mod8HanabiPlayer, plays, PosMod(cluevalue - (game.NextPlayer as Mod8HanabiPlayer).NextAction.ToMod8Value(), 8));
                        cluegiven = true;
                    }
                }

                List <HanabiCard> playcards = new List <HanabiCard>();

                for (int i = 0; i < game.PlayerCount; i++)
                {
                    var player = game.Players[i];
                    if (player != this)
                    {
                        (game.Players[i] as Mod8HanabiPlayer).SetActionFromClue(this, ref game, cluevalue);
                    }
                }
                hints[cluevalue]++;
                if (Settings.CollisionLying)
                {
                    var cluedplays = evaluations.Where(a => a.Type == HanabiActionType.Play).Select(a => a.Card).ToList();
                    var nextplayer = game.NextPlayer as Mod8HanabiPlayer;
                    if (nextplayer.NextAction.Type == HanabiActionType.Play)
                    {
                        var cluedplay = nextplayer.NextAction.Card;
                        foreach (HanabiCard card in cluedplays)
                        {
                            if (cluedplays.Count(c => c.Color == card.Color && c.Number == card.Number) >= 2 && nextplayer.NextAction.Card.Color == card.Color && nextplayer.NextAction.Card.Number == card.Number)
                            {
                                HanabiAction[] bad = { nextplayer.NextAction };
                                CollisionLieClue(ref game, nextplayer, plays, PosMod(cluevalue - nextplayer.NextAction.ToMod8Value(), 8));
                                cluegiven = true;
                                break;
                            }
                        }
                    }
                }
                if (Settings.PrintMoves && !cluegiven)
                {
                    Console.WriteLine($"Player {ID} gave a hint.");
                }
                //Once the hint has been decided, make sure the game uses up a hint
                game.GiveHint();
                this.NextAction = new HanabiAction(HanabiActionType.Hint, null, -1);
            }
            public bool IsValidClue(ref HanabiGame game, int clue)
            {
                var nnextplayer = game.Players[(game.PlayerTurn + 2) % game.PlayerCount];

                if (clue % 2 == 1)
                {
                    return(true);
                }
                if (clue >= 4)
                {
                    if ((clue % 4) - (clue % 2) == 0)
                    {
                        var num = game.NextPlayer.Hand[0].Number;
                        if (game.NextPlayer.Hand.Count(c => c.Number == num) == 4)
                        {
                            return(false);
                        }
                        else
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        var num = game.NextPlayer.Hand[0].Color;
                        if (game.NextPlayer.Hand.Count(c => c.Color == num) == 4)
                        {
                            return(false);
                        }
                        else
                        {
                            return(true);
                        }
                    }
                }
                else
                {
                    if ((clue % 4) - (clue % 2) == 0)
                    {
                        var num = nnextplayer.Hand[0].Number;
                        if (nnextplayer.Hand.Count(c => c.Number == num) == 4)
                        {
                            return(false);
                        }
                        else
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        var num = nnextplayer.Hand[0].Color;
                        if (nnextplayer.Hand.Count(c => c.Color == num) == 4)
                        {
                            return(false);
                        }
                        else
                        {
                            return(true);
                        }
                    }
                }
            }
Ejemplo n.º 28
0
 public override void Action(HanabiGame game, HanabiCard card, bool played, bool successful = true)
 {
     base.Action(game, card, played, successful);
 }
Ejemplo n.º 29
0
 public virtual void Action(HanabiGame game, HanabiCard card, bool played, bool successful = true)
 {
 }