358 lines
14 KiB
C#
358 lines
14 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace Chess
|
|
{
|
|
public class Posuniecie
|
|
{
|
|
private Pole figuraPole;
|
|
public RuchFigury?[] mozliweRuchy;
|
|
public Posuniecie() { poprzedniRuchy = new RuchFigury(1, 1); }
|
|
public Posuniecie(Pole figuraPole) : this()
|
|
{
|
|
this.figuraPole = figuraPole;
|
|
mozliweRuchy = Ruchy();
|
|
}
|
|
public bool jestRuchMozliwy(Pole wybranePole)
|
|
{
|
|
InterfejsObslugiPoprzednichRuchow(false);
|
|
for (int ruch = 0; ruch < mozliweRuchy.Length; ruch++)
|
|
{
|
|
if (mozliweRuchy[ruch] == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (mozliweRuchy[ruch]?.x == wybranePole.lokalizacja.x && mozliweRuchy[ruch]?.y == wybranePole.lokalizacja.y)
|
|
{
|
|
if (!ACzyMoznaSieRuszyc(ruch, wybranePole))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Szachownica.poprzednieRuchy.Add(new PoprzedniStanSzachownicy(figuraPole.figura, figuraPole.lokalizacja, (RuchFigury)mozliweRuchy[ruch], wybranePole.figura, ruch));
|
|
figuraPole.figura.pierwszyRuch = false;
|
|
wybranePole.PrzydzialFigur(figuraPole.figura);
|
|
figuraPole.PrzydzialFigur(new Figura(RodzajFigury.EMPTY));
|
|
if (!WybranieFigury.waiting)
|
|
{
|
|
Szachownica.KogoTerazTura = Szachownica.KogoTerazTura == Kolor.WHITE ? Kolor.BLACK : Kolor.WHITE;
|
|
Figura.ZaaktualizujWszystkieAtaki();
|
|
if (SyndromOblezonejTwierdzy())
|
|
{
|
|
Szachownica.Window.GameState.Text = "Szach";
|
|
Szachownica.Window.GameState.ForeColor = System.Drawing.Color.Firebrick;
|
|
_ = Mat();
|
|
}
|
|
else
|
|
{
|
|
Szachownica.Window.GameState.Text = "";
|
|
Szachownica.Window.GameState.ForeColor = System.Drawing.Color.OliveDrab;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
public void InterfejsObslugiPoprzednichRuchow(bool show)
|
|
{
|
|
for (int i = 0; i < mozliweRuchy.Length; i++)
|
|
{
|
|
if (mozliweRuchy[i] == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (figuraPole.figura.rodzajfigury == RodzajFigury.Pawn && ((i == 2 && nieJestZajetePole(figuraPole.lokalizacja.y + dir, figuraPole.lokalizacja.x + 1))
|
|
|| (i == 3 && nieJestZajetePole(figuraPole.lokalizacja.y + dir, figuraPole.lokalizacja.x - 1))))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Szachownica.pola[(int)mozliweRuchy[i]?.y, (int)mozliweRuchy[i]?.x].PossibleMove(show);
|
|
}
|
|
}
|
|
public bool SyndromOblezonejTwierdzy()
|
|
{
|
|
return Szachownica.JakieToPole(RodzajFigury.King, Szachownica.KogoTerazTura).atakNaPole != Kolor.NONE;
|
|
}
|
|
|
|
public bool Mat()
|
|
{
|
|
List<Pole> figuraPola = Szachownica.ZbierzWszystkieFiguryPola(Szachownica.KogoTerazTura);
|
|
for (int j = 0; j < figuraPola.Count; j++)
|
|
{
|
|
figuraPole = figuraPola[j];
|
|
mozliweRuchy = Ruchy();
|
|
if (CzyKrolJestBezpieczny())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
Szachownica.Window.GameState.Text = "Mat!";
|
|
Szachownica.Window.GameState.ForeColor = System.Drawing.Color.Firebrick;
|
|
Szachownica.Window.ZatrzymajZegar();
|
|
return true;
|
|
}
|
|
public bool CzyKrolJestBezpieczny()
|
|
{
|
|
for (int ruch = 0; ruch < mozliweRuchy.Length; ruch++)
|
|
{
|
|
if (mozliweRuchy[ruch] == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!MoznaSieRuszac((int)mozliweRuchy[ruch]?.y, (int)mozliweRuchy[ruch]?.x))
|
|
{
|
|
mozliweRuchy[ruch] = null;
|
|
}
|
|
}
|
|
for (int i = 0; i < mozliweRuchy.Length; i++)
|
|
{
|
|
if (mozliweRuchy[i].HasValue)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private bool MoznaSieRuszac(int y, int x)
|
|
{
|
|
Figura poprzedniePoleFigury = Szachownica.pola[y, x].figura;
|
|
Szachownica.pola[y, x].figura = figuraPole.figura;
|
|
figuraPole.figura = new Figura(RodzajFigury.EMPTY);
|
|
Figura.ZaaktualizujWszystkieAtaki();
|
|
if (!SyndromOblezonejTwierdzy())
|
|
{
|
|
figuraPole.figura = Szachownica.pola[y, x].figura;
|
|
Szachownica.pola[y, x].figura = poprzedniePoleFigury;
|
|
}
|
|
else
|
|
{
|
|
figuraPole.figura = Szachownica.pola[y, x].figura;
|
|
Szachownica.pola[y, x].figura = poprzedniePoleFigury;
|
|
Figura.ZaaktualizujWszystkieAtaki();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private bool ACzyMoznaSieRuszyc(int move, Pole kliknietePole)
|
|
{
|
|
switch (figuraPole.figura.rodzajfigury)
|
|
{
|
|
case RodzajFigury.Pawn:
|
|
figuraPole.figura.ruchODwaPola = move == 1;
|
|
if (move == 2 && nieJestZajetePole(figuraPole.lokalizacja.y + dir, figuraPole.lokalizacja.x + 1))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (move == 3 && nieJestZajetePole(figuraPole.lokalizacja.y + dir, figuraPole.lokalizacja.x - 1))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (move == 4 || move == 5)
|
|
{
|
|
int xdir = move == 4 ? 1 : -1;
|
|
Szachownica.pola[figuraPole.GetY, figuraPole.GetX + xdir].PrzydzialFigur(new Figura(RodzajFigury.EMPTY)); return true;
|
|
}
|
|
if ((figuraPole.GetY == 1 && figuraPole.figura.kolor == Kolor.WHITE) || (figuraPole.GetY == 6 && figuraPole.figura.kolor == Kolor.BLACK))
|
|
{
|
|
WybranieFigury pieceSelection = new WybranieFigury(kliknietePole);
|
|
pieceSelection.Show();
|
|
}
|
|
break;
|
|
case RodzajFigury.King:
|
|
int ydir = Szachownica.KogoTerazTura == Kolor.WHITE ? 7 : 0;
|
|
void castle(int tilex, int piecex)
|
|
{
|
|
Szachownica.pola[ydir, tilex].PrzydzialFigur(Szachownica.JakaToFigura(ydir, piecex));
|
|
Szachownica.pola[ydir, piecex].PrzydzialFigur(new Figura(RodzajFigury.EMPTY));
|
|
}
|
|
if (move == 8)
|
|
{
|
|
castle(5, 7);
|
|
}
|
|
|
|
if (move == 9)
|
|
{
|
|
castle(3, 0);
|
|
}
|
|
|
|
break;
|
|
default: break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private RuchFigury? poprzedniRuchy;
|
|
private int move;
|
|
|
|
private RuchFigury?[] Ruchy()
|
|
{
|
|
RuchFigury?[] ruchy = new RuchFigury?[8];
|
|
move = 0;
|
|
switch (figuraPole.figura.rodzajfigury)
|
|
{
|
|
case RodzajFigury.Bishop: ruchy = new RuchFigury?[32]; RuchLiniowy(ruchy, false); break;
|
|
case RodzajFigury.Knight:
|
|
ruchy[0] = destynacja(2, -1);
|
|
ruchy[1] = destynacja(2, 1);
|
|
ruchy[2] = destynacja(-2, 1);
|
|
ruchy[3] = destynacja(-2, -1);
|
|
ruchy[4] = destynacja(1, -2);
|
|
ruchy[5] = destynacja(1, 2);
|
|
ruchy[6] = destynacja(-1, -2);
|
|
ruchy[7] = destynacja(-1, 2);
|
|
break;
|
|
case RodzajFigury.Queen:
|
|
ruchy = new RuchFigury?[64];
|
|
RuchLiniowy(ruchy, false);
|
|
poprzedniRuchy = new RuchFigury(1, 1);
|
|
RuchLiniowy(ruchy, true);
|
|
break;
|
|
case RodzajFigury.Rook: ruchy = new RuchFigury?[32]; RuchLiniowy(ruchy, true); break;
|
|
case RodzajFigury.King:
|
|
ruchy = new RuchFigury?[10];
|
|
ruchy[0] = destynacja(1, -1);
|
|
ruchy[1] = destynacja(1, 1);
|
|
ruchy[2] = destynacja(-1, 1);
|
|
ruchy[3] = destynacja(-1, -1);
|
|
ruchy[4] = destynacja(1, 0);
|
|
ruchy[5] = destynacja(-1, 0);
|
|
ruchy[6] = destynacja(0, -1);
|
|
ruchy[7] = destynacja(0, 1);
|
|
bool CanCastle(int dir)
|
|
{
|
|
int range = dir == 1 ? 3 : 4;
|
|
for (int i = 1; i < range; i++)
|
|
{
|
|
if (jestZajete(figuraPole.GetY, figuraPole.GetX + (i * dir)) ||
|
|
(Szachownica.pola[figuraPole.GetY, figuraPole.GetX + (i * dir)].atakNaPole != Kolor.NONE))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
if (figuraPole.figura.pierwszyRuch && Szachownica.JakaToFigura(figuraPole.GetY, figuraPole.GetX + 3).pierwszyRuch) //right castling
|
|
{
|
|
ruchy[8] = CanCastle(1) ? destynacja(0, 2) : null;
|
|
}
|
|
|
|
if (figuraPole.figura.pierwszyRuch && Szachownica.JakaToFigura(figuraPole.GetY, figuraPole.GetX - 4).pierwszyRuch) //left castling
|
|
{
|
|
ruchy[9] = CanCastle(-1) ? destynacja(0, -2) : null;
|
|
}
|
|
|
|
break;
|
|
case RodzajFigury.Pawn:
|
|
ruchy = new RuchFigury?[6];
|
|
ruchy[0] = nieJestZajetePole(figuraPole.lokalizacja.y + (1 * dir), figuraPole.lokalizacja.x) ? destynacja(1 * dir, 0) : poprzedniRuchy = null;
|
|
if (poprzedniRuchy != null)
|
|
{
|
|
ruchy[1] = nieJestZajetePole(figuraPole.GetY + (2 * dir), figuraPole.GetX) && figuraPole.figura.pierwszyRuch ? destynacja(2 * dir, 0) : null;
|
|
}
|
|
|
|
ruchy[2] = destynacja(dir, 1);
|
|
ruchy[3] = destynacja(dir, -1);
|
|
ruchy[4] = czyJestPionemPrzeciwnika(figuraPole.GetY, figuraPole.GetX + 1) && !jestZajete(figuraPole.GetY + dir, figuraPole.GetX + 1) ? destynacja(dir, 1) : null;
|
|
ruchy[5] = czyJestPionemPrzeciwnika(figuraPole.GetY, figuraPole.GetX - 1) && !jestZajete(figuraPole.GetY + dir, figuraPole.GetX - 1) ? destynacja(dir, -1) : null;
|
|
break;
|
|
}
|
|
return ruchy;
|
|
}
|
|
|
|
private int dir => figuraPole.figura.kolor == Kolor.BLACK ? 1 : -1;
|
|
|
|
private void RuchLiniowy(RuchFigury?[] ruchy, bool liniaProsta)
|
|
{
|
|
int rookDir = liniaProsta ? 0 : 1; int bishopDir = liniaProsta ? 1 : -1;
|
|
for (int i = 1; i < 9; i++)
|
|
{
|
|
ruchy[move] = destynacjaLiniowa(-i, i * bishopDir * rookDir);
|
|
}
|
|
|
|
poprzedniRuchy = new RuchFigury(1, 1); for (int i = 1; i < 9; i++)
|
|
{
|
|
ruchy[move] = destynacjaLiniowa(i, i * rookDir);
|
|
}
|
|
|
|
poprzedniRuchy = new RuchFigury(1, 1); for (int i = 1; i < 9; i++)
|
|
{
|
|
ruchy[move] = destynacjaLiniowa(i * rookDir, -i);
|
|
}
|
|
|
|
poprzedniRuchy = new RuchFigury(1, 1); for (int i = 1; i < 9; i++)
|
|
{
|
|
ruchy[move] = destynacjaLiniowa(i * bishopDir * rookDir, i);
|
|
}
|
|
}
|
|
|
|
private RuchFigury? destynacjaLiniowa(int y, int x)
|
|
{
|
|
return poprzedniRuchy == null ? null : destynacja(y, x);
|
|
}
|
|
|
|
private RuchFigury? destynacja(int y, int x)
|
|
{
|
|
int LokacjaY = figuraPole.lokalizacja.y + y;
|
|
int LokacjaX = figuraPole.lokalizacja.x + x;
|
|
move++;
|
|
if (czyDostepUdzielony(LokacjaY, LokacjaX))
|
|
{
|
|
if (jestZajete(LokacjaY, LokacjaX) && figuraPole.figura.kolor != KolorPrzeciwnika(LokacjaY, LokacjaX))
|
|
{
|
|
poprzedniRuchy = null;
|
|
return new RuchFigury(LokacjaY, LokacjaX);
|
|
}
|
|
return jestZajete(LokacjaY, LokacjaX) ? (poprzedniRuchy = null) : (poprzedniRuchy = new RuchFigury(LokacjaY, LokacjaX));
|
|
}
|
|
else
|
|
{
|
|
return poprzedniRuchy = null;
|
|
}
|
|
}
|
|
|
|
private bool czyDostepUdzielony(int y, int x)
|
|
{
|
|
return Szachownica.czyMoznaWbic(y, x);
|
|
}
|
|
|
|
private bool jestZajete(int y, int x)
|
|
{
|
|
return Szachownica.pola[y, x].jestZajete();
|
|
}
|
|
|
|
private bool czyJestPionemPrzeciwnika(int y, int x)
|
|
{
|
|
return czyDostepUdzielony(y, x)
|
|
&& jestZajete(y, x) && Szachownica.JakaToFigura(y, x).ruchODwaPola && jestPrzeciwnegoKoloru(y, x);
|
|
}
|
|
|
|
private bool nieJestZajetePole(int y, int x)
|
|
{
|
|
return czyDostepUdzielony(y, x) && !jestZajete(y, x);
|
|
}
|
|
|
|
private bool jestPrzeciwnegoKoloru(int y, int x)
|
|
{
|
|
return figuraPole.figura.kolor != KolorPrzeciwnika(y, x) && KolorPrzeciwnika(y, x) != Kolor.NONE;
|
|
}
|
|
|
|
private Kolor KolorPrzeciwnika(int y, int x)
|
|
{
|
|
return Szachownica.pola[y, x].figura.kolor;
|
|
}
|
|
}
|
|
public struct RuchFigury
|
|
{
|
|
public int y, x;
|
|
public RuchFigury(int y, int x) { this.y = y; this.x = x; }
|
|
}
|
|
} |