private void FindUncoveringMoves(int maxExtraSuits)
 {
     // Find all uncovering moves.
     UncoveringMoves.Clear();
     for (int from = 0; from < NumberOfPiles; from++)
     {
         Pile fromPile = FindTableau[from];
         int  fromRow  = fromPile.Count - RunFinder.GetRunUpAnySuit(from);
         if (fromRow == 0)
         {
             continue;
         }
         int      fromSuits = RunFinder.CountSuits(from, fromRow);
         Card     fromCard  = fromPile[fromRow];
         PileList faceList  = FaceLists[(int)fromCard.Face + 1];
         for (int i = 0; i < faceList.Count; i++)
         {
             HoldingStack.Clear();
             int to = faceList[i];
             if (fromSuits - 1 > maxExtraSuits)
             {
                 int holdingSuits = FindHolding(FindTableau, HoldingStack, false, fromPile, from, fromRow, fromPile.Count, to, maxExtraSuits);
                 if (fromSuits - 1 > maxExtraSuits + holdingSuits)
                 {
                     break;
                 }
             }
             Pile toPile = FindTableau[to];
             Card toCard = toPile[toPile.Count - 1];
             int  order  = GetOrder(toCard, fromCard);
             UncoveringMoves.Add(new Move(from, fromRow, to, order, AddHolding(HoldingStack.Set)));
         }
     }
 }
Esempio n. 2
0
        private int CountUses(Move move)
        {
            if (move.FromRow == 0 || move.ToRow != FindTableau[move.To].Count)
            {
                // No exposed card, no uses.
                return(0);
            }

            int uses = 0;

            Pile fromPile    = FindTableau[move.From];
            Card fromCard    = fromPile[move.FromRow];
            Card exposedCard = fromPile[move.FromRow - 1];

            if (!exposedCard.IsTargetFor(fromCard))
            {
                // Check whether the exposed card will be useful.
                int numberOfSpaces = FindTableau.NumberOfSpaces - 1;
                int maxExtraSuits  = ExtraSuits(numberOfSpaces);
                int fromSuits      = RunFinder.CountSuits(move.From, move.FromRow);
                for (int nextFrom = 0; nextFrom < NumberOfPiles; nextFrom++)
                {
                    if (nextFrom == move.From || nextFrom == move.To)
                    {
                        // Inappropriate column.
                        continue;
                    }
                    Pile nextFromPile = FindTableau[nextFrom];
                    if (nextFromPile.Count == 0)
                    {
                        // Column is empty.
                        continue;
                    }
                    int nextFromRow = nextFromPile.Count - RunFinder.GetRunUpAnySuit(nextFrom);
                    if (!nextFromPile[nextFromRow].IsSourceFor(exposedCard))
                    {
                        // Not the card we need.
                        continue;
                    }
                    int extraSuits = RunFinder.CountSuits(nextFrom, nextFromRow) - 1;
                    if (extraSuits <= maxExtraSuits)
                    {
                        // Card leads to a useful move.
                        uses++;
                    }

                    // Check whether the exposed run will be useful.
                    int upperFromRow = move.FromRow - RunFinder.GetRunUp(move.From, move.FromRow);
                    if (upperFromRow != move.FromRow)
                    {
                        Card upperFromCard = fromPile[upperFromRow];
                        uses += FaceLists[(int)upperFromCard.Face + 1].Count;
                    }
                }
            }
            return(uses);
        }
