/*********************************************/ /* 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 <stdio.h> #include <string.h> #include <stdlib.h> /* --------------------------------------------------------------- */ /*********************************************/ /* 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); } /* --------------------------------------------------------------- */ /* --------------------------------------------------------------- */