private void BoardController_OnBoardUpdate(BoardModel Board)
        {
            // Lookup Changes
            //if (LookUpNewDeckCard)
            //{
            var NewDeckCard = Board.DeckCard;

            StateController.DeckCard = NewDeckCard;
            //}

            if (LookUpBottomCardIndex >= 0)
            {
                CardModel NewUncoveredCard = null;

                foreach (var Card in Board.Bottom)
                {
                    if (Card != null)
                    {
                        if (!KnownCards.Contains(Card.Type))
                        {
                            NewUncoveredCard = Card;
                        }
                    }
                }

                if (NewUncoveredCard == null)
                {
                    return;
                }

                if (!HasUncoveredCard)
                {
                    for (int i = StateController.Bottom[LookUpBottomCardIndex].Count - 1; i >= 0; i--)
                    {
                        if (StateController.Bottom[LookUpBottomCardIndex][i].Uncovered == false)
                        {
                            StateController.Bottom[LookUpBottomCardIndex][i] = NewUncoveredCard;
                            UncoveredCardIndex = i;
                            HasUncoveredCard   = true;
                            break;
                        }
                    }
                }

                StateController.Bottom[LookUpBottomCardIndex][UncoveredCardIndex] = NewUncoveredCard;
                FoundBottomCard = true;
            }
        }
        public void UpdateBoardWithObservations(CvModel[] Observations)
        {
            lock (mutex)
            {
                Transformer.GetBoardState(Observations);
                LastDeterminedBoardModels[CurrentDeterminedBoardModelIndex++] = Transformer.GetBoardState(Observations);
                if (CurrentDeterminedBoardModelIndex > ConsistencyBuffer - 1)
                {
                    BufferFull = true;
                    CurrentDeterminedBoardModelIndex = 0;
                }

                if (CurrentDeterminedBoardModelIndex % ConsistencyUpdatesPerCheck == 0 && BufferFull)
                {
                    // Check for most agreed consistent data
                    var dict = new Dictionary <BoardModel, int>();

                    foreach (var value in LastDeterminedBoardModels)
                    {
                        if (dict.ContainsKey(value))
                        {
                            dict[value]++;
                        }
                        else
                        {
                            dict[value] = 1;
                        }
                    }

                    KeyValuePair <BoardModel, int> MostOccuredModel = new KeyValuePair <BoardModel, int>(new BoardModel(), 0);
                    foreach (var pair in dict)
                    {
                        if (pair.Key.CardsOnBoard() >= MostOccuredModel.Key.CardsOnBoard())
                        {
                            if (pair.Value > MostOccuredModel.Value && pair.Value > MinConsistencyRequired)
                            {
                                MostOccuredModel = pair;
                            }
                        }
                    }

                    Board = MostOccuredModel.Key;
                    OnBoardUpdate?.Invoke(Board);
                }
            }
        }
        private void StateController_OnInitialized(BoardModel Board)
        {
            // Add all aldready observed cards..
            KnownCards.Add(Board.DeckCard.Type);

            foreach (var Card in Board.Bottom)
            {
                if (Card != default && Card.Uncovered)
                {
                    KnownCards.Add(Card.Type);
                }
            }
            foreach (var Card in Board.Top)
            {
                if (Card != default && Card.Uncovered)
                {
                    KnownCards.Add(Card.Type);
                }
            }
        }
        public void InitializeBoard(BoardModel StartBoard)
        {
            for (int i = 0; i < StartBoard.Bottom.Length; i++)
            {
                if (StartBoard.Bottom[i] != default)
                {
                    Bottom[i].Add(StartBoard.Bottom[i]);
                }
            }

            for (int i = 0; i < StartBoard.Top.Length; i++)
            {
                if (StartBoard.Top[i] != default)
                {
                    Top[i].Add(StartBoard.Bottom[i]);
                }
            }

            DeckCard = StartBoard.DeckCard;
            OnInitialized?.Invoke(StartBoard);
        }
 public void UpdateBoardState(BoardModel CurrentState)
 {
     OnDeckChanged?.Invoke(GetDeckCard(), GetTopDeck(), GetBottomDeck(), CurrentState);
 }
        private bool MoveAceToColorStack(CardModel DeckCard, List <CardModel>[] ColorDeck, List <CardModel>[] Deck, BoardModel Board)
        {
            for (int i = 6; i >= 0; i--)
            {
                int CardIndex = 0;
                foreach (var Card in Deck[i])
                {
                    if (IsAce(Card))
                    {
                        if (Deck[i].Count(c => c.Uncovered) > 0) // Dont try to lookup a new card in a deck that has no uncovered cards
                        {
                            LookUpBottomCardIndex = i;
                            Moves.Add($"Uncover New Card");
                        }

                        MoveCardToTop(i, DetermineTopPosition(Card), CardIndex);
                        return(true);
                    }

                    CardIndex++;
                }
            }

            if (IsAce(DeckCard))
            {
                LookUpNewDeckCard = true;
                Moves.Add($"Move {GetCardName(DeckCard)} to Color Stack");
                Moves.Add($"Draw a new card from deck.");
                StateController.Top[DetermineTopPosition(DeckCard)].Add(DeckCard);
                StateController.DeckCard = null;
                return(true);
            }

            return(false);
        }
        private void StateController_OnDeckChanged(CardModel DeckCard, List <CardModel>[] ColorDeck, List <CardModel>[] Deck, BoardModel Board)
        {
            // Add all aldready observed cards..

            /*
             * foreach (var Card in Board.Bottom)
             *  if (Card != default && Card.Uncovered)
             *      if (!KnownCards.Contains(Card.Type))
             *          KnownCards.Add(Card.Type);
             * foreach (var Card in Board.Top)
             *  if (Card != default && Card.Uncovered)
             *      if (!KnownCards.Contains(Card.Type))
             *          KnownCards.Add(Card.Type);
             *
             * if (Board.DeckCard != default && Board.DeckCard.Type != default)
             *  if (!KnownCards.Contains(Board.DeckCard.Type))
             *      KnownCards.Add(Board.DeckCard.Type);
             */

            // If we have a new card discovered add it to the known cards
            if (LookUpBottomCardIndex >= 0)
            {
                for (int i = StateController.Bottom[LookUpBottomCardIndex].Count - 1; i >= 0; i--)
                {
                    if (StateController.Bottom[LookUpBottomCardIndex][i].Uncovered)
                    {
                        if (!KnownCards.Contains(StateController.Bottom[LookUpBottomCardIndex][i].Type))
                        {
                            KnownCards.Add(StateController.Bottom[LookUpBottomCardIndex][i].Type);
                        }
                    }
                }
            }

            if (LookUpNewDeckCard)
            {
                if (!KnownCards.Contains(Board.DeckCard.Type))
                {
                    KnownCards.Add(Board.DeckCard.Type);
                }
            }

            // Reset Lookup Variables
            HasUncoveredCard      = false;
            LookUpNewDeckCard     = false;
            LookUpBottomCardIndex = -1;
            UncoveredCardIndex    = -1;
            FoundBottomCard       = false;

            // Check if game has finished
            bool HasNotFinished = false;

            for (int i = 0; i < 4; i++)
            {
                if (StateController.Top.Count() != 13)
                {
                    HasNotFinished = true;
                    break;
                }
            }

            if (!HasNotFinished) // Finished
            {
                MessageBox.Show("The game has finished!", "Finished");
                return;
            }

            // If there is an Ace then move it to color stack
            if (MoveAceToColorStack(DeckCard, ColorDeck, Deck, Board))
            {
                goto End;
            }

            // Get all moves we can do!
            var AllMoves = GetAllMoves();

            // No more moves
            if (AllMoves.Count == 0)
            {
                Moves.Add("Turn a deck card");
                LookUpNewDeckCard = true;
                goto End;
            }

            // Find the move with most covered cards in it
            CardMove MoveWithMostCoveredCards = default;
            int      CoveredCardCount         = -1;

            foreach (var Move in AllMoves)
            {
                // Find how much covered shit we have
                if (CoveredCardCount == -1 && Move.FromPosition == -1)
                {
                    MoveWithMostCoveredCards = Move;
                }
                ;

                if (Move.FromPosition == -1)
                {
                    continue;
                }

                var CurrentCoveredCards = StateController.Bottom[Move.FromPosition].Count(c => !c.Uncovered);
                if (CurrentCoveredCards > CoveredCardCount)
                {
                    MoveWithMostCoveredCards = Move;
                    CoveredCardCount         = CurrentCoveredCards;
                }
            }

            // Perform shit move
            if (MoveWithMostCoveredCards.MoveToTop)
            {
                MoveCardToTop(MoveWithMostCoveredCards.FromPosition, MoveWithMostCoveredCards.ToPosition, MoveWithMostCoveredCards.CardIndex);
            }
            else
            {
                MoveCardBottom(MoveWithMostCoveredCards.FromPosition, MoveWithMostCoveredCards.ToPosition, MoveWithMostCoveredCards.CardIndex);
            }

End:
            SaveMoves();
        }