Esempio n. 3
0
        private void Check(int from, int fromRow, int extraSuits, int maxExtraSuits)
        {
            if (fromRow == 0 && FindTableau.GetDownCount(from) != 0)
            {
                // Would turn over a card.
                return;
            }

            Pile fromPile       = FindTableau[from];
            Card fromCard       = fromPile[fromRow];
            Card fromCardParent = Card.Empty;
            bool inSequence     = true;

            if (fromRow != 0)
            {
                fromCardParent = fromPile[fromRow - 1];
                inSequence     = fromCardParent.IsTargetFor(fromCard);
            }
            HoldingStack fromHoldingStack = HoldingStacks[from];

            for (int to = 0; to < NumberOfPiles; to++)
            {
                Pile toPile = FindTableau[to];
                if (to == from || toPile.Count == 0)
                {
                    continue;
                }
                int splitRow = toPile.Count - RunFinder.GetRunUpAnySuit(to);
                int toRow    = -1;
                if (inSequence)
                {
                    // Try to find from counterpart in the first to run.
                    toRow = splitRow + (int)(toPile[splitRow].Face - fromCard.Face);
                    if (toRow < splitRow || toRow >= toPile.Count)
                    {
                        // Sequence doesn't contain our counterpart.
                        continue;
                    }
                }
                else
                {
                    // Try to swap with both runs out of sequence.
                    toRow = splitRow;
                    if (fromRow != 0 && !fromCardParent.IsTargetFor(toPile[toRow]))
                    {
                        // Cards don't match.
                        continue;
                    }
                }
                if (toRow == 0)
                {
                    if (fromRow == 0)
                    {
                        // No point in swap both entire piles.
                        continue;
                    }
                    if (FindTableau.GetDownCount(to) != 0)
                    {
                        // Would turn over a card.
                        continue;
                    }
                }
                else if (!toPile[toRow - 1].IsTargetFor(fromCard))
                {
                    // Cards don't match.
                    continue;
                }

                int toSuits = RunFinder.CountSuits(to, toRow);
                if (extraSuits + toSuits <= maxExtraSuits)
                {
                    // Swap with no holding piles.
                    Algorithm.ProcessCandidate(new Move(MoveType.Swap, from, fromRow, to, toRow));
                    continue;
                }

                HoldingStack toHoldingStack = HoldingStacks[to];
                if (extraSuits + toSuits > maxExtraSuits + fromHoldingStack.Suits + toHoldingStack.Suits)
                {
                    // Not enough spaces.
                    continue;
                }

                Used.Clear();
                Used.Add(from);
                Used.Add(to);
                int fromHoldingCount = 0;
                int toHoldingCount   = 0;
                int fromHoldingSuits = 0;
                int toHoldingSuits   = 0;
                while (true)
                {
                    if (fromHoldingCount < fromHoldingStack.Count &&
                        fromHoldingStack[fromHoldingCount].FromRow >= fromRow &&
                        !Used.Contains(fromHoldingStack[fromHoldingCount].To))
                    {
                        Used.Add(fromHoldingStack[fromHoldingCount].To);
                        fromHoldingSuits = fromHoldingStack[fromHoldingCount].Suits;
                        fromHoldingCount++;
                    }
                    else if (toHoldingCount < toHoldingStack.Count &&
                             toHoldingStack[toHoldingCount].FromRow >= toRow &&
                             !Used.Contains(toHoldingStack[toHoldingCount].To))
                    {
                        Used.Add(toHoldingStack[toHoldingCount].To);
                        toHoldingSuits = toHoldingStack[toHoldingCount].Suits;
                        toHoldingCount++;
                    }
                    else
                    {
                        // Out of options.
                        break;
                    }
                    if (extraSuits + toSuits > maxExtraSuits + fromHoldingSuits + toHoldingSuits)
                    {
                        // Not enough spaces.
                        continue;
                    }

                    // We've found a legal swap.
                    Debug.Assert(toRow == 0 || toPile[toRow - 1].IsTargetFor(fromCard));
                    Debug.Assert(fromRow == 0 || fromCardParent.IsTargetFor(toPile[toRow]));
                    HoldingSet fromHoldingSet = new HoldingSet(fromHoldingStack, fromHoldingCount);
                    HoldingSet toHoldingSet   = new HoldingSet(toHoldingStack, toHoldingCount);
                    Algorithm.ProcessCandidate(new Move(MoveType.Swap, from, fromRow, to, toRow, AddHolding(fromHoldingSet, toHoldingSet)));
                    break;
                }
            }
        }