/// <summary> /// Raises the <see cref="E:MoveStarted"/> event. /// </summary> /// <param name="args">The <see cref="FreeCell.Core.MoveStartedEventArgs"/> instance containing the event data.</param> public void OnMoveStarted(MoveStartedEventArgs args) { if (MoveStarted != null) { MoveStarted(this, args); } }
/// <summary> /// Raises the <see cref="E:MoveStarted"/> event. /// </summary> /// <param name="args">The <see cref="FreeCell.Core.MoveStartedEventArgs"/> instance containing the event data.</param> public void OnMoveStarted(MoveStartedEventArgs args) { if (MoveStarted != null) MoveStarted(this, args); }
/// <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."); } }
/// <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."); } }