chess-board/ChessPanel/Piece.cs

461 lines
22 KiB
C#
Raw Normal View History

2017-02-27 15:15:50 +01:00
using System;
using System.Collections.Generic;
using System.Drawing;
using ChessPanel;
using System.Linq;
using System.Windows;
namespace Chess
{
public abstract class Piece
{
public enum PieceColor { White, Black };
public enum PieceTeam { Enemy, Ally };
public enum PieceType { King, Queen, Bishop, Rook, Knight, Pawn };
public PieceColor color;
public PieceType type;
public Image image;
public bool HasMoved = false;
public bool EnPassantPossible = false; // Only in Pawn Class. Signs that this Piece has virtually not jumped two pieces, but one
internal static bool IsEndangeredLocationForPiece(Field[,] 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(Field[,] 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(Field[,] 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, testKingDanger: true).ContainsKey(kingLocation))
{
return true;
}
}
return false;
}
private static Vector GetKingLocation(Field[,] fields, PieceColor color)
{
foreach (var field in fields)
if (!field.IsEmpty && field.currentPiece.type == PieceType.King && field.currentPiece.color == color)
return field.location;
throw new Exception("King not found!");
}
internal abstract Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector currentLocation, bool onlyAttackFields = false, bool testKingDanger = false);
}
public class Rook : Piece
{
public Rook(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool ignoreKingCheck = false, bool testKingDanger = false)
{
var targetFields = GetTargetFields(fields, location, this.color);
/*if (!testKingDanger)
foreach (var item in targetFields)
if (MoveWillEndangerKing(fields, location, item.Key, this.color))
targetFields.Remove(item.Key);*/
return targetFields;
}
internal static Dictionary<Vector, PieceTeam> GetTargetFields(Field[,] fields, Vector location, PieceColor color)
{
Dictionary<Vector, PieceTeam> targetFields = new Dictionary<Vector, PieceTeam>();
for (int x = (int)location.X - 1; x >= 0; x--) // nach Links
{
if (fields[x, (int)location.Y].IsEmpty)
{
targetFields.Add(new Vector(x, (int)location.Y), PieceTeam.Ally);
}
else
{
if (fields[x, (int)location.Y].currentPiece.color != color)
targetFields.Add(new Vector(x, (int)location.Y), PieceTeam.Enemy);
break;
}
}
for (int x = (int)location.X + 1; x <= 7; x++) // nach Rechts
{
if (fields[x, (int)location.Y].IsEmpty)
{
targetFields.Add(new Vector(x, (int)location.Y), PieceTeam.Ally);
}
else
{
if (fields[x, (int)location.Y].currentPiece.color != color)
targetFields.Add(new Vector(x, (int)location.Y), PieceTeam.Enemy);
break;
}
}
for (int y = (int)location.Y - 1; y >= 0; y--) // nach Unten
{
if (fields[(int)(int)location.X, y].IsEmpty)
{
targetFields.Add(new Vector((int)location.X, y), PieceTeam.Ally);
}
else
{
if (fields[(int)(int)location.X, y].currentPiece.color != color)
targetFields.Add(new Vector((int)location.X, y), PieceTeam.Enemy);
break;
}
}
for (int y = (int)location.Y + 1; y <= 7; y++) // nach Oben
{
if (fields[(int)(int)location.X, y].IsEmpty)
{
targetFields.Add(new Vector((int)location.X, y), PieceTeam.Ally);
}
else
{
if (fields[(int)(int)location.X, y].currentPiece.color != color)
targetFields.Add(new Vector((int)location.X, y), PieceTeam.Enemy);
break;
}
}
return targetFields;
}
} // FINALIZED
public class Pawn : Piece
{
public Pawn(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool onlyAttackFields = false, bool testKingDanger = false)
{
var targetFields = GetTargetFields(fields, location, this.color, onlyAttackFields);
/*if (!testKingDanger)
foreach (var item in targetFields)
if (MoveWillEndangerKing(fields, location, item.Key, this.color))
targetFields.Remove(item.Key);*/
return targetFields;
}
private Dictionary<Vector, PieceTeam> GetTargetFields(Field[,] fields, Vector location, PieceColor color, bool onlyAttackFields = false)
{
Dictionary<Vector, PieceTeam> targetFields = new Dictionary<Vector, PieceTeam>();
int direction = this.color == PieceColor.White ? -1 : 1;
#region EnPassant
if (location.Y == (this.color == PieceColor.White ? 3 : 4))
for (int x = -1; x < 2; x += 2)
if (location.X + x <= 7 && location.X + x >= 0)
if (fields[(int)location.X + x, (int)location.Y].currentPiece != null)
if (fields[(int)location.X + x, (int)location.Y].currentPiece.type == PieceType.Pawn)
if (fields[(int)location.X + x, (int)location.Y].currentPiece.color != this.color)
if (fields[(int)location.X + x, (int)location.Y].currentPiece.EnPassantPossible)
targetFields.Add(new Vector(location.X + x, location.Y + direction), PieceTeam.Enemy);
#endregion
#region Movement
if (!onlyAttackFields)
for (int y = 1; y < 1 + (HasMoved ? 1 : 2); y++)
{
if (location.Y + (direction * y) > 7 || location.Y + (direction * y) < 0)
break;
if (fields[(int)location.X, (int)location.Y + (direction * y)].IsEmpty)
targetFields.Add(new Vector(location.X, (int)location.Y + (direction * y)), PieceTeam.Ally);
else
break;
}
#endregion
#region Attack
for (int x = -1; x < 2; x += 2)
{
if (location.Y + (direction) > 7 || location.Y + (direction) < 0 || location.X + x > 7 || location.X + x < 0)
continue;
if (onlyAttackFields || (fields[(int)location.X + x, (int)location.Y + (direction)].currentPiece != null && fields[(int)location.X + x, (int)location.Y + (direction)].currentPiece.color != this.color))
{
targetFields.Add(new Vector((int)location.X + x, (int)location.Y + (direction)), PieceTeam.Enemy);
}
}
#endregion
return targetFields;
}
} // EN-PASSANT MISSING
public class Knight : Piece
{
public Knight(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool ignoreKingCheck = false, bool testKingDanger = false)
{
var targetFields = GetTargetFields(fields, location, this.color);
/* if (!testKingDanger)
foreach (var item in targetFields)
if (MoveWillEndangerKing(fields, location, item.Key, this.color))
targetFields.Remove(item.Key);*/
return targetFields;
}
private Dictionary<Vector, PieceTeam> GetTargetFields(Field[,] fields, Vector location, PieceColor color)
{
Dictionary<Vector, PieceTeam> targetFields = new Dictionary<Vector, PieceTeam>();
for (int a = -1; a < 2; a += 2)
{
for (int b = -2; b < 3; b += 4)
{
if (!(a + (int)location.X > 7 || b + (int)location.Y < 0 || a + (int)location.X < 0 || b + (int)location.Y > 7))
{
if (fields[a + (int)location.X, b + (int)location.Y].IsEmpty)
{
targetFields.Add(new Vector(a + (int)location.X, b + (int)location.Y), PieceTeam.Ally);
}
else
{
if (fields[a + (int)location.X, b + (int)location.Y].currentPiece.color != color)
targetFields.Add(new Vector(a + (int)location.X, b + (int)location.Y), PieceTeam.Enemy);
}
}
if (!(b + (int)location.X > 7 || a + (int)location.Y < 0 || b + (int)location.X < 0 || a + (int)location.Y > 7))
{
if (fields[b + (int)location.X, a + (int)location.Y].IsEmpty)
{
targetFields.Add(new Vector(b + (int)location.X, a + (int)location.Y), PieceTeam.Ally);
}
else
{
if (fields[b + (int)location.X, a + (int)location.Y].currentPiece.color != color)
targetFields.Add(new Vector(b + (int)location.X, a + (int)location.Y), PieceTeam.Enemy);
}
}
}
}
return targetFields;
}
} // FINALIZED
public class Bishop : Piece
{
public Bishop(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool onlyAttackFields = false, bool testKingDanger = false)
{
var targetFields = GetTargetFields(fields, location, this.color, onlyAttackFields);
/* if (!testKingDanger)
foreach (var item in targetFields)
if (MoveWillEndangerKing(fields, location, item.Key, this.color))
targetFields.Remove(item.Key);*/
return targetFields;
}
internal static Dictionary<Vector, PieceTeam> GetTargetFields(Field[,] fields, Vector location, PieceColor color, bool onlyAttackFields = true)
{
Dictionary<Vector, PieceTeam> targetFields = new Dictionary<Vector, PieceTeam>();
for (int xy = 1; xy <= 7; xy++) // nach RechtsOben
{
if (location.X + xy > 7 || (int)location.Y + xy > 7)
break;
if (fields[xy + (int)location.X, xy + (int)location.Y].IsEmpty)
{
targetFields.Add(new Vector(xy + (int)location.X, xy + (int)location.Y), PieceTeam.Ally);
}
else
{
if (fields[xy + (int)location.X, xy + (int)location.Y].currentPiece.color != color)
targetFields.Add(new Vector(xy + (int)location.X, xy + (int)location.Y), PieceTeam.Enemy);
break;
}
}
for (int xy = 1; xy <= 7; xy++) // nach LinksOben
{
if (location.X - xy < 0 || (int)location.Y + xy > 7)
break;
if (fields[(int)location.X - xy, (int)location.Y + xy].IsEmpty)
{
targetFields.Add(new Vector(location.X - xy, (int)location.Y + xy), PieceTeam.Ally);
}
else
{
if (fields[(int)location.X - xy, (int)location.Y + xy].currentPiece.color != color)
targetFields.Add(new Vector(location.X - xy, (int)location.Y + xy), PieceTeam.Enemy);
break;
}
}
for (int xy = 1; xy <= 7; xy++) // nach RechtsUnten
{
if (location.X + xy > 7 || (int)location.Y - xy < 0)
break;
if (fields[xy + (int)location.X, (int)location.Y - xy].IsEmpty)
{
targetFields.Add(new Vector(xy + (int)location.X, (int)location.Y - xy), PieceTeam.Ally);
}
else
{
if (fields[xy + (int)location.X, (int)location.Y - xy].currentPiece.color != color)
targetFields.Add(new Vector(xy + (int)location.X, (int)location.Y - xy), PieceTeam.Enemy);
break;
}
}
for (int xy = 1; xy <= 7; xy++) // nach LinksUnten
{
if (location.X - xy < 0 || (int)location.Y - xy < 0)
break;
if (fields[(int)location.X - xy, (int)location.Y - xy].IsEmpty)
{
targetFields.Add(new Vector(location.X - xy, (int)location.Y - xy), PieceTeam.Ally);
}
else
{
if (fields[(int)location.X - xy, (int)location.Y - xy].currentPiece.color != color)
targetFields.Add(new Vector(location.X - xy, (int)location.Y - xy), PieceTeam.Enemy);
break;
}
}
return targetFields;
}
} // FINALIZED
public class Queen : Piece
{
public Queen(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool ignoreKingCheck = false, bool testKingDanger = false)
{
Dictionary<Vector, PieceTeam> targetFields = Rook.GetTargetFields(fields, location, this.color);
targetFields = targetFields.Concat(Bishop.GetTargetFields(fields, location, this.color)
.Where(kvp => !targetFields.ContainsKey(kvp.Key)))
.OrderBy(c => c.Value)
.ToDictionary(c => c.Key, c => c.Value);
/*if (!testKingDanger)
foreach (var item in targetFields)
if (MoveWillEndangerKing(fields, location, item.Key, this.color))
targetFields.Remove(item.Key);*/
return targetFields;
}
} // FINALIZED
public class King : Piece
{
public King(PieceColor color)
{
type = (PieceType)Enum.Parse(typeof(PieceType), this.GetType().Name);
this.color = color;
this.image = (Image)ChessPanel.Properties.Resources.ResourceManager.GetObject($"{this.type.ToString()}{this.color.ToString()}");
}
internal override Dictionary<Vector, PieceTeam> GetValidTargetFields(Field[,] fields, Vector location, bool ignoreKingCheck = false, bool testKingDanger = false) // ignoreKingCheck hat keinen Einfluss
{
return GetTargetFields(fields, location, this.color);
}
private Dictionary<Vector, PieceTeam> GetTargetFields(Field[,] fields, Vector location, PieceColor color)
{
Dictionary<Vector, PieceTeam> targetFields = new Dictionary<Vector, PieceTeam>();
#region Castling
if (!this.HasMoved) // Only Castle if King did not move
foreach (var item in fields)
{
var itemLocation = item.location;
// Sucht nach Ally Turm und prüft, ob er sich schon bewegt hat
if (item.currentPiece != null && item.currentPiece.type == PieceType.Rook && !item.currentPiece.HasMoved && item.currentPiece.color == this.color)
{
if (itemLocation.X == 0 || itemLocation.X == 7)
{
bool castling = true;
for (int x = (itemLocation.X == 0 ? 1 : 5); (itemLocation.X == 0 ? x < 4 : x < 7); x++)
{
if (!fields[x, (int)location.Y].IsEmpty)
{
castling = false;
break;
}
}
if (castling) // Only Check endangered Fields if castling is generally possible
{
for (int x = (itemLocation.X == 0 ? 2 : 4); x < (itemLocation.X == 0 ? 5 : 7); x++) // König steht im Schach oder überschreitet bedrohtes Feld
{
if (IsEndangeredLocationForPiece(fields, location, new Vector(x, location.Y), color))
{
castling = false;
break;
}
}
if (castling)
{
targetFields.Add(new Vector((itemLocation.X == 0 ? 2 : 6), itemLocation.Y), PieceTeam.Ally);
}
}
}
}
}
#endregion
#region Movement: 1 in every direction
for (int x = -1; x < 2; x++)
{
for (int y = -1; y < 2; y++)
{
if ((x == 0 && y == 0) || location.X + x > 7 || location.Y + y > 7 || location.X + x < 0 || location.Y + y < 0)
continue;
if (!IsEndangeredLocationForPiece(fields, location, new Vector(location.X + x, location.Y + y), color))
if (fields[(int)location.X + x, (int)location.Y + y].IsEmpty)
{
targetFields.Add(new Vector(location.X + x, (int)location.Y + y), PieceTeam.Ally);
}
else
{
if (fields[(int)location.X + x, (int)location.Y + y].currentPiece.color != color)
targetFields.Add(new Vector(location.X + x, (int)location.Y + y), PieceTeam.Enemy);
continue;
}
}
}
#endregion
return targetFields;
}
} // CHECKMATE/CHECK-TEST MISSING
}