/// <summary> /// Checks to see if it is possible to move the specified <see cref="Card"/> to the specified <see cref="Cascade"/>. /// </summary> /// <param name="card">The <see cref="Card"/> to check if its possible to move to the specified <see cref="Cascade"/></param> /// <param name="cascade">The <see cref="Cascade"/> that will be holding the specified <see cref="Card"/></param> /// <returns><c>true</c> if the specified <see cref="Card"/> can be moved to the specified <see cref="Stack"/>; otherwise <c>false</c></returns> public virtual bool CanMoveToCascade(Card card, Cascade cascade) { if (!EnforceRules) { return(true); } if (cascade.Count == 0) { return(true); } if (DoCardsLinkInCascade(card, cascade.Last())) { return(true); } return(false); }
/// <summary> /// Checks to see if it is possible to move the specified <see cref="Card"/> to the specified <see cref="Cascade"/>. /// </summary> /// <param name="tableaux">The tableaux to try to move to the cascade.</param> /// <param name="cascade">The <see cref="Cascade"/> that will be holding the specified <see cref="Card"/></param> /// <returns><c>true</c> if the specified <see cref="Card"/> can be moved to the specified <see cref="Stack"/>; otherwise <c>false</c></returns> public virtual bool CanMoveToCascade(List <Card> tableaux, Cascade cascade, Game game) { if (!EnforceRules) { return(true); } if (cascade.Count == 0) { return(true); } Card landingCard = cascade.Last(); if (tableaux.Count == 1) { // MOVING ONE CARD if (this.CanMoveToCascade(tableaux.Last(), cascade)) { return(true); } else { return(false); } } else { // MOVING MULTIPLE CARDS... FIND THE MAXIMUM NUMBER OF MOVES AVAILABLE. int maxMoves = Utility.GetMaximumMovesForGame(game, (cascade.Count == 0)); int level = 1; // WALK BACKWARDS OVER TABLEAUX TRYING EACH CARD AS A LINK TO LANDING CARD. for (int i = (tableaux.Count - 1); i >= 0; i--) { // CHECK FOR THE LINK BETWEEN CURRENT TABLEAUX CARD AND LANDING CARD. if (this.DoCardsLinkInCascade(tableaux[i], landingCard)) { // CARDS LINK, CHECK TO SEE IF WE'VE EXCEEDED OUT MAX NUMBER OF MOVES ALLOWED. if (level > maxMoves) { // MAX NUMBER OF MOVES EXCEEDED, MOVE FAILS return(false); } else { // MOVE SUCCESSFUL return(true); } } else { // CARDS DO NOT LINK, CONTINUE ONTO THE NEXT TABLEAUX CARD. if (i == 0) { // THIS IS THE LAST CARD IN THE TABLEAUX, MOVE FAILS BECAUSE NO LINKING CARDS FOUND IN STACK. return(false); } } level++; } } return(false); }
/// <summary> /// Moves the specified source. /// </summary> /// <param name="from">From.</param> /// <param name="to">To.</param> public virtual void Move(ITarget from, ITarget to) { MoveStartedEventArgs args = new MoveStartedEventArgs(from, to); OnMoveStarted(args); if (args.Cancel) { return; } if ((from is Cascade) && (to is Cascade)) { if (((Cascade)from).Count == 0) { throw new InvalidOperationException("There are no cards in the specified cascade to move to other cascade"); } Cascade source = ((Cascade)from); Cascade dest = ((Cascade)to); Card landingCard = dest.LastOrDefault(); List <Card> tableaux = Utility.GetTableauxFromCascade(source, _rules); if (tableaux.Count == 1) { // MOVING ONE CARD if (_rules.CanMoveToCascade(source.Last(), dest)) { dest.Add(source.Last()); source.Remove(source.Last()); OnMoveFinished(MoveFinishedEventArgs.SuccessfulResult); return; } else { OnMoveFinished(MoveFinishedEventArgs.UnlinkingCardsResult); return; } } else { // MOVING MULTIPLE CARDS... FIND THE MAXIMUM NUMBER OF MOVES AVAILABLE. int maxMoves = Utility.GetMaximumMovesForGame(this, (dest.Count == 0)); int level = 1; // WALK BACKWARDS OVER TABLEAUX TRYING EACH CARD AS A LINK TO LANDING CARD. for (int i = (tableaux.Count - 1); i >= 0; i--) { // CHECK FOR THE LINK BETWEEN CURRENT TABLEAUX CARD AND LANDING CARD. if (_rules.DoCardsLinkInCascade(tableaux[i], landingCard)) { // CARDS LINK, CHECK TO SEE IF WE'VE EXCEEDED OUT MAX NUMBER OF MOVES ALLOWED. if (level > maxMoves) { // MAX NUMBER OF MOVES EXCEEDED, MOVE FAILS OnMoveFinished(MoveFinishedEventArgs.NotEnoughFreeSpaceResult); } else { // MOVE CARDS STARTING BY ADDING ALL THE CARDS FROM TABLEAUX AND ADDING THEM TO DESTINATION. for (int j = i; j < tableaux.Count; j++) { dest.Add(tableaux[j]); source.Remove(tableaux[j]); } OnMoveFinished(MoveFinishedEventArgs.SuccessfulResult); return; } } else { // CARDS DO NOT LINK, CONTINUE ONTO THE NEXT TABLEAUX CARD. if (i == 0) { // THIS IS THE LAST CARD IN THE TABLEAUX, MOVE FAILS BECAUSE NO LINKING CARDS FOUND IN STACK. OnMoveFinished(MoveFinishedEventArgs.UnlinkingCardsResult); } } level++; } } } else if ((from is Cascade) && (to is Cell)) { if (((Cascade)from).Count == 0) { throw new InvalidOperationException("There are no cards in the specified cascade to move to cell"); } if (((Cell)to).HasCard) { OnMoveFinished(MoveFinishedEventArgs.OccupiedCellResult); return; } Card movingCard = ((Cascade)from).Last(); ((Cascade)from).Remove(movingCard); ((Cell)to).Card = movingCard; OnMoveFinished(MoveFinishedEventArgs.SuccessfulResult); return; } else if ((from is Cascade) && (to is Foundation)) { if (((Cascade)from).Count == 0) { throw new InvalidOperationException("There are no cards in the specified cascade to move to a foundation"); } Card movingCard = ((Cascade)from).Last(); if (_rules.CanMoveToFoundation(movingCard, ((Foundation)to))) { ((Cascade)from).Remove(movingCard); ((Foundation)to).Add(movingCard); OnMoveFinished(MoveFinishedEventArgs.SuccessfulResult); return; } else { OnMoveFinished(MoveFinishedEventArgs.UnlinkingCardsResult); return; } } else if ((from is Cell) && (to is Cell)) { if (!((Cell)from).HasCard) { throw new InvalidOperationException("There are no cards in the specified cell to move to cell"); } if (((Cell)to).HasCard) { OnMoveFinished(MoveFinishedEventArgs.OccupiedCellResult); return; } else { ((Cell)to).Card = ((Cell)from).Card.Clone(); ((Cell)from).Card = null; OnMoveFinished(MoveFinishedEventArgs.SuccessfulResult); return; } } else if ((from is Cell) && (to is Cascade)) { if (!((Cell)from).HasCard) { throw new InvalidOperationException("There are no cards in the specified cell to move to cascade"); } Cascade cascade = ((Cascade)to); Cell cell = ((Cell)from); if (_rules.CanMoveToCascade(cell.Card, cascade)) { Card movingCard = cell.Card.Clone(); cell.Card = null; cascade.Add(movingCard); OnMoveFinished(MoveFinishedEventArgs.SuccessfulResult); return; } else { OnMoveFinished(MoveFinishedEventArgs.UnlinkingCardsResult); return; } } else if ((from is Cell) && (to is Foundation)) { if (!((Cell)from).HasCard) { throw new InvalidOperationException("There are no cards in the specified cell to move to foundation"); } Card movingCard = ((Cell)from).Card.Clone(); if (_rules.CanMoveToFoundation(movingCard, ((Foundation)to))) { ((Cell)from).Card = null; ((Foundation)to).Add(movingCard); OnMoveFinished(MoveFinishedEventArgs.SuccessfulResult); return; } else { OnMoveFinished(MoveFinishedEventArgs.UnlinkingCardsResult); return; } } else if ((from is Foundation) && (to is Cell)) { if (_rules.AllowMoveFromFoundation) { if (((Foundation)from).Count == 0) { throw new InvalidOperationException("There are no cards in the specified foundation to move to a cell"); } if (((Cell)to).HasCard) { OnMoveFinished(MoveFinishedEventArgs.OccupiedCellResult); return; } else { ((Cell)to).Card = ((Foundation)from).Last(); OnMoveFinished(MoveFinishedEventArgs.SuccessfulResult); return; } } } else if ((from is Foundation) && (to is Cascade)) { if (_rules.AllowMoveFromFoundation) { if (((Foundation)from).Count == 0) { throw new InvalidOperationException("There are no cards in the specified foundation to move to a cascade"); } Card movingCard = ((Foundation)from).Last(); if (_rules.CanMoveToCascade(movingCard, ((Cascade)to))) { ((Foundation)from).Remove(movingCard); ((Cascade)to).Add(movingCard); OnMoveFinished(MoveFinishedEventArgs.SuccessfulResult); return; } else { OnMoveFinished(MoveFinishedEventArgs.UnlinkingCardsResult); return; } } } else if ((from is Foundation) && (to is Foundation)) { throw new InvalidOperationException("You cannot move a card from one foundation to another."); } }