using Shogi.Domain.Pathing; using System.Diagnostics; namespace Shogi.Domain.Pieces { [DebuggerDisplay("{WhichPiece} {Owner}")] public abstract class Piece { /// /// Creates a clone of an existing piece. /// public static Piece Create(Piece piece) => Create(piece.WhichPiece, piece.Owner, piece.IsPromoted); public static Piece Create(WhichPiece piece, WhichPlayer owner, bool isPromoted = false) { return piece switch { WhichPiece.King => new King(owner, isPromoted), WhichPiece.GoldGeneral => new GoldGeneral(owner, isPromoted), WhichPiece.SilverGeneral => new SilverGeneral(owner, isPromoted), WhichPiece.Bishop => new Bishop(owner, isPromoted), WhichPiece.Rook => new Rook(owner, isPromoted), WhichPiece.Knight => new Knight(owner, isPromoted), WhichPiece.Lance => new Lance(owner, isPromoted), WhichPiece.Pawn => new Pawn(owner, isPromoted), _ => throw new ArgumentException($"Unknown {nameof(WhichPiece)} when cloning a {nameof(Piece)}.") }; } // TODO: MoveSet doesn't account for Player2's pieces which are upside-down. public abstract IEnumerable MoveSet { get; } public WhichPiece WhichPiece { get; } public WhichPlayer Owner { get; private set; } public bool IsPromoted { get; private set; } public bool IsUpsideDown => Owner == WhichPlayer.Player2; protected Piece(WhichPiece piece, WhichPlayer owner, bool isPromoted = false) { WhichPiece = piece; Owner = owner; IsPromoted = isPromoted; } public bool CanPromote => !IsPromoted && WhichPiece != WhichPiece.King && WhichPiece != WhichPiece.GoldGeneral; public void Promote() => IsPromoted = CanPromote; /// /// Prep the piece for capture by changing ownership and demoting. /// public void Capture(WhichPlayer newOwner) { Owner = newOwner; IsPromoted = false; } /// /// Respecting the move-set of the Piece, collect all positions from start to end. /// Useful if you need to iterate a move-set. /// /// /// /// An empty list if the piece cannot legally traverse from start to end. Otherwise, a list of positions. public IEnumerable GetPathFromStartToEnd(Vector2 start, Vector2 end) { var steps = new List(10); var path = this.MoveSet.GetNearestPath(start, end); var position = start; while (Vector2.Distance(start, position) < Vector2.Distance(start, end)) { position += path.Direction; steps.Add(position); } if (position == end) { return steps; } return Array.Empty(); } /// /// Get all positions this piece could move to from the currentPosition, respecting the move-set of this piece. /// /// /// A list of positions the piece could move to. public IEnumerable GetPossiblePositions(Vector2 currentPosition) { throw new NotImplementedException(); } } }