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 int MoveOffUsingSpaces(int from, int fromRow, int to, int remainingSuits, int n) { int suits = Math.Min(remainingSuits, n); if (Diagnostics) { Utils.WriteLine("MOUS: {0} -> {1}: {2}", from, to, suits); } for (int i = n - suits; i < n; i++) { // Move as much as possible but not too much. Pile fromPile = Tableau[from]; int currentFromRow = fromPile.Count - Tableau.GetRunUp(from, fromPile.Count); if (currentFromRow < fromRow) { currentFromRow = fromRow; } int runLength = fromPile.Count - currentFromRow; MakeSimpleMove(from, -runLength, Spaces[i]); MoveStack.Push(new Move(Spaces[i], -runLength, to)); } for (int i = n - 2; i >= n - suits; i--) { int runLength = Tableau[Spaces[i]].Count; MakeSimpleMove(Spaces[i], -runLength, Spaces[n - 1]); MoveStack.Push(new Move(Spaces[n - 1], -runLength, Spaces[i])); } return(suits); }
void UseMovementStack() { GameObject capsule = GameObject.CreatePrimitive(PrimitiveType.Capsule); MoveStack mover = capsule.AddComponent <MoveStack>(); mover.AddMove(Moves.None); mover.AddMove(Moves.Forward); mover.AddMove(Moves.None); mover.AddMove(Moves.None); mover.AddMove(Moves.Right); mover.AddMove(Moves.None); mover.AddMove(Moves.Right); mover.Move(); }
private void UnloadToSpaces(int from, int fromRow, int to) { if (Diagnostics) { Utils.WriteLine("ULTS: {0}/{1} -> {2}", from, fromRow, to); } int numberOfSpaces = Tableau.NumberOfSpaces; int suits = Tableau.CountSuits(from, fromRow); if (suits > ExtraSuits(numberOfSpaces)) { throw new InvalidMoveException("insufficient spaces"); } Spaces.Copy(Tableau.Spaces); int totalSuits = Tableau.CountSuits(from, fromRow); int remainingSuits = totalSuits; int currrentFromRow = Tableau[from].Count; for (int n = 0; n < numberOfSpaces; n++) { int m = Math.Min(numberOfSpaces, n + remainingSuits); for (int i = m - 1; i >= n; i--) { int runLength = Tableau.GetRunUp(from, currrentFromRow); currrentFromRow -= runLength; currrentFromRow = Math.Max(currrentFromRow, fromRow); MakeSimpleMove(from, -runLength, Spaces[i]); MoveStack.Push(new Move(Spaces[i], -runLength, to)); remainingSuits--; } for (int i = n + 1; i < m; i++) { int runLength = Tableau[Spaces[i]].Count; MakeSimpleMove(Spaces[i], -runLength, Spaces[n]); MoveStack.Push(new Move(Spaces[n], -runLength, Spaces[i])); } if (remainingSuits == 0) { break; } } }
/// <summary> /// Synchronizes the Moves and MoveStack lists if the specified move /// is not already in both lists. /// </summary> /// <param name="move">The move to check.</param> private void SyncMoveStack(ISpace move) { // If the move diverges from the move stack, synchronize // the Moves and MoveStack lists. if (Moves.Count > MoveStack.Count) { // The move goes beyond the MoveStack, so add // the move to the MoveStack. MoveStack.Add(move); } else { var stackMove = MoveStack[Moves.Count - 1]; if ((stackMove == null && stackMove != move) || (stackMove != null && !stackMove.Equals(move))) { // The move is different from same position in // the MoveStack, so reset the MoveStack to match // the Moves list. MoveStack = new List <ISpace>(Moves); } } }
/// <summary> /// Returns the game to the state it was in after the specified number of turns. /// </summary> /// <param name="turnCount">The number of turns.</param> /// <returns>A list of the spaces affected by the last move, starting with the space /// of the move and including the spaces of all the pieces captured by the move.</returns> private IAsyncOperation <IList <ISpace> > ResetAsync(int turnCount) { if (turnCount < 0 || turnCount > MoveStack.Count) { throw new ArgumentException("must be 0 or greater and " + "no higher than MoveStack.Count.", "turnCount"); } if (turnCount == Moves.Count) { throw new ArgumentException("must be different than " + "Moves.Count.", "turnCount"); } // Use a lock to prevent this method from modifying the game state at // the same time a different thread is in the locked MoveAsync method. lock (_lockObject) { IList <ISpace> newMoves; if (turnCount < Moves.Count) { // Backward navigation resets the board to its initial state in // preparation for replaying all moves up to the indicated move. SetUpEmptyBoard(); newMoves = Moves.Take(turnCount).ToList(); Moves.Clear(); } else { // Forward navigation retrieves previously-undone moves in // preparation for their replay from the current board state. newMoves = MoveStack.Skip(Moves.Count) .Take(turnCount - Moves.Count).ToList(); } return(MoveAsync(newMoves)); } }
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); } }