chess/Posuniecie.cs

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