/// <summary> /// Coloca la partida en un movimiento /// </summary> internal void GoToMovement(MovementFigureViewModel movementViewModel) { bool end = false; List <ActionBaseModel> actions = new List <ActionBaseModel>(); // Limpia el tablero Reset(); // Realiza los movimientos while (!end) { MovementFigureModel movement = GetNextMovement(); if (movement == null) { end = true; } else { // Acumula las acciones actions.AddRange(MakeMovement(movement)); // Si estamos en el movimiento buscado, terminamos if (movementViewModel.Movement == ActualMovement || ActualMovementIndex >= ActualVariationGame.Movements.Count) { // Selecciona el movimiento en la lista MovementsList.SelectMovement(ActualMovement); // Indica que ha terminado end = true; } } } // Ejecuta las acciones RaiseEventShowMovements(actions, false); }
public MovementFigureViewModel(MovementListViewModel movementListViewModel, MovementFigureModel movement, int movementIndex, int variationIndex) { // Inicializa las propiedades MovementListViewModel = movementListViewModel; VariationIndex = variationIndex; Selected = false; Piece = movement.OriginPiece; Color = movement.Color; MovementIndex = movementIndex; Movement = movement; Text = movement.Content; HasVariation = movement.Variations.Count > 0; Time = "01:07"; // Añade las variaciones VariationsList = new MovementListSelectVariationViewModel(movement); // Añade los comentarios Remarks = new ObservableCollection <MovementRemarkViewModel>(); foreach (string comment in movement.Comments) { Remarks.Add(new MovementRemarkViewModel(comment)); RemarksText += comment + Environment.NewLine; } HasRemarks = Remarks.Count > 0; // Inicializa la forma en que se debe ver el movimiento en la lista (tamaños de fuente, tamaños de imagen...) AssignViewSizes(variationIndex); // Inicializa los comandos SelectMovementCommand = new Mvvm.BaseCommand(parameter => ExecuteMovement(), parameter => CanExecuteMovement()); }
/// <summary> /// Convierte un movimiento de pieza /// </summary> private MovementFigureModel ConvertPieceMovement(PieceMovementModel movement) { MovementFigureModel movementFigure = new MovementFigureModel(ConvertTurn(movement.Turn), movement.Content); // Convierte los datos básicos ConvertMovementBase(movement, movementFigure); // Añade las variaciones (antes de mover real) foreach (VariationModel variation in movement.Variations) { movementFigure.Variations.Add(ConvertVariation(variation, movementFigure)); } // Convierte el color de la figura if (movement.Turn.Type == TurnModel.TurnType.White) { movementFigure.Color = PieceBaseModel.PieceColor.White; } else { movementFigure.Color = PieceBaseModel.PieceColor.Black; } // Convierte los datos de la notación SAN ConvertSan(movementFigure, movement.Content); // Devuelve el movimiento return(movementFigure); }
/// <summary> /// Crea las acciones necesarias para deshacer un movimiento /// </summary> private List <ActionBaseModel> CreateUndoMoveActions(MovementFigureModel movement) { List <ActionBaseModel> actions = new List <ActionBaseModel>(); // Deshace la promoción if (movement.PromotedPiece != null) { // Elimina la pieza promocionada actions.Add(CreateCaptureAction(movement.PromotedPiece ?? PieceBaseModel.PieceType.Queen, movement.Color, movement.To)); // Crea de nuevo el peón en el mismo lugar que la pieza promocionada actions.Add(CreatePromoteAction(PieceBaseModel.PieceType.Pawn, movement.Color, movement.To)); } // Deshace el movimiento actions.Add(CreateMoveAction(movement.OriginPiece, movement.Color, movement.To, movement.From)); // Crea de nuevo la pieza capturada if (movement.Type == MovementFigureModel.MovementType.Capture) { if (movement.CapturedEnPassant != null) { actions.Add(CreatePromoteAction(movement.Captured.Type, movement.Captured.Color, movement.CapturedEnPassant)); } else { actions.Add(CreatePromoteAction(movement.Captured.Type, movement.Captured.Color, movement.To)); } } // Devuelve las accioens return(actions); }
/// <summary> /// Obtiene el siguiente movimiento (hacia atrás o hacia delante) /// </summary> internal MovementFigureModel GetMovement(bool back) { MovementFigureModel movement = null; // Obtiene el movimiento if (back) { if (_actualMovementIndex > 0) { movement = FigureMovements[--_actualMovementIndex]; } } else { if (_actualMovementIndex < FigureMovements.Count) { movement = FigureMovements[_actualMovementIndex]; _actualMovementIndex++; } } // Selecciona el movimiento if (movement != null) { SelectMovement(_actualMovementIndex); } // Devuelve el movimiento return(movement); }
/// <summary> /// Realiza un movimiento /// </summary> public bool Move(MovementFigureModel movement) { bool canMove = false; // Dependiendo del tipo de movimiento switch (movement.Type) { case MovementFigureModel.MovementType.CastleKingSide: canMove = MoveCastleKingSide(movement.Color); break; case MovementFigureModel.MovementType.CastleQueenSide: canMove = MoveCastleQueenSide(movement.Color); break; default: canMove = Move(movement.From.Row, movement.From.Column, movement.To.Row, movement.To.Column); break; } // Promociona la pieza if (canMove && movement.PromotedPiece != null) { canMove = Promote(movement.To.Row, movement.To.Column, movement.PromotedPiece ?? PieceBaseModel.PieceType.Pawn); } // Devuelve el valor que indica si se puede hacer un movimiento return(canMove); }
/// <summary> /// Realiza un movimiento /// </summary> private List <ActionBaseModel> MakeMovement(MovementFigureModel movement) { List <ActionBaseModel> actions = new ActionFactory().Create(movement); // Guarda el movimiento actual ActualMovement = movement; // Ejecuta el movimiento sobre el tablero Board.Move(movement); // Devuelve las acciones return(actions); }
/// <summary> /// Realiza el siguiente movimiento /// </summary> private void GoNextMovement() { MovementFigureModel movement = GetNextMovement(); // Realiza el movimiento if (movement != null) { // Ejecuta el movimiento RaiseEventShowMovements(MakeMovement(movement), MainViewModel.MustShowAnimation); // Lo muestra en la lista MovementsList.SelectMovement(movement); } }
public MovementSelectVariationViewModel(GameBoardViewModel gameBoardViewModel, MovementVariationModel variation, MovementFigureModel movement) { // Inicializa los objetos GameBoardViewModel = gameBoardViewModel; Movement = movement; Variation = variation; // Inicializa las propiedades Piece = movement.OriginPiece; Color = movement.Color; Text = movement.Content; // Inicializa los comandos SelectMovementCommand = new Mvvm.BaseCommand(parameter => ExecuteMovement(), parameter => CanExecuteMovement()); }
/// <summary> /// Realiza el movimiento de la figura /// </summary> private void MakeMove(MovementFigureModel movement) { //// Debug //#if DEBUG // System.Diagnostics.Debug.WriteLine($"Movement: {movement}"); //#endif // Realiza los movimientos switch (movement.Type) { case MovementFigureModel.MovementType.CastleKingSide: if (!Board.CanMoveCastleKingSide(movement.Color)) { throw new LibChessGame.Models.Exceptions.GameReaderException($"Error at movement castle king side {movement.Content}"); } else { Board.MoveCastleKingSide(movement.Color); } break; case MovementFigureModel.MovementType.CastleQueenSide: if (!Board.CanMoveCastleQueenSide(movement.Color)) { throw new LibChessGame.Models.Exceptions.GameReaderException($"Error at movement castle queen side {movement.Content}"); } else { Board.MoveCastleQueenSide(movement.Color); } break; case MovementFigureModel.MovementType.CaptureEnPassant: throw new NotImplementedException("Cant do EnPassant capture"); default: if (!Board.CanMove(movement.From.Row, movement.From.Column, movement.To.Row, movement.To.Column)) { throw new LibChessGame.Models.Exceptions.GameReaderException($"Error at movement {movement.Content}"); } else { Board.Move(movement); } break; } //// Debug //#if DEBUG // System.Diagnostics.Debug.WriteLine(Board.GetText()); // System.Diagnostics.Debug.WriteLine(new string('-', 80)); //#endif }
/// <summary> /// Obtiene el icono asociado a un <see cref="MovementFigureModel"/> /// </summary> private string GetIcon(MovementFigureModel movement) { string nameColor = ""; string namePiece = ""; // Obtiene el nombre del color if (movement.Color == PieceBaseModel.PieceColor.White) { nameColor = "White"; } else { nameColor = "Black"; } // Obtiene el nombre de la pieza switch (movement.OriginPiece) { case PieceBaseModel.PieceType.Pawn: namePiece = "Pawn"; break; case PieceBaseModel.PieceType.Rook: namePiece = "Rook"; break; case PieceBaseModel.PieceType.Knight: namePiece = "Knight"; break; case PieceBaseModel.PieceType.Bishop: namePiece = "Bishop"; break; case PieceBaseModel.PieceType.Queen: namePiece = "Queen"; break; case PieceBaseModel.PieceType.King: namePiece = "King"; break; } // Obtiene el nombre de la imagen if (!string.IsNullOrEmpty(nameColor) && !string.IsNullOrEmpty(namePiece)) { return($"/BauChessViewer;component/Resources/Images/{namePiece}{nameColor}.gif"); } else { return(null); } }
/// <summary> /// Deshace un movimiento /// </summary> private void UndoMovement(MovementFigureModel movement, bool raiseActions) { List <ActionBaseModel> actions = new ActionFactory().CreateUndo(movement); // Guarda el movimiento actual IsMoving = true; // Lanza las acciones if (raiseActions) { RaiseEventShowMovements(actions, MainViewModel.MustShowAnimation); } // Ejecuta el movimiento sobre el tablero Board.Undo(movement); }
/// <summary> /// Deshace el movimiento /// </summary> private void UndoMove(MovementFigureModel movement) { // Deshace la promoción if (movement.PromotedPiece != null) { this[movement.To] = new PawnModel(movement.Color); } // Deshace el movimiento MoveWithoutCheck(movement.To.Row, movement.To.Column, movement.From.Row, movement.From.Column, false); // Deshace la captura if (movement.Captured != null) { CreatePiece(movement.Captured.Type, movement.Captured.Color); } //? Debería cambiar los parámetros de movimiento de la figura }
/// <summary> /// Crea los movimientos hasta una variación /// </summary> internal void GoToVariation(MovementVariationModel variation, MovementFigureModel movement) { if (variation != null && movement != null) { // Cambia la variación actual y guarda el movimiento de la variación ActualVariationGame = VariationGame.CloneTo(null, variation, movement); VariationMovement = variation.Parent as MovementFigureModel; // y carga la lista LoadListViewMovements(ActualVariationGame.Movements); // Selecciona el movimiento en la lista y mueve MovementsList.SelectMovement(movement); GoToMovement(MovementsList.ActualMovement); // Indica que está en una variación IsAtVariation = true; } }
/// <summary> /// Añade un movimiento a la lista /// </summary> private MovementFigureModel ParseMovement(GameBoardModel board, PieceBaseModel.PieceColor actualColor, Move move) { MovementFigureModel newMovement = new MovementFigureModel(); CellConversor cellConversor = new CellConversor(); // Asigna los datos newMovement.Color = actualColor; newMovement.Type = ConvertMovement(move.Type); newMovement.Text = move.ToString(); newMovement.IsCheck = move.IsCheck ?? false; newMovement.IsDoubleCheck = move.IsDoubleCheck ?? false; newMovement.IsCheckMate = move.IsCheckMate ?? false; switch (newMovement.Type) { case MovementFigureModel.MovementType.CastleKingSide: case MovementFigureModel.MovementType.CastleQueenSide: // Asigna la pieza de origen newMovement.OriginPiece = PieceBaseModel.PieceType.Rook; // Crea las acciones de enroque newMovement.Actions.CreateCastleKingActions(board, newMovement); break; default: PieceBaseModel.PieceType?targetPiece = null; // Asigna los datos newMovement.OriginPiece = ConvertPiece(move.Piece); targetPiece = ConvertPiece(move.TargetPiece); // Añade la pieza promocionada if (move.PromotedPiece != null) { newMovement.PromotedPiece = ConvertPiece(move.PromotedPiece); } // Crea las acciones newMovement.Actions.CreateActions(board, newMovement, cellConversor.ConvertCell(move.TargetSquare.Rank, move.TargetSquare.File), cellConversor.ConvertCell(move.OriginRank, move.OriginFile), targetPiece); break; } newMovement.Annotation = ConvertAnnotation(move.Annotation); // Ejecuta los movimientos sobre el tablero board.Execute(newMovement); // Devuelve el movimiento return(newMovement); }
/// <summary> /// Deshace un movimiento /// </summary> public void Undo(MovementFigureModel movement) { switch (movement.Type) { case MovementFigureModel.MovementType.CastleKingSide: UndoCastleKingSide(movement.Color); break; case MovementFigureModel.MovementType.CastleQueenSide: UndoCastleQueenSide(movement.Color); break; default: UndoMove(movement); break; } }
/// <summary> /// Muestra el movimiento siguiente / anterior /// </summary> private void ShowMovement(bool back, bool showAnimation) { if (ChessGameViewModel.ChessGame != null) { MovementFigureModel movement = ChessGameViewModel.GetMovement(back); // Limpia el panel ClearMovementPanel(); // Obtiene el siguiente movimiento if (ChessGameViewModel.MovementsList.ActualMovement != null) { lblMovement.Text = ChessGameViewModel.MovementsList.ActualMovement.Text; imgMovement.Source = udtBoard.LoadImage(ChessGameViewModel.MovementsList.ActualMovement.Color, ChessGameViewModel.MovementsList.ActualMovement.Piece); udtBoard.ShowMovement(movement, back, showAnimation); } } }
public MovementFigureViewModel(PgnGameViewModel pgnGameViewModel, MovementFigureModel movement, int movementIndex, int variationIndex) { // Inicializa las propiedades PgnGameViewModel = pgnGameViewModel; VariationIndex = variationIndex; Selected = false; Piece = movement.OriginPiece; Color = movement.Color; MovementIndex = movementIndex; Movement = movement; Text = movement.Text; HasVariation = movement.Variation != null; Time = "01:07"; // Inicializa la forma en que se debe ver el movimiento en la lista (tamaños de fuente, tamaños de imagen...) AssignViewSizes(variationIndex, Selected); // Inicializa los comandos SelectMovementCommand = new BaseCommand(parameter => ExecuteMovement(), parameter => CanExecuteMovement()); }
/// <summary> /// Crea las acciones de enroque /// </summary> private List <ActionBaseModel> CreateCastleKingActions(MovementFigureModel movement) { List <ActionBaseModel> actions = new List <ActionBaseModel>(); int row = movement.Color == PieceBaseModel.PieceColor.White ? 7 : 0; // Enroque if (movement.Type == MovementFigureModel.MovementType.CastleKingSide) // enroque corto { actions.Add(CreateMoveAction(PieceBaseModel.PieceType.Rook, movement.Color, new CellModel(row, 7), new CellModel(row, 5))); actions.Add(CreateMoveAction(PieceBaseModel.PieceType.King, movement.Color, new CellModel(row, 4), new CellModel(row, 6))); } else // enroque largo { actions.Add(CreateMoveAction(PieceBaseModel.PieceType.Rook, movement.Color, new CellModel(row, 0), new CellModel(row, 3))); actions.Add(CreateMoveAction(PieceBaseModel.PieceType.King, movement.Color, new CellModel(row, 4), new CellModel(row, 2))); } // Devuelve las acciones return(actions); }
/// <summary> /// Crea una lista de acciones para deshacer un movimiento /// </summary> public List <ActionBaseModel> CreateUndo(MovementFigureModel movement) { List <ActionBaseModel> actions = new List <ActionBaseModel>(); // Añade las acciones switch (movement.Type) { case MovementFigureModel.MovementType.CastleKingSide: case MovementFigureModel.MovementType.CastleQueenSide: actions.AddRange(CreateUndoCastleKingActions(movement)); break; default: actions.AddRange(CreateUndoMoveActions(movement)); break; } // Devuelve las acciones return(actions); }
/// <summary> /// Realiza los movimientos asociados a una serie de acciones /// </summary> internal void Execute(MovementFigureModel movement) { foreach (ActionBaseModel action in movement.Actions) { switch (action) { case ActionMoveModel child: Move(child); break; case ActionCaptureModel child: Capture(child); break; case ActionPromoteModel child: Promote(child); break; } } }
/// <summary> /// Crea una lista de acciones basada en un movimiento /// </summary> public List <ActionBaseModel> Create(MovementFigureModel movement) { List <ActionBaseModel> actions = new List <ActionBaseModel>(); // Añade las acciones switch (movement.Type) { case MovementFigureModel.MovementType.CastleKingSide: case MovementFigureModel.MovementType.CastleQueenSide: actions.AddRange(CreateCastleKingActions(movement)); break; default: // Crea el movimiento actions.Add(CreateMoveAction(movement.OriginPiece, movement.Color, movement.From, movement.To)); // Añade la captura if (movement.Type == MovementFigureModel.MovementType.Capture) { if (movement.CapturedEnPassant != null) { actions.Add(CreateCaptureAction(movement.Captured.Type, movement.Captured.Color, movement.CapturedEnPassant)); } else { actions.Add(CreateCaptureAction(movement.Captured.Type, movement.Captured.Color, movement.To)); } } // Crea la promoción if (movement.PromotedPiece != null) { // Elimina el peón actions.Add(CreateCaptureAction(PieceBaseModel.PieceType.Pawn, movement.Color, movement.To)); // Crea la promoción actions.Add(CreatePromoteAction(movement.PromotedPiece ?? PieceBaseModel.PieceType.Queen, movement.Color, movement.To)); } break; } // Devuelve las acciones return(actions); }
/// <summary> /// Busca la pieza de un color que se pueden mover a una celda /// </summary> internal PieceBaseModel SearchMoveTo(MovementFigureModel movement, CellModel target, CellModel origin) { List <PieceBaseModel> pieces = new List <PieceBaseModel>(); // Busca las piezas foreach (PieceBaseModel piece in Pieces) { if (piece.Type == movement.OriginPiece && piece.Color == movement.Color && piece.CanMoveTo(this, target, movement.Type)) { pieces.Add(piece); } } // Si se le ha pasado una fila / columna para ajustarlo, obtiene la pieza que estaba inicialmente en esa posición if (pieces.Count > 1) { if (origin != null && (origin.Row != -1 || origin.Column != -1)) { foreach (PieceBaseModel piece in pieces) { if ((origin.Column == -1 && piece.Cell.Row == origin.Row) || (origin.Row == -1 && piece.Cell.Column == origin.Column) || (piece.Cell.Row == origin.Row && piece.Cell.Column == origin.Column)) { return(piece); } } } } // Devuelve la primera pieza localizada if (pieces.Count > 0) { return(pieces[0]); } else { return(null); } }
/// <summary> /// Selecciona un movimiento en la lista /// </summary> internal void SelectMovement(MovementFigureModel movement) { if (movement == null) { SelectedMovement = null; ActualMovement = null; } else { foreach (BaseMovementViewModel baseMovement in Movements) { if (baseMovement is MovementFigureDoubleViewModel movementDouble) { // Selecciona el movimiento blanco if (movementDouble.WhiteMovement != null) { movementDouble.WhiteMovement.Selected = movementDouble.WhiteMovement.Movement.Id == movement.Id; if (movementDouble.WhiteMovement.Selected) { SelectedMovement = movementDouble; ActualMovement = movementDouble.WhiteMovement; } } // Selecciona el movimiento negro if (movementDouble.BlackMovement != null) { movementDouble.BlackMovement.Selected = movementDouble.BlackMovement.Movement.Id == movement.Id; if (movementDouble.BlackMovement.Selected) { SelectedMovement = movementDouble; ActualMovement = movementDouble.BlackMovement; } } } } } }
/// <summary> /// Crea un movimiento de una variación /// </summary> private MovementFigureVariationDoubleViewModel CreateRecursiveMovement(MovementFigureVariationDoubleViewModel lastMovement, MovementFigureModel move, int movementIndex, int movementLineIndex, int variationIndex) { // Si es necesario, crea un nuevo movimiento if (lastMovement == null) { lastMovement = new MovementFigureVariationDoubleViewModel(movementIndex, movementLineIndex, variationIndex); Movements.Add(lastMovement); } // Asigna el movimiento de blancas / negras if (move.Color == Bau.Libraries.LibChessGame.Board.Pieces.PieceBaseModel.PieceColor.White) { // Asigna el movimiento de blancas lastMovement.WhiteMovement = new MovementFigureViewModel(PgnGameViewModel, move, movementIndex, variationIndex); // Carga la variación if (MustShowVariations(move)) { LoadVariationMovements(move.Variation, movementIndex, movementLineIndex, variationIndex + 1); lastMovement = null; } } else // Asigna el movimiento de negras { // Asigna el movimiento de negras lastMovement.BlackMovement = new MovementFigureViewModel(PgnGameViewModel, move, movementIndex, variationIndex); // Carga la variación if (MustShowVariations(move)) { LoadVariationMovements(move.Variation, movementIndex, movementLineIndex, variationIndex + 1); } lastMovement = null; } // Devuelve el último movimiento añadido a la lista return(lastMovement); }
public MovementListSelectVariationViewModel(GameBoardViewModel gameBoardViewModel, MovementFigureModel movement) { // Crea la colección Variations = new ObservableCollection <MovementSelectVariationViewModel>(); // Añade las variaciones que se pueden seleccionar foreach (MovementVariationModel variation in movement.Variations) { bool isAdded = false; // Añade el primer movimiento de figura de la variación foreach (MovementBaseModel movementVariation in variation.Movements) { if (!isAdded && movementVariation is MovementFigureModel movementFigure) { // Añade la variación Variations.Add(new MovementSelectVariationViewModel(gameBoardViewModel, variation, movementFigure)); // Indica que se ha añadido isAdded = true; } } } }
/// <summary> /// Extrae la celda origen del movimiento /// </summary> /// <remarks> /// Disambiguation /// In the case of ambiguities (multiple pieces of the same type moving to the same square), the first appropriate /// disambiguating step of the three following steps is taken: /// First, if the moving pieces can be distinguished by their originating files, the originating file letter of the /// moving piece is inserted immediately after the moving piece letter. /// Second (when the first step fails), if the moving pieces can be distinguished by their originating ranks, the /// originating rank digit of the moving piece is inserted immediately after the moving piece letter. /// Third (when both the first and the second steps fail), the two character square coordinate of the originating /// square of the moving piece is inserted immediately after the moving piece letter. /// </remarks> /// <example> /// cxb5 axb5 dxe5 Bxe7 Qxe7 Nxc4 Bxc4 Nb6 Rxe1+ /// </example> private void ExtractCellsInfo(MovementFigureModel movement, ref string content) { string cellStart = string.Empty, cellEnd = string.Empty; // Captura if (content.StartsWith("x", StringComparison.CurrentCultureIgnoreCase)) { movement.Type = MovementFigureModel.MovementType.Capture; content = content.Substring(1); } // Obtiene los datos de la celda de inicio cellStart = ExtractCell(ref content); // Captura if (content.StartsWith("x", StringComparison.CurrentCultureIgnoreCase)) { // Indica que es una captura (y ya ha habido información de celda) movement.Type = MovementFigureModel.MovementType.Capture; content = content.Substring(1); // Obtiene los datos de la celda de fin if (!string.IsNullOrWhiteSpace(content)) { cellEnd = ExtractCell(ref content); } } // Interpreta el movimiento if (string.IsNullOrWhiteSpace(cellStart) && string.IsNullOrWhiteSpace(cellEnd)) { throw new LibChessGame.Models.Exceptions.GameReaderException($"Cant get movement from {movement.Content}"); } else { (CellModel from, CellModel to) = GetChoords(cellStart, cellEnd); (int row, int column, PieceBaseModel piece)pieceCell = Board.SearchMoveTo(movement.OriginPiece, movement.Color, from.Row, from.Column, to.Row, to.Column); // Asigna los datos del movimiento if (pieceCell.piece == null) { throw new LibChessGame.Models.Exceptions.GameReaderException($"Cant find who moves to {movement.Content}"); } else { // Asigna el movimiento de inicio y fin movement.From = new CellModel(pieceCell.row, pieceCell.column); movement.To = to; // Asigna la pieza capturada if (movement.Type == MovementFigureModel.MovementType.Capture) { if (Board.IsCaptureEnPassant(Board[movement.From], movement.To.Row, movement.To.Column, Board[movement.To])) { movement.Captured = new PawnModel(Board.Parameters.EnPassantColor); movement.CapturedEnPassant = new CellModel(Board.Parameters.EnPassantCell); } else { movement.Captured = Board[movement.To]; } } } } }
/// <summary> /// Obtiene los datos de la notación SAN /// </summary> private void ConvertSan(MovementFigureModel movement, string content) { //// Debug //#if DEBUG // System.Diagnostics.Debug.WriteLine($"Start convert SAN: {content}"); //#endif // Tipo de movimiento movement.Type = MovementFigureModel.MovementType.Normal; // Obtiene la información básica del movimiento if (content == "0-0" || content == "O-O") { // Datos de la pieza movement.OriginPiece = PieceBaseModel.PieceType.King; movement.Type = MovementFigureModel.MovementType.CastleKingSide; // Quita los datos del contenido if (content.Length == 3) { content = string.Empty; } else { content = content.Substring(3); } } else if (content == "0-0-0" || content == "O-O-O") { // Datos de la pieza movement.OriginPiece = PieceBaseModel.PieceType.King; movement.Type = MovementFigureModel.MovementType.CastleQueenSide; // Quita los datos del contenido if (content.Length == 5) { content = string.Empty; } else { content = content.Substring(5); } } else { // Obtiene la pieza movement.OriginPiece = ExtractPiece(ref content); // Obtiene la información de las celdas origen y destino ExtractCellsInfo(movement, ref content); } // Obtiene la información adicional if (!string.IsNullOrWhiteSpace(content)) { // Promociones, jaque, jaque mate if (content.StartsWith("=")) // promoción { content = content.Substring(1); movement.PromotedPiece = ExtractPiece(ref content); } else if (content.StartsWith("(=)")) // el jugador ofrece tablas (algunos archivos) { content = content.Substring(3); movement.IsDrawOffered = true; } else if (content.StartsWith("++")) // jaque mate en algunos archivos { content = content.Substring(2); movement.IsCheckMate = true; } else if (content.StartsWith("+")) // jaque { content = content.Substring(1); movement.IsCheck = true; } else if (content.StartsWith("#")) // jaque mate { content = content.Substring(1); movement.IsCheckMate = true; } // Anotaciones if (!string.IsNullOrWhiteSpace(content)) { movement.Info.Add(new MovementInfoModel(content)); } } // Y por último realiza el movimiento MakeMove(movement); }
/// <summary> /// Muestra un movimiento /// </summary> internal void ShowMovement(MovementFigureModel movement, bool backMovement, bool showAnimation) { if (movement != null) { List <ActionViewMovement> actions = new List <ActionViewMovement>(); // Recorre las acciones del movimiento hacia delante o hacia atrás if (!backMovement) { foreach (ActionBaseModel action in movement.Actions) { switch (action) { case ActionMoveModel move: actions.Add(GetActionMovePiece(move)); break; case ActionCaptureModel move: actions.Add(GetActionCapturePiece(move)); break; case ActionPromoteModel move: actions.Add(GetActionPromotePiece(move)); break; } } } else { for (int index = movement.Actions.Count - 1; index >= 0; index--) { switch (movement.Actions[index]) { case ActionMoveModel move: actions.Add(GetActionUndoMovePiece(move)); break; case ActionCaptureModel move: actions.Add(GetActionUndoCapturePiece(move)); break; case ActionPromoteModel move: actions.Add(GetActionUndoPromotePiece(move)); break; } } } // Muestra las animaciones o ejecuta las acciones if (showAnimation && ViewModel.MustShowAnimation) { Storyboard storyBoard = CreateAnimations(actions); // ... y las muestra if (storyBoard.Children.Count > 0) { // Indica que se está realizando un movimiento CanMove = false; // Asigna el evento de fin de animación storyBoard.Completed += (sender, evntArgs) => { // Ejecuta las acciones ExecuteActions(actions); // Indica que se ha finalizado el movimiento CanMove = true; }; // Comienza la animación storyBoard.Begin(); } else { ExecuteActions(actions); } } else // Ejecuta directamente las acciones sobre el tablero { ExecuteActions(actions); } } }
/// <summary> /// Interpreta los movimientos /// </summary> private MovementModelCollection ParseMovements(VariationModel variation, MoveTextEntryList moveEntryList) { MovementModelCollection movements = new MovementModelCollection(); PieceBaseModel.PieceColor actualColor = PieceBaseModel.PieceColor.White; PieceBaseModelCollection previousPieces = new PieceBaseModelCollection(); // Inicializa el tablero variation.GameBoard.Reset(); // Cambia el color inicial if (variation.Setup.HasSetup && !variation.Setup.IsWhiteMove) { actualColor = PieceBaseModel.PieceColor.Black; } // Interpreta la lista de movimientos try { foreach (MoveTextEntry moveEntry in moveEntryList) { switch (moveEntry) { case RAVEntry rav: MovementFigureModel lastMovement = movements.SearchLastPieceMovement(); if (lastMovement != null) { lastMovement.Variation = CreateVariation(actualColor, previousPieces, rav); } break; case NAGEntry nag: System.Diagnostics.Debug.WriteLine(moveEntry.GetType().ToString()); break; case CommentEntry comment: movements.Add(new MovementRemarksModel(comment.Comment)); break; case MovePairEntry movement: // Añade el movimiento de blancas movements.Add(ParseMovement(variation.GameBoard, actualColor, (moveEntry as MovePairEntry).White)); actualColor = GetNextColor(actualColor); // Clona la lista de piezas hasta el movimiento anterior previousPieces = variation.GameBoard.Pieces.Clone(); // Añade el movimiento de negras movements.Add(ParseMovement(variation.GameBoard, actualColor, (moveEntry as MovePairEntry).Black)); actualColor = GetNextColor(actualColor); break; case HalfMoveEntry movement: // Clona la lista de piezas hasta el movimiento anterior previousPieces = variation.GameBoard.Pieces.Clone(); // Añade el movimiento actual movements.Add(ParseMovement(variation.GameBoard, actualColor, (moveEntry as HalfMoveEntry).Move)); actualColor = GetNextColor(actualColor); break; case GameEndEntry movement: movements.Add(new MovementGameEndModel(ConvertResult(movement.Result))); break; default: System.Diagnostics.Debug.WriteLine(moveEntry.GetType().ToString()); break; } } } catch (Exception exception) { variation.ParseError = exception.Message; } // Devuelve la colección de movimientos return(movements); }