/*********************************************/
/* Programm z.B. in "chess.c" speichern; */
/* compilieren mit cc/gcc/CC/c++/g++ (egal) */
/* z.B. "cc chess.c -o chess" */
/* Aufruf mit "chess" oder "./chess" */
/*********************************************/
/* --------------------------------------------------------------- */
/* --------------------------------------------------------------- */
/*********************************************/
/* Bedienung des Programms:-) */
/* Nach Aufruf des Programms: Rechentiefe */
/* und Tiefe fuer die Ruhesuche eingeben. */
/* */
/* hinter "your move: " kann */
/* 1. ein "q" fuer "quit" eingegeben werden */
/* 2. ein "p" fuer "play move" */
/* 3. ein "00" fuer die kurze Rochade */
/* 4. ein "000" fuer die lange Rochade */
/* 5. ein beliebiger Zug in KLEINBUCHSTABEN */
/* */
/* eine Ueberpruefung der Zuege wird nicht */
/* vorgenommen. */
/*********************************************/
/* --------------------------------------------------------------- */
/* --------------------------------------------------------------- */
/*********************************************/
/* Dieses kleine Schachprogramm soll dem */
/* Interessierten einen Einblick in die */
/* Schachprogrammierung geben; */
/* es ist mit Sicherheit nicht gut */
/* optimiert, aber (hoffentlich) so einfach */
/* zu verstehen, dass zum Experimentieren */
/* anregt; */
/* */
/* wesentliche Verbesserungen waeren: */
/* - sukkzessiv die Rechentiefe erhoehen */
/* und zwischendrin sortieren (dadurch */
/* werden die besseren Zuege zuerst be- */
/* rechnet, und wesentlich mehr Schnitte */
/* am Suchbaum vorgenommen) [- ][----] */
/* - Nega-Scout [--- ][- ] */
/* - Schach-Vertiefung [----][--- ] */
/* - bessere Stellungsbewert. [-- ][----] */
/* - Code optimieren (x3..x5) [--- ][--- ] */
/* - Rochade implementieren [-- ][-- ] */
/* - zusaetzliche Heuristiken */
/* fuer die Vertiefung [----][----] */
/* - Spielphase (Eroeffn., */
/* Mittel- u. Endspiel) in */
/* der Bewert. beruecksicht.[- ][-- ] */
/* - eine kleine Eroeffnungs- [- ][-- ] */
/* bibliothek */
/* in Klammern bedeuten: */
/* 1. Komplexitaet/Aufwand [....] */
/* 2. Wirkung [....] */
/* */
/* es haelt sogar meist um 20 Zuege gegen */
/* GNUchess aus (bis jetzt max. max 29) und */
/* spielt etwa wie Mephisto Mini.
/* */
/* (geschrieben von Andre Heuner, 27.05.99) */
/*********************************************/
/* --------------------------------------------------------------- */
/* --------------------------------------------------------------- */
#include
#include
#include
/* --------------------------------------------------------------- */
/*********************************************/
/* Konst. fuer Farben, maximale Rechentiefe */
/* und generierbare Zuege je Position, */
/* Figuren, Leerfeld und Randmarkierung */
/* (nicht betretbare Felder, s.u.) */
/*********************************************/
#define white 1
#define black -1
#define maxPly 16
#define maxPsn 128
#define pawn 100
#define knight 320
#define bishop 324
#define rook 512
#define queen 900
#define king 9999
#define empty 0
#define border 1
/* --------------------------------------------------------------- */
/*********************************************/
/* Das Schachbrett wird statt 8x8 10x12 */
/* definiert und es wird eine Markierung */
/* fuer nicht betretbare Felder eingefuehrt */
/* -> somit erleichtert sich die Randabfrage */
/* etwas (siehe auch den Zuegegenerator) */
/* */
/* Brett: */
/* board[0] %%%%%%%%%% board[9] */
/* %%%%%%%%%% */
/* a8 %oooooooo% h8 */
/* %oooooooo% */
/* %........% Legende: */
/* %........% % Rand */
/* %........% o Figuren */
/* %........% . Leerfelder */
/* %oooooooo% */
/* a1 %oooooooo% h1 */
/* %%%%%%%%%% */
/* %%%%%%%%%% board[119] */
/* */
/*********************************************/
/******************************/
int maxDepth; /* Rechentiefe */
int maxExt; /* zusaetzliche Vertiefung; */
/* hier als globale Variablen */
/* */
int colorToMove; /* Farbe am Zug */
int move; /* Zum merken des besten */
/* Zuges -> from/to[1, move] */
/* */
int board[120]; /* Schachbrett 10x12 (s.o.) */
/* */
int captNo; /* zum zaehlen der in FOLGE */
int captures[256]; /* ausgefuehrten Schlagzuege */
/* auf dem (internen) Brett */
/* aktuell: captures[captNo] */
/* */
int from[maxPly][maxPsn]; /* Ausgangsfelder der Zuege */
int to[maxPly][maxPsn]; /* Endpositionen der Zuege */
int capt[maxPly][maxPsn]; /* Geschlagene Figur */
int prom[maxPly][maxPsn]; /* Umwandlung: ja/nein */
/******************************/
/*********************************************/
/* Das Zaehlen der in Folge ausgefuehrten */
/* Schlagzuege dient der Eindaemmung des */
/* Horizonteffektes beim Schlagen: wird der */
/* Suchbaum naemlich nur nach einer geraden */
/* Anzahl von Schlagzuegen beschnitten, so */
/* ist die Auswirkung i.d.R. nicht sooo */
/* verhehrend. Dies ist eine SEHR wirksame */
/* Heuristik !-) */
/*********************************************/
/* --------------------------------------------------------------- */
/*********************************************/
/* Richtungen fuer die Zuegegeneration */
/*********************************************/
int pawnDrc[4] = {-11, -9,-10,-20};
int bishopDrc[4] = {-11, 11, -9, 9};
int rookDrc[4] = {-10, 10, -1, 1};
int knightDrc[8] = {-21, 21, -8, 8, -12, 12, -19, 19};
int queenDrc[8] = {-10, 10, -1, 1, -11, 11, -9, 9};
int kingDrc[8] = {-10, 10, -1, 1, -11, 11, -9, 9};
/* --------------------------------------------------------------- */
/* --------------------------------------------------------------- */
/*********************************************/
/* kleine Hilfsroutine: vertauscht den */
/* Inhalt zweier Positionen auf dem Brett; */
/* wird fuer die Ausfuehrung der Rochade */
/* benutzt */
/*********************************************/
void swapPieces (int psnI, int psnII)
{
int piece;
piece = board[psnI ];
board[psnI ] = board[psnII];
board[psnII] = piece;
}
/* --------------------------------------------------------------- */
/*********************************************/
/* Initialisierung: Brett aufbauen (s.o.), */
/* Weiss faengt an und noch kein Schlagzug */
/* ausgefuehrt */
/*********************************************/
void init ()
{
int nmbr;
for (nmbr = 0; nmbr < 120; nmbr++) board[nmbr] = border;
for (nmbr = 31; nmbr < 39; nmbr++) board[nmbr] = -pawn;
for (nmbr = 41; nmbr < 49; nmbr++) board[nmbr] = empty;
for (nmbr = 51; nmbr < 59; nmbr++) board[nmbr] = empty;
for (nmbr = 61; nmbr < 69; nmbr++) board[nmbr] = empty;
for (nmbr = 71; nmbr < 79; nmbr++) board[nmbr] = empty;
for (nmbr = 81; nmbr < 89; nmbr++) board[nmbr] = pawn;
board[21] = -rook; board[91] = rook;
board[22] = -knight; board[92] = knight;
board[23] = -bishop; board[93] = bishop;
board[24] = -queen; board[94] = queen;
board[25] = -king; board[96] = bishop;
board[26] = -bishop; board[95] = king;
board[27] = -knight; board[97] = knight;
board[28] = -rook; board[98] = rook;
colorToMove = 1;
captNo = 0;
captures[0] = 0;
}
/* --------------------------------------------------------------- */
/*********************************************/
/* unsere 2D-Visualisierung ;-) */
/*********************************************/
void drawBoard ()
{
int nmbr;
system ("clear");
for (nmbr = 19; nmbr < 102; nmbr++)
{
switch (board[nmbr])
{
case pawn : printf ("o¸"); break;
case -pawn : printf ("o "); break;
case knight : printf ("§¸"); break;
case -knight : printf ("§ "); break;
case bishop : printf ("0¸"); break;
case -bishop : printf ("0 "); break;
case rook : printf ("=¸"); break;
case -rook : printf ("= "); break;
case queen : printf ("8¸"); break;
case -queen : printf ("8 "); break;
case king : printf ("+¸"); break;
case -king : printf ("+ "); break;
case empty : printf ("· "); break;
case border : printf ("\n"); nmbr++; break;
}
}
}
/* --------------------------------------------------------------- */
/* --------------------------------------------------------------- */
/*********************************************/
/* Der Zuegenerator: */
/* es werden die Figuren auf dem Brett in */
/* einer Schleife aufgesucht, und deren */
/* Zuege generiert. Die Behandlung von */
/* Weiss und Schwarz wird durch Multiplik. */
/* mit dem Parameter fuer die Farbe */
/* zusammengefasst. */
/* */
/* Der Zuegegenerator bekommt als Parameter */
/* die Farbe, fuer die die Zuege generiert */
/* werden sollen und einen Parameter "ply" */
/* der festlegt wohin die generierten Zuege */
/* gespeichert werden sollen: diese werden */
/* in from[ply][..] und to[ply][..] abgelegt */
/* Der Zuegegenerator verwendet sonst nur */
/* noch das interne Brett "board" und die */
/* "Richtungs"-Arrays (s.o.) */
/* */
/* Struktur: */
/* - suche Figuren der Farbe "color" */
/* - Bauer */
/* - Schlagzuege */
/* - Bauer vorziehen */
/* - Bauer zwei vorziehen */
/* - Springer */
/* - Laeufer */
/* - Turm */
/* - Dame */
/* - Koenig */
/* */
/* Es fehlen: */
/* - Rochaden: */
/* Hierzu muessten einmal "moveBack" */
/* und "moveForward" so erweitert, */
/* dass sie die Bewegung des Koenigs */
/* und der Tuerme mitprotokoliert; */
/* anschliessend kann hinter die */
/* Schleife im Zuegegenerator die */
/* Generierung erfolgen; zu testen: */
/* 1. stehen Koenig/Turm richtig */
/* 2. Koenig/Turm nicht bewegt */
/* 3. sind die zwei Zwischenfelder */
/* leer */
/* 4. Koenig und uebersprungenes */
/* Feld sind unbedroht (den Rest */
/* macht der Suchbaum) */
/* - En Passent */
/* Erweiterung von "move...": */
/* falls ein Bauer zwei vorgezogen */
/* wird -> Linie merken; En Pass. */
/* schlagen moeglich wenn: */
/* 1. Bauer auf richtiger Reihe */
/* 2. Bauer steht auf einer Linie, */
/* neben der zuvor ein Bauer zwei */
/* vorgezogen hat. */
/* - Unterverwandlungen */
/* Am besten viermal einfuegen und */
/* die Information, in welche Figur */
/* (Spr., Laeuf., Turm, Dame) */
/* umgewandelt wird z.B. in "prom" */
/* speichern */
/*********************************************/
int generateMoves (int color, int ply)
{
/**************************************/
int psn; /* Schleifenzaehler fuer Figurensuche */
int no; /* Hilfsschleifenzaehler */
int drc; /* Richtungen fuer Zuegegeneration */
int moves; /* Zaehler fuer generierte Zuege */
/**************************************/
for (psn = 0, moves = 0; psn < 120; psn++)
{
if (color *board[psn] > 0)
switch (board[psn])
{
case pawn :
case -pawn : for (no = 0; no < 2; no++)
if (board[psn +color *pawnDrc[no]] *-color >= pawn)
{
from[ply][moves ] = psn;
to [ply][moves++] = color *pawnDrc[no] +psn;
}
if (board[psn +color *pawnDrc[2]] == empty)
{
from[ply][moves ] = psn;
to [ply][moves++] = color *pawnDrc[2] +psn;
}
if ((board[psn +color *pawnDrc[2]] == empty) &&
(board[psn +color *pawnDrc[3]] == empty) &&
(((color == 1) && (psn > 80)) ||
((color == -1) && (psn < 40)) ))
{
from[ply][moves ] = psn;
to [ply][moves++] = color *pawnDrc[3] +psn;
}
break;
case knight :
case -knight : for (no = 0; no < 8; no++)
if ((board[psn +knightDrc[no]] == empty) ||
(board[psn +knightDrc[no]] *-color >= pawn))
{
from[ply][moves ] = psn;
to [ply][moves++] = knightDrc[no] +psn;
}
break;
case bishop :
case -bishop : for (no = 0, drc = bishopDrc[no]; no < 4;
no+= 1, drc = bishopDrc[no])
do
if ((board[psn +drc] == empty) ||
(board[psn +drc] *-color >= pawn))
{
from[ply][moves ] = psn;
to [ply][moves++] = drc +psn;
}
while (board[psn +(drc += bishopDrc[no])-
bishopDrc[no]] == empty);
break;
case rook :
case -rook : for (no = 0, drc = rookDrc[no]; no < 4;
no+= 1, drc = rookDrc[no])
do
if ((board[psn +drc] == empty) ||
(board[psn +drc] *-color >= pawn))
{
from[ply][moves ] = psn;
to [ply][moves++] = drc +psn;
}
while (board[psn +(drc += rookDrc[no])-
rookDrc[no]] == empty);
break;
case queen :
case -queen : for (no = 0, drc = queenDrc[no]; no < 8;
no+= 1, drc = queenDrc[no])
do
if ((board[psn +drc] == empty) ||
(board[psn +drc] *-color >= pawn))
{
from[ply][moves ] = psn;
to [ply][moves++] = drc +psn;
}
while (board[psn +(drc += queenDrc[no])-
queenDrc[no]] == empty);
break;
case king :
case -king : for (no = 0; no < 8; no++)
if ((board[psn +kingDrc[no]] == empty) ||
(board[psn +kingDrc[no]] *-color >= pawn))
{
from[ply][moves ] = psn;
to [ply][moves++] = kingDrc[no] +psn;
}
break;
}
}
return(moves);
}
/* --------------------------------------------------------------- */
/*********************************************/
/* Zieht den Zug from/to[ply][psn] vor; */
/* ggfs. Umwandlung (hier immer zur Dame); */
/* anschliessend: falls dies kein Schlagzug */
/* ist, dann Anzahl der in Folge ausgef. */
/* Schlagzuege gleich Null; sonst Wert von */
/* vorher plus eins */
/*********************************************/
void moveForward (int ply, int psn)
{
if ( ((board[from[ply][psn]] == pawn) && (from[ply][psn] < 40)) ||
((board[from[ply][psn]] == -pawn) && (from[ply][psn] > 80)) ) prom[ply][psn] = 1;
else prom[ply][psn] = 0;
capt[ply][psn] = board[ to[ply][psn]];
board[ to[ply][psn]] = board[from[ply][psn]];
board[from[ply][psn]] = empty;
if (prom[ply][psn])
{
if (board[to[ply][psn]] == pawn) board[to[ply][psn]] = queen;
if (board[to[ply][psn]] == -pawn) board[to[ply][psn]] = -queen;
}
if (capt[ply][psn] == 0) captures[++captNo] = 0;
else captures[++captNo] = captures[captNo -1] +1;
}
/* --------------------------------------------------------------- */
/*********************************************/
/* Zieht den Zug from/to[ply][psn] zurueck; */
/* ggfs. Rueckumwandlung */
/* ausserdem: den Zeiger auf das Feld, in */
/* dem die Zahl der in Folge ausgefuehrten */
/* Schlagzuege drinstehen um eins dekrem. */
/*********************************************/
void moveBack (int ply, int psn)
{
board[from[ply][psn]] = board[to[ply][psn]];
board[ to[ply][psn]] = capt[ply][psn];
if (prom[ply][psn])
{
if (board[from[ply][psn]] == queen) board[from[ply][psn]] = pawn;
if (board[from[ply][psn]] == -queen) board[from[ply][psn]] = -pawn;
}
captNo--;
}
/* --------------------------------------------------------------- */
/*********************************************/
/* Die Stellungsbewertung: */
/* wie beim Zuegegenerator durchs Brett */
/* flitzen und bei gefundenen Figuren deren */
/* - Material werten */
/* - Position (z.B. Zentrierung) */
/* - Stellung zu anderen Figuren */
/* (z.B. Doppelbauern) */
/* */
/* Die Stellungsbewertung bezieht sich nur */
/* auf das interne Brett; der Parameter, der */
/* die am Zug befindliche Farbe enthaelt, */
/* kann hin und wieder nuetzlich sein. */
/* */
/* WICHTIG: */
/* DIESE hier ist nur als ein BEISPIEL zu */
/* sehen; ich empfehle hier mal kraeftig */
/* rumzuprobieren :-) */
/* */
/* Kriterien hier: */
/* Material: alles zaehlen */
/* Bauer: Zentrierung, Zentrumsbauern */
/* blockieren, Doppelbauern, */
/* "Bauernketten" */
/* Springer: Zentrierung, Gabelung */
/* Laeufer: Zentrierung */
/* Turm: ins gegnerische Lager, Wirkung ins */
/* Zentrum, offene Linien, Verdoppl. */
/* Dame: mindest. beide Springer entwickelt */
/* bevor zu weit nach draussen */
/* Koenig: offene Angriffslinien vermeiden */
/* */
/* Das ganze ohne Bereichsabfragen => */
/* stochastischer Einfluss ;-) */
/*********************************************/
int evaluatePosition (int color)
{
/**************************************/
int psn; /* Laufvariable fuers Brett */
int pColor; /* Farbe der zu bewertenden Figur */
int score; /* Gesamtbewertung */
/**************************************/
for (psn = 0,
score = 0; psn < 120; psn++)
{
if (board[psn] >= pawn) pColor = 1;
if (board[psn] <= -pawn) pColor = -1;
switch (board[psn])
{
case pawn :
case -pawn : score += board[psn];
if ((psn == 54) || (psn == 55) ||
(psn == 64) || (psn == 65)) score += pColor *16;
if (((psn >= 73) && (psn <= 76)) ||
((psn >= 43) && (psn <= 46))) score += pColor *10;
score += pColor *(8- abs (9- ((psn %10) *2)));
if (((psn %10 == 4) ||
(psn %10 == 5)) &&
(board[psn -pColor *10] == empty)) score += pColor *10;
if ((board[psn -1 ] == pColor *pawn) ||
(board[psn +1 ] == pColor *pawn) ||
(board[psn - 9 *pColor] == pColor *pawn) ||
(board[psn -11 *pColor] == pColor *pawn)) score += pColor* +3;
if ((board[psn -10 *pColor] == pColor *pawn) ||
(board[psn -20 *pColor] == pColor *pawn) ||
(board[psn -30 *pColor] == pColor *pawn)) score += pColor* -20;
break;
case knight :
case -knight : score += board[psn];
if ((-pColor *board[psn -12] >= rook)
+(-pColor *board[psn - 8] >= rook)
+(-pColor *board[psn +12] >= rook)
+(-pColor *board[psn + 8] >= rook)
+(-pColor *board[psn -21] >= rook)
+(-pColor *board[psn -19] >= rook)
+(-pColor *board[psn +21] >= rook)
+(-pColor *board[psn +19] >= rook) >= 2) score += pColor *72;
score += pColor *((8- abs (9- ((psn %10 ) *2))) << 1);
score += pColor *((8- abs (9- ((psn /10 -1) *2))) << 1);
break;
case bishop :
case -bishop : score += board[psn];
score += pColor *((8- abs (9- ((psn %10 ) *2))) );
score += pColor *((8- abs (9- ((psn /10 -1) *2))) << 1);
break;
case rook :
case -rook : score += board[psn];
if ((pColor == white) && (psn <= 40)) score += 32;
if ((pColor == black) && (psn >= 80)) score += -32;
score += pColor *((8- abs (9- ((psn %10) *2))));
if ((board[psn -10 * pColor] != pColor *pawn) &&
(board[psn -20 * pColor] != pColor *pawn) &&
(board[psn -30 * pColor] != pColor *pawn) &&
(board[psn -40 * pColor] != pColor *pawn)) score += pColor *16;
if ((board[psn -10 * pColor] == pColor *rook) ||
(board[psn -20 * pColor] == pColor *rook) ||
(board[psn -30 * pColor] == pColor *rook) ||
(board[psn -40 * pColor] == pColor *rook)) score += pColor *16;
break;
case queen :
case -queen : score += board[psn];
if ((pColor == white) &&
(psn < 80) &&
((board[92] == knight) ||
(board[97] == knight))) score -= 32;
if ((pColor == black) &&
(psn > 40) &&
((board[22] == -knight) ||
(board[27] == -knight))) score -= -32;
break;
case king :
case -king : score += board[psn];
if ((board[psn - 9 * pColor] * pColor >= pawn) ||
(board[psn -18 * pColor] * pColor >= pawn)) score += pColor *16;
if ((board[psn -11 * pColor] * pColor >= pawn) ||
(board[psn -22 * pColor] * pColor >= pawn)) score += pColor *16;
if ((board[psn -10 * pColor] * pColor >= pawn) ||
(board[psn -20 * pColor] * pColor >= pawn) ||
(board[psn -30 * pColor] * pColor >= pawn)) score += pColor *16;
break;
}
}
return score;
}
/* --------------------------------------------------------------- */
/* --------------------------------------------------------------- */
/*********************************************/
/* Die Alpha-Beta Vertiefung */
/* d.h. HIER nur Schlagzuege betrachten */
/*********************************************/
int Extend (int color, int alpha,
int beta, int depth)
{
int no;
int noMoves;
int value = evaluatePosition (color);
if (color *value > color *alpha) alpha = value;
/***********************************************/
/* ist die maximale Tiefe erreicht, so wird */
/* auf jeden Fall die Stellungsbew. zurueck- */
/* gegeben; falls zwar noch ein Zug Vertiefung */
/* erlaubt ist, aber bereits eine gerade */
/* Anzahl Schlagzuege in Folge gespielt war, */
/* so wird vozeitig abgebrochen (s.o.); */
/* sonst geht's weiter */
/***********************************************/
if (depth > maxDepth +maxExt -1)
if ((depth > maxDepth +maxExt) ||
(!(captures[captNo]) % 2)) return value;
noMoves = generateMoves(color, depth);
for (no=0; no < noMoves; no++)
{
if (board[to[depth][no]])
{
if (board [to[depth][no]] == king) return -32000;
if (board [to[depth][no]] == -king) return 32000;
moveForward (depth, no);
value = Extend (-color, beta, alpha, depth +1);
if (color == white) if (value > alpha) alpha = value;
if (color == black) if (value < alpha) alpha = value;
moveBack (depth, no);
if (color == white) if (alpha > beta) return alpha;
if (color == black) if (alpha < beta) return alpha;
}
}
return alpha;
}
/* --------------------------------------------------------------- */
/*********************************************/
/* Der Alpha-Beta (den kennt man ja ;-) */
/*********************************************/
int alphaBeta (int color, int alpha,
int beta, int depth)
{
/************************************************/
/* ohne Vertiefung: */
/* if (depth > maxDepth) */
/* return evaluatePosition (color); else */
/************************************************/
if (depth > maxDepth)
return Extend (color, alpha, beta, depth); else
{
int no;
int noMoves;
int value;
noMoves = generateMoves(color, depth);
for (no=0; no < noMoves; no++)
{
if (board [to[depth][no]] == king) return -32000;
if (board [to[depth][no]] == -king) return 32000;
moveForward (depth, no);
value = alphaBeta (-color, beta, alpha, depth +1);
if (color == white)
if (value > alpha) { alpha = value; if (depth == 1) move = no; }
if (color == black)
if (value < alpha) { alpha = value; if (depth == 1) move = no; }
moveBack (depth, no);
if (color == white) if (alpha > beta) return alpha;
if (color == black) if (alpha < beta) return alpha;
}
return alpha;
}
}
/* --------------------------------------------------------------- */
/* --------------------------------------------------------------- */
/*********************************************/
/* Computerzug; besser ist sukzessives Er- */
/* hoehen der Rechentiefe mit zwischen- */
/* sortieren -> dazu ist aber auch eine */
/* Aenderung der Funktion "alphaBeta" */
/* notwendig, da sonst der Zuegegenerator */
/* die Reihenfolge der Zuege bestimmt. */
/*********************************************/
void playMove ()
{
int score = alphaBeta (colorToMove, colorToMove *-32000,
colorToMove * 32000, 1);
moveForward (1, move);
drawBoard();
printf ("my move: %c%c%c%c [%d] \a\n\n",
(96 +(from[1][move] % 10)),
(58 -(from[1][move] / 10)),
(96 +( to[1][move] % 10)),
(58 -( to[1][move] / 10)), score);
}
/* --------------------------------------------------------------- */
/*********************************************/
/* User Interface ;-) (ausbaufaehig) */
/* Zugeingabe: in Kleinbuchstaben "e2e4" */
/* Rochaden : "00" oder "000" */
/* Sonstiges : "q" quit; "p" play */
/*********************************************/
void getPlayerMove ()
{
char move[6] = "";
printf ("your move: "); scanf ("%s", move);
if (!strcmp (move, "q")) { exit(0); }
if (!strcmp (move, "p")) { colorToMove = -colorToMove; return; }
if (!strcmp (move, "00"))
if (colorToMove == white)
{ swapPieces (95, 97); swapPieces (96, 98); return; } else
{ swapPieces (25, 27); swapPieces (26, 28); return; }
if (!strcmp (move, "000"))
if (colorToMove == white)
{ swapPieces (95, 93); swapPieces (91, 94); return; } else
{ swapPieces (25, 23); swapPieces (21, 24); return; }
from[0][0] = (move[0] -96) +(58 -move[1]) *10;
to [0][0] = (move[2] -96) +(58 -move[3]) *10;
moveForward (0, 0);
}
/* --------------------------------------------------------------- */
/* --------------------------------------------------------------- */
/*********************************************/
/* Hauptprogramm: */
/* - Spielstufe :-) */
/* - Initialisieren */
/* - Schleife */
/* - Spielerzug */
/* - Computerzug */
/*********************************************/
int main ()
{
system ("clear");
printf ("\n Empfehlung in Klammern \n");
printf ("\n Rechentiefe [2]: "); scanf ("%d", &maxDepth);
printf ("\n Vertiefung [4]: "); scanf ("%d", &maxExt);
init(); drawBoard();
while (1)
{
getPlayerMove (); colorToMove = -colorToMove;
playMove (); colorToMove = -colorToMove;
}
return (0);
}
/* --------------------------------------------------------------- */
/* --------------------------------------------------------------- */