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();
}
}
}