using Shogi.Domain.YetToBeAssimilatedIntoDDD.Pathing; using System.Diagnostics; namespace Shogi.Domain.ValueObjects { [DebuggerDisplay("{WhichPiece} {Owner}")] public abstract record class Piece { 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)}.") }; } 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 along the shortest path 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 = MoveSet.GetNearestPath(start, end); var position = start; while (Vector2.Distance(start, position) < Vector2.Distance(start, end)) { position += path.Step; steps.Add(position); if (path.Distance == Distance.OneStep) break; } if (position == end) { return steps; } return []; } } }