private void MakeMove(Node node, int i) { Move move = node.Moves[i]; bool toEmpty = move.Type == MoveType.Basic && WorkingTableau[move.To].Count == 0; MoveStack.Clear(); for (int next = move.HoldingNext; next != -1; next = node.SupplementaryList[next].Next) { Move holdingMove = node.SupplementaryList[next]; WorkingTableau.Move(new Move(MoveType.Basic, MoveFlags.Holding, holdingMove.From, holdingMove.FromRow, holdingMove.To)); int undoTo = holdingMove.From == move.From ? move.To : move.From; MoveStack.Push(new Move(MoveType.Basic, MoveFlags.UndoHolding, holdingMove.To, -holdingMove.ToRow, undoTo)); } WorkingTableau.Move(new Move(move.Type, move.From, move.FromRow, move.To, move.ToRow)); if (!toEmpty) { while (MoveStack.Count > 0) { Move holdingMove = MoveStack.Pop(); if (!WorkingTableau.IsValid(holdingMove)) { break; } WorkingTableau.Move(holdingMove); } } }
private void MakeCompositeSinglePileMove(int first) { if (Diagnostics) { Utils.WriteLine("MCSPM"); } bool aborted = false; int offloadPile = -1; MoveStack.Clear(); for (int next = first; next != -1; next = SupplementaryList[next].Next) { int numberOfSpaces = Tableau.NumberOfSpaces; Move move = Tableau.Normalize(SupplementaryList[next]); if (move.Type == MoveType.Unload) { offloadPile = move.To; UnloadToSpaces(move.From, move.FromRow, -1); } else if (move.Type == MoveType.Reload) { if (Diagnostics) { Utils.WriteLine("RL:"); } while (MoveStack.Count != 0) { Move subMove = MoveStack.Pop(); int to = subMove.To != -1 ? subMove.To : move.To; MakeSimpleMove(subMove.From, subMove.FromRow, to); } offloadPile = -1; } else if (move.Flags.UndoHolding()) { TryMakeMoveUsingSpaces(move); } else { if (!TryMakeMoveUsingSpaces(move)) { // Things got messed up due to a discard. There might // be another pile with the same target. bool foundAlternative = false; Pile fromPile = Tableau[move.From]; if (move.From >= 0 && move.From < fromPile.Count) { Card fromCard = fromPile[move.FromRow]; for (int to = 0; to < NumberOfPiles; to++) { if (to == move.From) { continue; } Pile toPile = Tableau[to]; if (toPile.Count == 0) { continue; } if (!fromCard.IsSourceFor(toPile[toPile.Count - 1])) { continue; } if (TryMakeMoveUsingSpaces(new Move(move.From, move.FromRow, to))) { foundAlternative = true; } break; } } if (!foundAlternative) { // This move is hopelessly messed up. aborted = true; break; } } } } if (!aborted && MoveStack.Count != 0) { throw new Exception("missing reload move"); } }
private void SwapUsingSpaces(int from, int fromRow, int to, int toRow) { if (Diagnostics) { Utils.WriteLine("SWUS: {0}/{1} -> {2}/{3}", from, fromRow, to, toRow); } int fromSuits = Tableau.CountSuits(from, fromRow); int toSuits = Tableau.CountSuits(to, toRow); if (fromSuits == 0 && toSuits == 0) { return; } if (fromSuits == 0) { MakeMoveUsingSpaces(to, toRow, from); return; } if (toSuits == 0) { MakeMoveUsingSpaces(from, fromRow, to); return; } int numberOfSpaces = Tableau.NumberOfSpaces; Spaces.Copy(Tableau.Spaces); if (fromSuits + toSuits - 1 > ExtraSuits(numberOfSpaces)) { throw new InvalidMoveException("insufficient spaces"); } MoveStack.Clear(); for (int n = numberOfSpaces; n > 0 && fromSuits + toSuits > 1; n--) { if (fromSuits >= toSuits) { int moveSuits = toSuits != 0 ? fromSuits : fromSuits - 1; fromSuits -= MoveOffUsingSpaces(from, fromRow, to, moveSuits, n); } else { int moveSuits = fromSuits != 0 ? toSuits : toSuits - 1; toSuits -= MoveOffUsingSpaces(to, toRow, from, moveSuits, n); } } if (fromSuits + toSuits != 1 || fromSuits * toSuits != 0) { throw new Exception("bug: left over swap runs"); } if (fromSuits == 1) { MakeSimpleMove(from, fromRow, to); } else { MakeSimpleMove(to, toRow, from); } while (MoveStack.Count != 0) { Move move = MoveStack.Pop(); MakeSimpleMove(move.From, move.FromRow, move.To); } }