232 lines
11 KiB
C#
232 lines
11 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Drawing;
|
|||
|
using ChessPanel;
|
|||
|
using System.Linq;
|
|||
|
using System.Windows;
|
|||
|
|
|||
|
namespace Chess
|
|||
|
{
|
|||
|
public enum PieceColor { White, Black };
|
|||
|
public enum PieceTeam { Enemy, Ally };
|
|||
|
public enum PieceType { King, Queen, Bishop, Rook, Knight, Pawn };
|
|||
|
public enum MoveMode { Normal, Attack, Movement };
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Figur
|
|||
|
/// </summary>
|
|||
|
public abstract class Piece
|
|||
|
{
|
|||
|
public PieceColor color;
|
|||
|
public PieceType type;
|
|||
|
public Dictionary<Field, PieceTeam> validTargetSpots;
|
|||
|
public Image image;
|
|||
|
public bool HasMoved = false;
|
|||
|
public Field field;
|
|||
|
public bool EnPassantPossible = false; // Only in Pawn Class. Signs that this Piece has virtually not jumped two pieces, but one, reflective meaning: This.Figure can be attacked using Enpassant if this.type is Pawn
|
|||
|
public override string ToString()
|
|||
|
{
|
|||
|
return type.ToString();
|
|||
|
}
|
|||
|
|
|||
|
public Piece(Vector position, Grid fields)
|
|||
|
{
|
|||
|
this.field = fields[position];
|
|||
|
fields[position].CurrentPiece = this;
|
|||
|
}
|
|||
|
|
|||
|
public Dictionary<Field, PieceTeam> RefreshValidTargetSpots(Grid fields, MoveMode mode = MoveMode.Normal)
|
|||
|
{
|
|||
|
this.validTargetSpots = this.GetValidTargetFields(fields, mode);
|
|||
|
return validTargetSpots;
|
|||
|
}
|
|||
|
|
|||
|
internal void RemoveTargetFieldsWhereKingIsEndangered(Grid fields, Dictionary<Field, PieceTeam> targetFields)
|
|||
|
{
|
|||
|
Field ownKingLocation = fields.GetKing(this.color).field;
|
|||
|
foreach (var virtualTargetField in targetFields)
|
|||
|
{
|
|||
|
if (fields.IsFieldVirtuallyEndagered(ownKingLocation, (this.color == PieceColor.Black ? PieceColor.White : PieceColor.Black), this, virtualTargetField.Key))
|
|||
|
targetFields.Remove(virtualTargetField.Key);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Tests if the Move will leave your King endangered.
|
|||
|
/// </summary>
|
|||
|
/// <param name="fields">GameField</param>
|
|||
|
/// <param name="pieceLocation">Location of Piece to move</param>
|
|||
|
/// <param name="simulatedLocation">Location to move Piece to</param>
|
|||
|
/// <param name="color">Color of Piece to move</param>
|
|||
|
/// <returns>Bool</returns>
|
|||
|
/* internal static bool MoveWillEndangerOwnKing(Grid fields, Vector pieceLocation, Vector simulatedLocation, PieceColor color)
|
|||
|
{
|
|||
|
// fields[simulateLocation].currentPiece = fields[pieceLocation].currentPiece;
|
|||
|
// fields[pieceLocation].currentPiece = null;
|
|||
|
// Check if own king is endangered
|
|||
|
return FieldIsEndangered(fields, simulatedLocation, kingLocation, color, dontTestKingDanger: true);
|
|||
|
}*/
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Checks if a specific field can be reached by the figure while a virtual move is simulated
|
|||
|
/// </summary>
|
|||
|
/// <param name="movePiece">Piece that virtually got moved</param>
|
|||
|
/// <param name="targetPos">Field that the movePiece virtually moved to</param>
|
|||
|
/// <param name="possibleEndageredField">Field that should be checked</param>
|
|||
|
/// <param name="fields">Current Game Grid</param>
|
|||
|
/// <returns></returns>
|
|||
|
internal abstract bool EndageresFieldWithVirtualMove(Grid fields, Field possibleEndageredField, Piece movePiece, Field targetPos);
|
|||
|
|
|||
|
internal void Move(Field newPieceField)
|
|||
|
{
|
|||
|
this.field.CurrentPiece = null; // Remove piece from previous position
|
|||
|
this.field = newPieceField; // Set pieces location to new field
|
|||
|
newPieceField.CurrentPiece = this; // Set new fields piece to this
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Tests if the Move will leave your movedPiece endangered.
|
|||
|
/// </summary>
|
|||
|
/// <param name="fields">GameField</param>
|
|||
|
/// <param name="pieceLocation">Location of Piece to move</param>
|
|||
|
/// <param name="testLocation">Location to move Piece to</param>
|
|||
|
/// <param name="color">Color of Piece to move</param>
|
|||
|
/// <returns>Bool</returns>
|
|||
|
//internal static bool MoveWillEndangerPiece(Grid fields, Vector pieceLocation, Vector testLocation, PieceColor color)
|
|||
|
//{
|
|||
|
// return false;
|
|||
|
// //Grid simulatedField = fields;
|
|||
|
// //simulatedField[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = null;
|
|||
|
// //return FieldIsEndangered(fields simulatedField, testLocation, color);
|
|||
|
//}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Tests if your King is currently endangered.
|
|||
|
/// </summary>
|
|||
|
/// <param name="fields">GameField</param>
|
|||
|
/// <param name="color">Kings color</param>
|
|||
|
/// <returns></returns>
|
|||
|
//private static bool KingIsEndangered(Grid fields, PieceColor color) => FieldIsEndangered(fields, GetKingLocation(fields, color), color, dontTestKingDanger: true);
|
|||
|
/// <summary>
|
|||
|
/// Tests if the testLocation is endangered by an enemy.
|
|||
|
/// </summary>
|
|||
|
/// <param name="fields">GameField</param>
|
|||
|
/// <param name="color">Ally Color</param>
|
|||
|
/// <param name="testLocation">Location to test</param>
|
|||
|
/// <returns>Bool</returns>
|
|||
|
//private static bool FieldIsEndangered(Grid fields, Vector simulatedLocation, Vector testLocation, PieceColor color, bool dontTestKingDanger = false)
|
|||
|
//{
|
|||
|
// foreach (Field field in fields)
|
|||
|
// {
|
|||
|
// if (field.location != simulatedLocation
|
|||
|
// && field.currentPiece != null
|
|||
|
// && field.currentPiece.color != color
|
|||
|
// && field.currentPiece.GetValidTargetFields(fields, dontTestKingDanger: dontTestKingDanger).ContainsKey(testLocation))
|
|||
|
// return true;
|
|||
|
// }
|
|||
|
// return false;
|
|||
|
//}
|
|||
|
/*internal static bool IsEndangeredLocationForPiece(Grid fields, Vector pieceLocation, Vector testLocation, PieceColor color)
|
|||
|
{
|
|||
|
bool returnValue = false;
|
|||
|
Piece p = fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece;
|
|||
|
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = null;
|
|||
|
foreach (var field in fields)
|
|||
|
{
|
|||
|
if (field.currentPiece != null) if (field.currentPiece.color != color) if (field.currentPiece.GetValidTargetFields(fields, field.location, true).ContainsKey(testLocation))
|
|||
|
{
|
|||
|
returnValue = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = p;
|
|||
|
return returnValue;
|
|||
|
}*/
|
|||
|
/* internal static bool MoveWillEndangerKing(Grid fields, Vector pieceLocation, Vector pieceMovedLocation, PieceColor color) // This does not test if it is a valid move spot
|
|||
|
{
|
|||
|
bool returnValue = false;
|
|||
|
Piece p1 = fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece;
|
|||
|
Piece p2 = fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece;
|
|||
|
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = null;
|
|||
|
fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece = p1;
|
|||
|
returnValue = KingIsEndangered(fields, color);
|
|||
|
fields[(int)pieceLocation.X, (int)pieceLocation.Y].currentPiece = p1;
|
|||
|
fields[(int)pieceMovedLocation.X, (int)pieceMovedLocation.Y].currentPiece = p2;
|
|||
|
return returnValue;
|
|||
|
}*/
|
|||
|
/* private static bool KingIsEndangered(Grid fields, PieceColor color)
|
|||
|
{
|
|||
|
Vector kingLocation = GetKingLocation(fields, color);
|
|||
|
foreach (var field in fields)
|
|||
|
{
|
|||
|
if (field.currentPiece == null || field.currentPiece.color != color)
|
|||
|
continue;
|
|||
|
if (field.currentPiece.GetValidTargetFields(fields, field.location, dontTestKingDanger: true).ContainsKey(kingLocation))
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}*/
|
|||
|
/// <summary>
|
|||
|
/// Searches for the King of the given color.
|
|||
|
/// </summary>
|
|||
|
/// <param name="fields">GameField</param>
|
|||
|
/// <param name="color">Kings color</param>
|
|||
|
/// <returns>King location as Vector</returns>
|
|||
|
private static Vector GetKingLocation(Grid fields, PieceColor color)
|
|||
|
{
|
|||
|
foreach (Field field in fields)
|
|||
|
if (!field.IsEmpty && field.currentPiece.type == PieceType.King && field.currentPiece.color == color)
|
|||
|
return field.location;
|
|||
|
throw new Exception("King not found!");
|
|||
|
}
|
|||
|
virtual internal Dictionary<Field, PieceTeam> GetValidTargetFields(Grid fields, MoveMode mode = MoveMode.Normal, bool dontTestKingDanger = false)
|
|||
|
{
|
|||
|
var targetFields = GetTargetFields(fields, field, this.color);
|
|||
|
if (!dontTestKingDanger)
|
|||
|
{
|
|||
|
Field kinglocation = fields.GetKing(this.color).field;
|
|||
|
List<Field> remove = new List<Field>();
|
|||
|
|
|||
|
foreach (var item in targetFields.Keys)
|
|||
|
{
|
|||
|
if (fields.IsFieldVirtuallyEndagered(kinglocation, (this.color == PieceColor.Black ? PieceColor.White : PieceColor.Black), this, item))
|
|||
|
remove.Add(item);
|
|||
|
}
|
|||
|
foreach (var item in remove)
|
|||
|
{
|
|||
|
targetFields.Remove(item);
|
|||
|
}
|
|||
|
}
|
|||
|
return targetFields;
|
|||
|
}
|
|||
|
internal abstract Dictionary<Field, PieceTeam> GetTargetFields(Grid fields, Field field, PieceColor color);
|
|||
|
internal static bool FieldIsVirtuallyEmpty(Field targetPos, Field skipField, Field possibleTargetField)
|
|||
|
{
|
|||
|
return (possibleTargetField.IsEmpty && possibleTargetField != targetPos)
|
|||
|
|| possibleTargetField == skipField;
|
|||
|
}
|
|||
|
internal static bool CheckFieldCanBeReached(Field possibleEndageredField, Field targetPos, Piece movePiece, Field possibleTargetField, PieceColor color, out bool breakIt)
|
|||
|
{
|
|||
|
breakIt = false;
|
|||
|
|
|||
|
var skipField = movePiece.field;
|
|||
|
if (FieldIsVirtuallyEmpty(targetPos, skipField, possibleTargetField))
|
|||
|
{
|
|||
|
if (possibleTargetField == possibleEndageredField)
|
|||
|
return true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
var checkPiece = possibleTargetField == targetPos ? movePiece : possibleTargetField.CurrentPiece;
|
|||
|
|
|||
|
if (checkPiece.color != color && possibleTargetField == possibleEndageredField)
|
|||
|
return true;
|
|||
|
breakIt=true;
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
//internal abstract Dictionary<Field, PieceTeam> GetValidTargetFields(Grid fields, MoveMode mode = MoveMode.Any, bool dontTestKingDanger = false);
|
|||
|
}
|
|||
|
}
|