introduced game state structure

Mon, 31 Mar 2014 15:03:25 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 31 Mar 2014 15:03:25 +0200
changeset 23
824c9522ce66
parent 22
41bbfd4d17a3
child 24
4d030da07c88

introduced game state structure

src/chess/bishop.c file | annotate | diff | comparison | revisions
src/chess/bishop.h file | annotate | diff | comparison | revisions
src/chess/king.c file | annotate | diff | comparison | revisions
src/chess/king.h file | annotate | diff | comparison | revisions
src/chess/knight.c file | annotate | diff | comparison | revisions
src/chess/knight.h file | annotate | diff | comparison | revisions
src/chess/pawn.c file | annotate | diff | comparison | revisions
src/chess/pawn.h file | annotate | diff | comparison | revisions
src/chess/queen.c file | annotate | diff | comparison | revisions
src/chess/queen.h file | annotate | diff | comparison | revisions
src/chess/rook.c file | annotate | diff | comparison | revisions
src/chess/rook.h file | annotate | diff | comparison | revisions
src/chess/rules.c file | annotate | diff | comparison | revisions
src/chess/rules.h file | annotate | diff | comparison | revisions
src/game.c file | annotate | diff | comparison | revisions
src/game.h file | annotate | diff | comparison | revisions
src/main.c file | annotate | diff | comparison | revisions
src/terminal-chess.h file | annotate | diff | comparison | revisions
--- a/src/chess/bishop.c	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/bishop.c	Mon Mar 31 15:03:25 2014 +0200
@@ -35,7 +35,7 @@
     return abs(move->torow-move->fromrow) == abs(move->tofile-move->fromfile);
 }
 
