implemented simple pawn movement

Sat, 22 Mar 2014 16:04:02 +0100

author
Mike Becker <universe@uap-core.de>
date
Sat, 22 Mar 2014 16:04:02 +0100
changeset 8
52d742aee695
parent 7
41468077b5bb
child 9
4e4f156bba58

implemented simple pawn movement

src/game.c file | annotate | diff | comparison | revisions
src/game.h file | annotate | diff | comparison | revisions
--- a/src/game.c	Wed Mar 19 15:36:54 2014 +0100
+++ b/src/game.c	Sat Mar 22 16:04:02 2014 +0100
@@ -34,7 +34,7 @@
 
 static const uint8_t boardx = 10, boardy = 10;
 
-static void draw_board(Board board) {
+static void draw_board(Board board, uint8_t mycolor) {
     
     for (uint8_t y = 0 ; y < 8 ; y++) {
         for (uint8_t x = 0 ; x < 8 ; x++) {
@@ -53,22 +53,118 @@
             attrset((col == WHITE ? A_BOLD : A_DIM) |
                 COLOR_PAIR((y&1)==(x&1) ? COL_WB : COL_BW));
             
-            mvaddch(boardy-y, boardx+x*3, ' ');
-            mvaddch(boardy-y, boardx+x*3+1, piecec);
-            mvaddch(boardy-y, boardx+x*3+2, ' ');
+            int cy = mycolor == WHITE ? boardy-y : boardy-7+y;
+            int cx = mycolor == WHITE ? boardx+x*3 : boardx+21-x*3;
+            mvaddch(cy, cx, ' ');
+            mvaddch(cy, cx+1, piecec);
+            mvaddch(cy, cx+2, ' ');
         }
     }
     
     attrset(A_NORMAL);
     for (uint8_t i = 0 ; i < 8 ; i++) {
-        mvaddch(boardy+1, boardx+i*3+1, 'a'+i);
-        mvaddch(boardy-i, boardx-2, '1'+i);
+        int x = mycolor == WHITE ? boardx+i*3+1 : boardx+22-i*3;
+        int y = mycolor == WHITE ? boardy-i : boardy-7+i;
+        mvaddch(boardy+1, x, 'a'+i);
+        mvaddch(y, boardx-2, '1'+i);
     }
 }
 
-static int sendmove(int opponent) {
+static void apply_move(Board board, Move *move) {
+    board[move->fromrow][move->fromfile] = 0;
+    // TODO: care for en passant capture
+    board[move->torow][move->tofile] = move->piece;
+}
+
+static _Bool validate_move(Board board, uint8_t mycolor, Move *move) {
+    _Bool result = TRUE;
+    
+    /* does piece exist */
+    result &= board[move->fromrow][move->fromfile] == move->piece;
+    
+    /* is move rule conform */
+    // TODO: make it so
+    
+    /* is piece blocked */
+    // TODO: make it so
+    
+    /* is piece pinned */
+    // TODO: make it so
+    
+    return result;
+}
+
+static _Bool eval_move(Board board, uint8_t mycolor, char *movestr, Move *move) {
+    memset(move, 0, sizeof(Move));
+    
+    size_t len = strlen(movestr);
+    
+    /* remove check */
+    if (movestr[len-1] == '+') {
+        len--; movestr[len] = '\0';
+        move->check = TRUE;
+    }
+    
+    if (len == 2) {
+        /* pawn move (e.g. "e4") */
+        if (isfile(movestr[0]) && isrow(movestr[1])) {
+            move->piece = PAWN;
+            move->fromfile = move->tofile = fileidx(movestr[0]);
+            move->torow = rowidx(movestr[1]);
+            move->fromrow = rowidx(movestr[1]) + (mycolor == WHITE ? -1 : 1);
+            if (move->fromrow > 6) {
+                move->piece = 0;
+            } else {
+                /* advanced first move */
+                if (move->fromrow == (mycolor == WHITE ? 2 : 5) &&
+                    board[move->fromrow][move->fromfile] != (mycolor|PAWN)) {
+                    
+                    move->fromrow += (mycolor == WHITE ? -1 : 1);
+                    if (move->fromrow > 6) {
+                        move->piece = 0;
+                    }
+                }
+            }
+        }
+    } else if (len == 3) {
+        if (strcmp(movestr, "0-0") == 0) {
+            /* king side castling */
+            move->piece = KING;
+            move->fromfile = fileidx('e');
+            move->fromfile = fileidx('g');
+            move->fromrow = move->torow = mycolor == WHITE ? 0 : 7;
+        } else {
+            /* unambiguous move (e.g. "Nf3") */
+        }
+        
+    } else if (len == 4) {
+        /* ambiguous move (e.g. "Ndf3") */
+        
+        /* unambiguous capture (e.g. "Nxf3", "dxe5") */
+        
+    } else if (len == 5) {
+        /* queen side castling "O-O-O" */
+        
+        /* ambiguous capture (e.g. "Ndxf3") */
+        
+        /* long notation move (e.g. "Nc5a4") */
+        
+        /* long notation capture (e.g. "e5xf6") */
+    } else if (len == 6) {
+        /* long notation capture (e.g. "Nc5xf3") */
+    }
+    
+    if (move->piece) {
+        move->piece |= mycolor;
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+static int sendmove(Board board, uint8_t mycolor, int opponent) {
     const size_t buflen = 8;
-    char move[buflen];
+    char movestr[buflen];
     _Bool remisrejected = FALSE;
     
     while (1) {
@@ -86,13 +182,14 @@
         }
         clrtoeol();
         refresh();
-        getnstr(move, buflen);
+        getnstr(movestr, buflen);
 
-        if (strncmp(move, "surr", buflen) == 0) {
+        if (strncmp(movestr, "surr", buflen) == 0) {
             printw("You surrendered!");
+            refresh();
             net_send_code(opponent, NETCODE_SURRENDER);
             return 1;
-        } else if (strncmp(move, "remis", buflen) == 0) {
+        } else if (strncmp(movestr, "remis", buflen) == 0) {
             if (!remisrejected) {
                 net_send_code(opponent, NETCODE_REMIS);
                 printw("Remis offer sent - waiting for acceptance...");
@@ -100,19 +197,32 @@
                 if (net_recieve_code(opponent) == NETCODE_ACCEPT) {
                     printw("\rRemis accepted!");
                     clrtoeol();
+                    refresh();
                     return 1;
                 } else {
                     remisrejected = TRUE;
                 }
             }
         } else {
-            // TODO: validate move syntactically
-            // TODO: send move and await acceptance
+            Move move;
+            if (eval_move(board, mycolor, movestr, &move)) {
+                net_send_code(opponent, NETCODE_MOVE);
+                net_send_data(opponent, &move, sizeof(Move));
+                if (net_recieve_code(opponent) == NETCODE_ACCEPT) {
+                    apply_move(board, &move);
+                    return 0;
+                } else {
+                    printw("Invalid move.");
+                    clrtoeol();
+                }
+            } else {
+                printw("Can't interpret move - please use algebraic notation.");
+            }
         }
     }
 }
 
-static int recvmove(int opponent) {
+static int recvmove(Board board, uint8_t mycolor, int opponent) {
     
     while (1) {
         move(boardy+3, 0);
@@ -122,6 +232,8 @@
 
         // TODO: nonblocking
         uint32_t code = net_recieve_code(opponent);
+        
+        Move move;
         switch (code) {
             case NETCODE_SURRENDER:
                 printw("\rYour opponent surrendered!");
@@ -139,9 +251,14 @@
                 }
                 break;
             case NETCODE_MOVE:
-                // TODO: receive move
-                // TODO: validate move and accept/reject
-                return 0;
+                net_recieve_data(opponent, &move, sizeof(Move));
+                if (validate_move(board, mycolor, &move)) {
+                    apply_move(board, &move);
+                    net_send_code(opponent, NETCODE_ACCEPT);
+                    return 0;
+                } else {
+                    net_send_code(opponent, NETCODE_DECLINE);
+                }
         }
     }
 }
@@ -149,6 +266,8 @@
 void game_start(Settings *settings, int opponent) {
     _Bool myturn = is_server(settings) ==
         (settings->gameinfo.servercolor == WHITE);
+    uint8_t mycolor = myturn ? WHITE:BLACK;
+    
     _Bool running;
     
     Board board = {
@@ -164,11 +283,11 @@
     
     do {
         clear();
-        draw_board(board);
+        draw_board(board, mycolor);
         if (myturn) {
-            running = !sendmove(opponent);
+            running = !sendmove(board, mycolor, opponent);
         } else {
-            running = !recvmove(opponent);
+            running = !recvmove(board, mycolor, opponent);
             flushinp(); // flush any input the user hacked in while waiting
         }
         myturn ^= 1;
--- a/src/game.h	Wed Mar 19 15:36:54 2014 +0100
+++ b/src/game.h	Sat Mar 22 16:04:02 2014 +0100
@@ -65,6 +65,21 @@
 
 typedef uint8_t Board[8][8];
 
+typedef struct {
+    uint8_t piece;
+    uint8_t fromfile;
+    uint8_t fromrow;
+    uint8_t tofile;
+    uint8_t torow;
+    _Bool check;
+    _Bool capture;
+} Move;
+
+#define isfile(file) (file >= 'a' && file <= 'h')
+#define isrow(row) (row >= '1' && row <= '8')
+#define rowidx(row) (row-'1')
+#define fileidx(file) (file-'a')
+
 void game_start(Settings *settings, int opponent);
 
 #ifdef	__cplusplus

mercurial