-_Bool bishop_isblocked(Board board, Move *move) {
+_Bool bishop_isblocked(GameState *gamestate, Move *move) {
     int dy = move->torow > move->fromrow ? 1 : -1;
     int dx = move->tofile > move->fromfile ? 1 : -1;
     
@@ -45,7 +45,7 @@
     while (x != move->tofile-dx && y != move->torow-dy) {
         x += dx;
         y += dy;
-        if (board[y][x]) {
+        if (gamestate->board[y][x]) {
             return 1;
         }
     }
@@ -53,12 +53,12 @@
     return 0;
 }
 
-static int bishop_getloc_fixedfile(Board board, Move *move) {
+static int bishop_getloc_fixedfile(GameState *gamestate, Move *move) {
     uint8_t d = abs(move->fromfile - move->tofile);
-    if (board[move->torow - d][move->fromfile] == move->piece) {
+    if (gamestate->board[move->torow - d][move->fromfile] == move->piece) {
         move->fromrow = move->torow - d;
     }
-    if (board[move->torow + d][move->fromfile] == move->piece) {
+    if (gamestate->board[move->torow + d][move->fromfile] == move->piece) {
         if (move->fromrow == POS_UNSPECIFIED) {
             move->fromrow = move->torow + d;
         } else {
@@ -69,12 +69,12 @@
         INVALID_POSITION : VALID_MOVE_SYNTAX;
 }
 
-static int bishop_getloc_fixedrow(Board board, Move *move) {
+static int bishop_getloc_fixedrow(GameState *gamestate, Move *move) {
     uint8_t d = abs(move->fromrow - move->torow);
-    if (board[move->fromrow][move->tofile - d] == move->piece) {
+    if (gamestate->board[move->fromrow][move->tofile - d] == move->piece) {
         move->fromfile = move->tofile - d;
     }
-    if (board[move->fromrow][move->tofile + d] == move->piece) {
+    if (gamestate->board[move->fromrow][move->tofile + d] == move->piece) {
         if (move->fromfile == POS_UNSPECIFIED) {
             move->fromfile = move->tofile + d;
         } else {
@@ -85,14 +85,14 @@
         INVALID_POSITION : VALID_MOVE_SYNTAX;
 }
 
-int bishop_getlocation(Board board, Move *move) {
+int bishop_getlocation(GameState *gamestate, Move *move) {
     
     if (move->fromfile != POS_UNSPECIFIED) {
-        return bishop_getloc_fixedfile(board, move);
+        return bishop_getloc_fixedfile(gamestate, move);
     }
     
     if (move->fromrow != POS_UNSPECIFIED) {
-        return bishop_getloc_fixedrow(board, move);
+        return bishop_getloc_fixedrow(gamestate, move);
     }
     
     _Bool amb = 0;
@@ -100,7 +100,7 @@
         uint8_t row = move->torow + d;
         if (isidx(row)) {
             uint8_t file = move->tofile + d;
-            if (isidx(file) && board[row][file] == move->piece) {
+            if (isidx(file) && gamestate->board[row][file] == move->piece) {
                 if (amb) {
                     return AMBIGUOUS_MOVE;
                 }
@@ -109,7 +109,7 @@
                 move->fromfile = file;
             }
             file = move->tofile - d;
-            if (isidx(file) && board[row][file] == move->piece) {
+            if (isidx(file) && gamestate->board[row][file] == move->piece) {
                 if (amb) {
                     return AMBIGUOUS_MOVE;
                 }
--- a/src/chess/bishop.h	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/bishop.h	Mon Mar 31 15:03:25 2014 +0200
@@ -37,8 +37,8 @@
 #endif
 
 _Bool bishop_chkrules(Move *move);
-_Bool bishop_isblocked(Board board, Move *move);
-int bishop_getlocation(Board board, Move *move);
+_Bool bishop_isblocked(GameState *gamestate, Move *move);
+int bishop_getlocation(GameState *gamestate, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/chess/king.c	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/king.c	Mon Mar 31 15:03:25 2014 +0200
@@ -30,17 +30,17 @@
 #include "rules.h"
 #include "king.h"
 
-_Bool king_chkrules(Board board, Move* move) {
+_Bool king_chkrules(GameState *gamestate, Move* move) {
     // TODO: implement
     return 0;
 }
 
-_Bool king_isblocked(Board board, Move *move) {
+_Bool king_isblocked(GameState *gamestate, Move *move) {
     // TODO: implement
     return 1;
 }
 
-int king_getlocation(Board board, Move *move) {
+int king_getlocation(GameState *gamestate, Move *move) {
     // TODO: implement
     return INVALID_MOVE_SYNTAX;
 }
--- a/src/chess/king.h	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/king.h	Mon Mar 31 15:03:25 2014 +0200
@@ -37,9 +37,9 @@
 extern "C" {
 #endif
 
-_Bool king_chkrules(Board board, Move *move);
-_Bool king_isblocked(Board board, Move *move);
-int king_getlocation(Board board, Move *move);
+_Bool king_chkrules(GameState *gamestate, Move *move);
+_Bool king_isblocked(GameState *gamestate, Move *move);
+int king_getlocation(GameState *gamestate, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/chess/knight.c	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/knight.c	Mon Mar 31 15:03:25 2014 +0200
@@ -38,12 +38,12 @@
     return (dx == 2 && dy == 1) || (dx == 1 && dy == 2);
 }
 
-static int knight_getloc_fixedrow(Board board, Move *move) {
+static int knight_getloc_fixedrow(GameState *gamestate, Move *move) {
     int d = 3 - abs(move->fromrow - move->torow);
     
     if (d == 1 || d == 2) {
         if (move->tofile < 6 &&
-            board[move->fromrow][move->tofile + d] == move->piece) {
+            gamestate->board[move->fromrow][move->tofile + d] == move->piece) {
             if (move->fromfile == POS_UNSPECIFIED) {
                 move->fromfile = move->tofile + d;
                 return VALID_MOVE_SYNTAX;
@@ -52,7 +52,7 @@
             }
         }
         if (move->tofile > 1 &&
-            board[move->fromrow][move->tofile - d] == move->piece) {
+            gamestate->board[move->fromrow][move->tofile - d] == move->piece) {
             if (move->fromfile == POS_UNSPECIFIED) {
                 move->fromfile = move->tofile - d;
                 return VALID_MOVE_SYNTAX;
@@ -65,12 +65,12 @@
     return INVALID_POSITION;
 }
 
-static int knight_getloc_fixedfile(Board board, Move *move) {
+static int knight_getloc_fixedfile(GameState *gamestate, Move *move) {
     int d = 3 - abs(move->fromfile - move->tofile);
     
     if (d == 1 || d == 2) {
         if (move->torow < 6 &&
-            board[move->torow + d][move->fromfile] == move->piece) {
+            gamestate->board[move->torow + d][move->fromfile] == move->piece) {
             if (move->fromrow == POS_UNSPECIFIED) {
                 move->fromrow = move->torow + d;
                 return VALID_MOVE_SYNTAX;
@@ -79,7 +79,7 @@
             }
         }
         if (move->torow > 1 &&
-            board[move->torow - d][move->fromfile] == move->piece) {
+            gamestate->board[move->torow - d][move->fromfile] == move->piece) {
             if (move->fromrow == POS_UNSPECIFIED) {
                 move->fromrow = move->torow - d;
                 return VALID_MOVE_SYNTAX;
@@ -92,14 +92,14 @@
     return INVALID_POSITION;
 }
 
-int knight_getlocation(Board board, Move *move) {
+int knight_getlocation(GameState *gamestate, Move *move) {
     
     if (move->fromfile != POS_UNSPECIFIED) {
-        return knight_getloc_fixedfile(board, move);
+        return knight_getloc_fixedfile(gamestate, move);
     }
     
     if (move->fromrow != POS_UNSPECIFIED) {
-        return knight_getloc_fixedrow(board, move);
+        return knight_getloc_fixedrow(gamestate, move);
     }
     
     for (int x = -2 ; x <= 2 ; x++) {
@@ -113,7 +113,8 @@
             uint8_t cx = move->tofile + x;
             uint8_t cy = move->torow + y;
 
-            if (isidx(cx) && isidx(cy) && board[cy][cx] == move->piece) {
+            if (isidx(cx) && isidx(cy)
+                && gamestate->board[cy][cx] == move->piece) {
                 if (move->fromfile == POS_UNSPECIFIED
                     && move->fromrow == POS_UNSPECIFIED) {
                     move->fromfile = cx;
--- a/src/chess/knight.h	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/knight.h	Mon Mar 31 15:03:25 2014 +0200
@@ -37,8 +37,8 @@
 #endif
 
 _Bool knight_chkrules(Move *move);
-#define knight_isblocked(b,m) 0
-int knight_getlocation(Board board, Move *move);
+#define knight_isblocked(gs,m) 0
+int knight_getlocation(GameState *gamestate, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/chess/pawn.c	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/pawn.c	Mon Mar 31 15:03:25 2014 +0200
@@ -30,7 +30,7 @@
 #include "pawn.h"
 #include "rules.h"
 
-_Bool pawn_chkrules(Board board, Move *move) {
+_Bool pawn_chkrules(GameState *gamestate, Move *move) {
     int8_t d = ((move->piece & COLOR_MASK) == WHITE ? -1 : 1);
     
     if (move->torow == (d < 0 ? 7 : 0)) {
@@ -53,8 +53,9 @@
             move->fromfile == move->tofile + 1 ||
             move->fromfile == move->tofile - 1)) {
 
-            return mdst(board,move)
-                || (board[move->fromrow][move->tofile] & ENPASSANT_THREAT);
+            return mdst(gamestate->board, move) ||
+                (gamestate->board[move->fromrow][move->tofile]
+                & ENPASSANT_THREAT);
         } else {
             return 0;
         }
@@ -69,11 +70,11 @@
     }
 }
 
-_Bool pawn_isblocked(Board board, Move *move) {
-    return mdst(board,move) && !move->capture;
+_Bool pawn_isblocked(GameState *gamestate, Move *move) {
+    return mdst(gamestate->board, move) && !move->capture;
 }
 
-int pawn_getlocation(Board board, Move *move) {
+int pawn_getlocation(GameState *gamestate, Move *move) {
     int8_t d = ((move->piece & COLOR_MASK) == WHITE ? -1 : 1);
     
     if (move->fromfile == POS_UNSPECIFIED) {
@@ -85,7 +86,7 @@
     } else {
         /* advanced first move */
         if (move->fromrow == (d < 0 ? 2 : 5) &&
-            msrc(board,move) != move->piece) {
+            msrc(gamestate->board,move) != move->piece) {
 
             move->fromrow += d;
             if (move->fromrow > 6) {
--- a/src/chess/pawn.h	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/pawn.h	Mon Mar 31 15:03:25 2014 +0200
@@ -36,9 +36,9 @@
 extern "C" {
 #endif
 
-_Bool pawn_chkrules(Board board, Move *move);
-_Bool pawn_isblocked(Board board, Move *move);
-int pawn_getlocation(Board board, Move *move);
+_Bool pawn_chkrules(GameState *gamestate, Move *move);
+_Bool pawn_isblocked(GameState *gamestate, Move *move);
+int pawn_getlocation(GameState *gamestate, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/chess/queen.c	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/queen.c	Mon Mar 31 15:03:25 2014 +0200
@@ -35,12 +35,12 @@
     return 0;
 }
 
-_Bool queen_isblocked(Board board, Move *move) {
+_Bool queen_isblocked(GameState *gamestate, Move *move) {
     // TODO: implement
     return 1;
 }
 
-int queen_getlocation(Board board, Move *move) {
+int queen_getlocation(GameState *gamestate, Move *move) {
     // TODO: implement
     return INVALID_MOVE_SYNTAX;
 }
--- a/src/chess/queen.h	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/queen.h	Mon Mar 31 15:03:25 2014 +0200
@@ -37,8 +37,8 @@
 #endif
 
 _Bool queen_chkrules(Move *move);
-_Bool queen_isblocked(Board board, Move *move);
-int queen_getlocation(Board board, Move *move);
+_Bool queen_isblocked(GameState *gamestate, Move *move);
+int queen_getlocation(GameState *gamestate, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/chess/rook.c	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/rook.c	Mon Mar 31 15:03:25 2014 +0200
@@ -34,14 +34,14 @@
     return move->torow == move->fromrow || move->tofile == move->fromfile;
 }
 
-_Bool rook_isblocked(Board board, Move *move) {
+_Bool rook_isblocked(GameState *gamestate, Move *move) {
     
     if (move->torow == move->fromrow) {
         int d = move->tofile > move->fromfile ? 1 : -1;
         uint8_t f = move->fromfile;
         while (f != move->tofile-d) {
             f += d;
-            if (board[move->fromrow][f]) {
+            if (gamestate->board[move->fromrow][f]) {
                 return 1;
             }
         }
@@ -50,7 +50,7 @@
         uint8_t r = move->fromrow;
         while (r != move->torow - d) {
             r += d;
-            if (board[r][move->fromfile]) {
+            if (gamestate->board[r][move->fromfile]) {
                 return 1;
             }
         }
@@ -59,10 +59,10 @@
     return 0;
 }
 
-static int rook_getloc_fixedrow(Board board, Move *move) {
+static int rook_getloc_fixedrow(GameState *gamestate, Move *move) {
     uint8_t file = POS_UNSPECIFIED;
     for (uint8_t f = 0 ; f < 8 ; f++) {
-        if (board[move->fromrow][f] == move->piece) {
+        if (gamestate->board[move->fromrow][f] == move->piece) {
             if (file == POS_UNSPECIFIED) {
                 file = f;
             } else {
@@ -78,10 +78,10 @@
     }
 }
 
-static int rook_getloc_fixedfile(Board board, Move *move) {
+static int rook_getloc_fixedfile(GameState *gamestate, Move *move) {
     uint8_t row = POS_UNSPECIFIED;
     for (uint8_t r = 0 ; r < 8 ; r++) {
-        if (board[r][move->fromfile] == move->piece) {
+        if (gamestate->board[r][move->fromfile] == move->piece) {
             if (row == POS_UNSPECIFIED) {
                 row = r;
             } else {
@@ -97,13 +97,13 @@
     }
 }
 
-int rook_getlocation(Board board, Move *move) {
+int rook_getlocation(GameState *gamestate, Move *move) {
     
     if (move->fromfile != POS_UNSPECIFIED) {
         if (move->fromfile == move->tofile) {
-            return rook_getloc_fixedfile(board, move);
+            return rook_getloc_fixedfile(gamestate, move);
         } else {
-            if (board[move->torow][move->fromfile] == move->piece) {
+            if (gamestate->board[move->torow][move->fromfile] == move->piece) {
                 move->fromrow = move->torow;
                 return VALID_MOVE_SYNTAX;
             } else {
@@ -114,9 +114,9 @@
     
     if (move->fromrow != POS_UNSPECIFIED) {
         if (move->fromrow == move->torow) {
-            return rook_getloc_fixedrow(board, move);
+            return rook_getloc_fixedrow(gamestate, move);
         } else {
-            if (board[move->fromrow][move->tofile] == move->piece) {
+            if (gamestate->board[move->fromrow][move->tofile] == move->piece) {
                 move->fromfile = move->tofile;
                 return VALID_MOVE_SYNTAX;
             } else {
@@ -128,10 +128,10 @@
     Move chkrowmove = *move, chkfilemove = *move;
     
     chkrowmove.fromrow = move->torow;
-    int chkrow = rook_getloc_fixedrow(board, &chkrowmove);
+    int chkrow = rook_getloc_fixedrow(gamestate, &chkrowmove);
     
     chkfilemove.fromfile = move->tofile;
-    int chkfile = rook_getloc_fixedfile(board, &chkfilemove);
+    int chkfile = rook_getloc_fixedfile(gamestate, &chkfilemove);
     
     if ((chkrow == VALID_MOVE_SYNTAX && chkfile == VALID_MOVE_SYNTAX) ||
         chkrow == AMBIGUOUS_MOVE || chkfile == AMBIGUOUS_MOVE) {
--- a/src/chess/rook.h	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/rook.h	Mon Mar 31 15:03:25 2014 +0200
@@ -37,8 +37,8 @@
 #endif
 
 _Bool rook_chkrules(Move *move);
-_Bool rook_isblocked(Board board, Move *move);
-int rook_getlocation(Board board, Move *move);
+_Bool rook_isblocked(GameState *gamestate, Move *move);
+int rook_getlocation(GameState *gamestate, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/chess/rules.c	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/rules.c	Mon Mar 31 15:03:25 2014 +0200
@@ -30,6 +30,30 @@
 #include "rules.h"
 #include "chess.h"
 #include <string.h>
+#include <stdlib.h>
+
+void gamestate_cleanup(GameState *gamestate) {
+    MoveList *elem;
+    elem = gamestate->movelist;
+    while (elem) {
+        MoveList *cur = elem;
+        elem = elem->next;
+        free(cur);
+    };
+}
+
+static void addmove(GameState* gamestate, Move *move) {
+    MoveList *elem = malloc(sizeof(MoveList));
+    elem->next = NULL;
+    elem->move = *move;
+    
+    if (gamestate->lastmove) {
+        gamestate->lastmove->next = elem;
+        gamestate->lastmove = elem;
+    } else {
+        gamestate->movelist = gamestate->lastmove = elem;
+    }
+}
 
 char getpiecechr(uint8_t piece) {
     switch (piece & PIECE_MASK) {
@@ -53,41 +77,34 @@
     }
 }
 
-/**
- * Guesses the location of a piece for short algebraic notation.
- * 
- * @param board the current state of the board
- * @param move the move date to operate on
- * @return status code (see rules/rules.h for the codes)
- */
-static int getlocation(Board board, Move *move) {   
+static int getlocation(GameState *gamestate, Move *move) {   
     uint8_t piece = move->piece & PIECE_MASK;
     switch (piece) {
-        case PAWN: return pawn_getlocation(board, move);
-        case ROOK: return rook_getlocation(board, move);
-        case KNIGHT: return knight_getlocation(board, move);
-        case BISHOP: return bishop_getlocation(board, move);
-        case QUEEN: return queen_getlocation(board, move);
-        case KING: return king_getlocation(board, move);
+        case PAWN: return pawn_getlocation(gamestate, move);
+        case ROOK: return rook_getlocation(gamestate, move);
+        case KNIGHT: return knight_getlocation(gamestate, move);
+        case BISHOP: return bishop_getlocation(gamestate, move);
+        case QUEEN: return queen_getlocation(gamestate, move);
+        case KING: return king_getlocation(gamestate, move);
         default: return INVALID_MOVE_SYNTAX;
     }
 }
 
 
-void apply_move(Board board, Move *move) {
+void apply_move(GameState *gamestate, Move *move) {
     uint8_t piece = move->piece & PIECE_MASK;
     uint8_t color = move->piece & COLOR_MASK;
     
     /* en passant capture */
     if (move->capture && piece == PAWN &&
-        mdst(board, move) == 0) {
-        board[move->fromrow][move->tofile] = 0;
+        mdst(gamestate->board, move) == 0) {
+        gamestate->board[move->fromrow][move->tofile] = 0;
     }
     
     /* remove old en passant threats */
     for (uint8_t file = 0 ; file < 8 ; file++) {
-        board[3][file] &= ~ENPASSANT_THREAT;
-        board[4][file] &= ~ENPASSANT_THREAT;
+        gamestate->board[3][file] &= ~ENPASSANT_THREAT;
+        gamestate->board[4][file] &= ~ENPASSANT_THREAT;
     }
     
     /* add new en passant threat */
@@ -98,11 +115,11 @@
     }
     
     /* move (and maybe capture or promote) */
-    msrc(board, move) = 0;
+    msrc(gamestate->board, move) = 0;
     if (move->promotion) {
-        mdst(board, move) = move->promotion;
+        mdst(gamestate->board, move) = move->promotion;
     } else {
-        mdst(board, move) = move->piece;
+        mdst(gamestate->board, move) = move->piece;
     }
     
     /* castling */
@@ -110,16 +127,18 @@
         move->fromfile == fileidx('e')) {
         
         if (move->tofile == fileidx('g')) {
-            board[move->torow][fileidx('h')] = 0;
-            board[move->torow][fileidx('f')] = color|ROOK;
+            gamestate->board[move->torow][fileidx('h')] = 0;
+            gamestate->board[move->torow][fileidx('f')] = color|ROOK;
         } else if (move->tofile == fileidx('c')) {
-            board[move->torow][fileidx('a')] = 0;
-            board[move->torow][fileidx('d')] = color|ROOK;
+            gamestate->board[move->torow][fileidx('a')] = 0;
+            gamestate->board[move->torow][fileidx('d')] = color|ROOK;
         }
     }
+    
+    addmove(gamestate, move);
 }
 
-_Bool validate_move(Board board, Move *move) {
+_Bool validate_move(GameState *gamestate, Move *move) {
     _Bool result;
     
     /* validate indices (don't trust opponent) */
@@ -133,38 +152,39 @@
     }
     
     /* does piece exist */
-    result = msrc(board, move) == move->piece;
+    result = msrc(gamestate->board, move) == move->piece;
     
     /* can't capture own pieces */
-    if ((mdst(board, move) & COLOR_MASK) == (move->piece & COLOR_MASK)) {
+    if ((mdst(gamestate->board, move) & COLOR_MASK)
+        == (move->piece & COLOR_MASK)) {
         return 0;
     }
     
     /* validate individual rules */
     switch (move->piece & PIECE_MASK) {
     case PAWN:
-        result = result && pawn_chkrules(board, move);
-        result = result && !pawn_isblocked(board, move);
+        result = result && pawn_chkrules(gamestate, move);
+        result = result && !pawn_isblocked(gamestate, move);
         break;
     case ROOK:
         result = result && rook_chkrules(move);
-        result = result && !rook_isblocked(board, move);
+        result = result && !rook_isblocked(gamestate, move);
         break;
     case KNIGHT:
         result = result && knight_chkrules(move);
-        result = result && !knight_isblocked(board, move);
+        result = result && !knight_isblocked(gamestate, move);
         break;
     case BISHOP:
         result = result && bishop_chkrules(move);
-        result = result && !bishop_isblocked(board, move);
+        result = result && !bishop_isblocked(gamestate, move);
         break;
     case QUEEN:
         result = result && queen_chkrules(move);
-        result = result && !queen_isblocked(board, move);
+        result = result && !queen_isblocked(gamestate, move);
         break;
     case KING:
-        result = result && king_chkrules(board, move);
-        result = result && !king_isblocked(board, move);
+        result = result && king_chkrules(gamestate, move);
+        result = result && !king_isblocked(gamestate, move);
         break;
     default:
         result = 0;
@@ -179,7 +199,7 @@
     return result;
 }
 
-int eval_move(Board board, uint8_t mycolor, char *mstr, Move *move) {
+int eval_move(GameState *gamestate, char *mstr, Move *move) {
     memset(move, 0, sizeof(Move));
     move->fromfile = POS_UNSPECIFIED;
     move->fromrow = POS_UNSPECIFIED;
@@ -201,7 +221,7 @@
         if (!move->promotion) {
             return INVALID_MOVE_SYNTAX;
         } else {
-            move->promotion |= mycolor;
+            move->promotion |= gamestate->mycolor;
             len -= 2;
             mstr[len] = 0;
         }
@@ -218,7 +238,7 @@
             move->piece = KING;
             move->fromfile = fileidx('e');
             move->tofile = fileidx('g');
-            move->fromrow = move->torow = mycolor == WHITE ? 0 : 7;
+            move->fromrow = move->torow = gamestate->mycolor == WHITE ? 0 : 7;
         } else {
             /* move (e.g. "Nf3") */
             move->piece = getpiece(mstr[0]);
@@ -254,7 +274,7 @@
             move->piece = KING;
             move->fromfile = fileidx('e');
             move->tofile = fileidx('c');
-            move->fromrow = move->torow = mycolor == WHITE ? 0 : 7;
+            move->fromrow = move->torow = gamestate->mycolor == WHITE ? 0 : 7;
         } else {
             move->piece = getpiece(mstr[0]);
             if (mstr[2] == 'x') {
@@ -290,15 +310,16 @@
 
     
     if (move->piece) {
-        if (move->piece == PAWN && move->torow == (mycolor==WHITE?7:0)
+        if (move->piece == PAWN
+            && move->torow == (gamestate->mycolor==WHITE?7:0)
             && !move->promotion) {
             return NEED_PROMOTION;
         }
         
-        move->piece |= mycolor;
+        move->piece |= gamestate->mycolor;
         if (move->fromfile == POS_UNSPECIFIED
             || move->fromrow == POS_UNSPECIFIED) {
-            return getlocation(board, move);
+            return getlocation(gamestate, move);
         } else {
             return chkidx(move) ? VALID_MOVE_SYNTAX : INVALID_POSITION;
         }
--- a/src/chess/rules.h	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/chess/rules.h	Mon Mar 31 15:03:25 2014 +0200
@@ -68,6 +68,7 @@
 
 typedef uint8_t Board[8][8];
 
+
 typedef struct {
     uint8_t piece;
     uint8_t fromfile;
@@ -80,6 +81,20 @@
     _Bool capture;
 } Move;
 
+typedef struct MoveList MoveList;
+
+struct MoveList {
+    Move move;
+    MoveList* next;
+};
+
+typedef struct {
+    Board board;
+    uint8_t mycolor;
+    MoveList* movelist;
+    MoveList* lastmove;
+} GameState;
+
 #define POS_UNSPECIFIED UINT8_MAX
 #define mdst(b,m) b[(m)->torow][(m)->tofile]
 #define msrc(b,m) b[(m)->fromrow][(m)->fromfile]
@@ -102,6 +117,8 @@
 #define fileidx_s(c) (isfile(c)?fileidx(c):POS_UNSPECIFIED)
 #define rowidx_s(c) (isrow(c)?rowidx(c):POS_UNSPECIFIED)
 
+void gamestate_cleanup(GameState *gamestate);
+
 /**
  * Maps a character to a piece.
  * 
@@ -126,29 +143,28 @@
  * Evaluates a move syntactically and stores the move data in the specified
  * object.
  * 
- * @param board the current state of the board
- * @param mycolor the color of the current player
+ * @param gamestate the current game state
  * @param mstr the input string to parse
  * @param move a pointer to object where the move data shall be stored
  * @return status code (see rules/rules.h for the list of codes)
  */
-int eval_move(Board board, uint8_t mycolor, char *mstr, Move *move);
+int eval_move(GameState *gamestate, char *mstr, Move *move);
 
 /**
  * Validates move by applying chess rules.
- * @param board the current board state
+ * @param gamestate the current game state
  * @param move the move to validate
  * @return TRUE, if the move complies to chess rules, FALSE otherwise
  */
-_Bool validate_move(Board board, Move *move);
+_Bool validate_move(GameState *gamestate, Move *move);
 
 /**
  * Applies a move and deletes captured pieces.
  * 
- * @param board the current board state
+ * @param gamestate the current game state
  * @param move the move to apply
  */
-void apply_move(Board board, Move *move);
+void apply_move(GameState *gamestate, Move *move);
 
 #endif	/* RULES_H */
 
--- a/src/game.c	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/game.c	Mon Mar 31 15:03:25 2014 +0200
@@ -35,12 +35,12 @@
 
 static const uint8_t boardx = 10, boardy = 10;
 
-static void draw_board(Board board, MoveListRoot *movelist, uint8_t mycolor) {
+static void draw_board(GameState *gamestate) {
     
     for (uint8_t y = 0 ; y < 8 ; y++) {
         for (uint8_t x = 0 ; x < 8 ; x++) {
-            uint8_t col = board[y][x] & COLOR_MASK;
-            uint8_t piece = board[y][x] & PIECE_MASK;
+            uint8_t col = gamestate->board[y][x] & COLOR_MASK;
+            uint8_t piece = gamestate->board[y][x] & PIECE_MASK;
             char piecec;
             if (piece) {
                 piecec = piece == PAWN ? 'P' : getpiecechr(piece);
@@ -51,8 +51,8 @@
             attrset((col == WHITE ? A_BOLD : A_DIM) |
                 COLOR_PAIR((y&1)==(x&1) ? COL_WB : COL_BW));
             
-            int cy = mycolor == WHITE ? boardy-y : boardy-7+y;
-            int cx = mycolor == WHITE ? boardx+x*3 : boardx+21-x*3;
+            int cy = gamestate->mycolor == WHITE ? boardy-y : boardy-7+y;
+            int cx = gamestate->mycolor == WHITE ? boardx+x*3 : boardx+21-x*3;
             mvaddch(cy, cx, ' ');
             mvaddch(cy, cx+1, piecec);
             mvaddch(cy, cx+2, ' ');
@@ -61,8 +61,8 @@
     
     attrset(A_NORMAL);
     for (uint8_t i = 0 ; i < 8 ; i++) {
-        int x = mycolor == WHITE ? boardx+i*3+1 : boardx+22-i*3;
-        int y = mycolor == WHITE ? boardy-i : boardy-7+i;
+        int x = gamestate->mycolor == WHITE ? boardx+i*3+1 : boardx+22-i*3;
+        int y = gamestate->mycolor == WHITE ? boardy-i : boardy-7+i;
         mvaddch(boardy+1, x, 'a'+i);
         mvaddch(y, boardx-2, '1'+i);
     }
@@ -72,14 +72,14 @@
     uint8_t logy = 0;
     const uint8_t logx = boardx + 30;
     int logi = 1;
-    MoveList *logelem = movelist->first;
+    MoveList *logelem = gamestate->movelist;
     
     while (logelem) {
         logi++;
         if (logi % 2 == 0) {
             if ((logi - 2) % 4 == 0) {
                 logy++;
-                wmove(tchess_window, logy, logx);
+                move(logy, logx);
             }
             printw("%d. ", logi / 2);
         }
@@ -108,15 +108,14 @@
 }
 
 
-static int sendmove(Board board, MoveListRoot *movelist,
-    uint8_t mycolor, int opponent) {
+static int sendmove(GameState *gamestate, int opponent) {
     
     const size_t buflen = 8;
     char movestr[buflen];
     _Bool remisrejected = FALSE;
     uint8_t code;
     
-    int inputy = getmaxy(tchess_window) - 6;
+    int inputy = getmaxy(stdscr) - 6;
     while (1) {
         move(inputy, 0);
         if (remisrejected) {
@@ -156,7 +155,7 @@
             }
         } else {
             Move move;
-            int eval_result = eval_move(board, mycolor, movestr, &move);
+            int eval_result = eval_move(gamestate, movestr, &move);
             switch (eval_result) {
             case VALID_MOVE_SYNTAX:
                 net_send_data(opponent, NETCODE_MOVE, &move, sizeof(Move));
@@ -166,8 +165,7 @@
                 if (code == NETCODE_DECLINE) {
                     printw("Invalid move.");
                 } else {
-                    apply_move(board, &move);
-                    addmove(movelist, &move);
+                    apply_move(gamestate, &move);
                     if (move.checkmate) {
                         printw("Checkmate!");
                         clrtoeol();
@@ -194,9 +192,9 @@
     }
 }
 
-static int recvmove(Board board, MoveListRoot *movelist, int opponent) {
+static int recvmove(GameState *gamestate, int opponent) {
     
-    int inputy = getmaxy(tchess_window) - 6;
+    int inputy = getmaxy(stdscr) - 6;
     while (1) {
         move(inputy, 0);
         printw("Awaiting opponent move...");
@@ -225,9 +223,8 @@
                 break;
             case NETCODE_MOVE:
                 net_recieve_data(opponent, &move, sizeof(Move));
-                if (validate_move(board, &move)) {
-                    apply_move(board, &move);
-                    addmove(movelist, &move);
+                if (validate_move(gamestate, &move)) {
+                    apply_move(gamestate, &move);
                     if (move.check) {
                         net_send_code(opponent, NETCODE_CHECK);
                     } else if (move.checkmate) {
@@ -243,40 +240,12 @@
     }
 }
 
-void freemovelist(MoveListRoot* list) {
-    MoveList *elem;
-    elem = list->first;
-    while (elem) {
-        MoveList *cur = elem;
-        elem = elem->next;
-        free(cur);
-    };
-    free(list);
-}
-
-void addmove(MoveListRoot* list, Move *move) {
-    MoveList *elem = malloc(sizeof(MoveList));
-    elem->next = NULL;
-    elem->move = *move;
-    
-    if (list->last) {
-        list->last->next = elem;
-        list->last = elem;
-    } else {
-        list->first = list->last = elem;
-    }
-}
-
 void game_start(Settings *settings, int opponent) {
     _Bool myturn = is_server(settings) ==
         (settings->gameinfo.servercolor == WHITE);
-    uint8_t mycolor = myturn ? WHITE:BLACK;
     
-    _Bool running;
-    
-    MoveListRoot* movelist = calloc(1, sizeof(MoveListRoot));
-    
-    Board board = {
+    GameState gamestate;
+    Board initboard = {
         {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK},
         {WPAWN, WPAWN,   WPAWN,   WPAWN,  WPAWN, WPAWN,   WPAWN,   WPAWN},
         {0,     0,       0,       0,      0,     0,       0,       0},
@@ -286,22 +255,26 @@
         {BPAWN, BPAWN,   BPAWN,   BPAWN,  BPAWN, BPAWN,   BPAWN,   BPAWN},
         {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK}
     };
+    memcpy(gamestate.board, initboard, sizeof(Board));
+    gamestate.mycolor = myturn ? WHITE:BLACK;
+    gamestate.movelist = gamestate.lastmove = NULL;
     
+    _Bool running;
     do {
         clear();
-        draw_board(board, movelist, mycolor);
+        draw_board(&gamestate);
         if (myturn) {
-            running = !sendmove(board, movelist, mycolor, opponent);
+            running = !sendmove(&gamestate, opponent);
         } else {
-            running = !recvmove(board, movelist, opponent);
+            running = !recvmove(&gamestate, opponent);
             flushinp(); // flush any input the user hacked in while waiting
         }
         myturn ^= TRUE;
     }  while (running);
     
-    freemovelist(movelist);
+    gamestate_cleanup(&gamestate);
     
-    mvaddstr(getmaxy(tchess_window)-1, 0,
+    mvaddstr(getmaxy(stdscr)-1, 0,
         "Game has ended. Press any key to leave...");
     getch();
 }
--- a/src/game.h	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/game.h	Mon Mar 31 15:03:25 2014 +0200
@@ -37,25 +37,8 @@
 extern "C" {
 #endif
 
-typedef struct MoveList MoveList;
-typedef struct MoveListRoot MoveListRoot;
-
-struct MoveListRoot {
-    MoveList* first;
-    MoveList* last;
-};
-
-struct MoveList {
-    Move move;
-    MoveList* next;
-};
-
-
 void game_start(Settings *settings, int opponent);
 
-void freemovelist(MoveListRoot* list);
-void addmove(MoveListRoot *movelist, Move *move);
-
 #ifdef	__cplusplus
 }
 #endif
--- a/src/main.c	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/main.c	Mon Mar 31 15:03:25 2014 +0200
@@ -160,7 +160,7 @@
         );
         return EXIT_SUCCESS;
     }    
-    tchess_window = initscr();
+    initscr();
     cbreak();
     if (has_colors()) {
         start_color();
--- a/src/terminal-chess.h	Mon Mar 31 14:08:00 2014 +0200
+++ b/src/terminal-chess.h	Mon Mar 31 15:03:25 2014 +0200
@@ -39,8 +39,6 @@
 extern "C" {
 #endif
 
-WINDOW* tchess_window;
-
 #define TIME_MAX UINT16_MAX
     
 typedef struct {

mercurial