introduced status codes for get_location to produce detailed error messages + added knight rules

Fri, 28 Mar 2014 14:32:52 +0100

author
Mike Becker <universe@uap-core.de>
date
Fri, 28 Mar 2014 14:32:52 +0100
changeset 16
a298c6637c30
parent 15
7ffd66591afe
child 17
2aed5418e142

introduced status codes for get_location to produce detailed error messages + added knight rules

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/rules/bishop.c file | annotate | diff | comparison | revisions
src/rules/bishop.h file | annotate | diff | comparison | revisions
src/rules/king.c file | annotate | diff | comparison | revisions
src/rules/king.h file | annotate | diff | comparison | revisions
src/rules/knight.c file | annotate | diff | comparison | revisions
src/rules/knight.h file | annotate | diff | comparison | revisions
src/rules/pawn.c file | annotate | diff | comparison | revisions
src/rules/pawn.h file | annotate | diff | comparison | revisions
src/rules/queen.c file | annotate | diff | comparison | revisions
src/rules/queen.h file | annotate | diff | comparison | revisions
src/rules/rook.c file | annotate | diff | comparison | revisions
src/rules/rook.h file | annotate | diff | comparison | revisions
src/rules/rules.h file | annotate | diff | comparison | revisions
--- a/src/game.c	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/game.c	Fri Mar 28 14:32:52 2014 +0100
@@ -147,19 +147,19 @@
         result = result && !pawn_isblocked(board, move);
         break;
     case ROOK:
-        result = result && rook_chkrules(board, move);
+        result = result && rook_chkrules(move);
         result = result && !rook_isblocked(board, move);
         break;
     case KNIGHT:
-        result = result && knight_chkrules(board, move);
+        result = result && knight_chkrules(move);
         result = result && !knight_isblocked(board, move);
         break;
     case BISHOP:
-        result = result && bishop_chkrules(board, move);
+        result = result && bishop_chkrules(move);
         result = result && !bishop_isblocked(board, move);
         break;
     case QUEEN:
-        result = result && queen_chkrules(board, move);
+        result = result && queen_chkrules(move);
         result = result && !queen_isblocked(board, move);
         break;
     case KING:
@@ -203,10 +203,9 @@
  * 
  * @param board the current state of the board
  * @param move the move date to operate on
- * @return TRUE if the location could be retrieved, FALSE if the location is
- * ambiguous
+ * @return status code (see rules/rules.h for the codes)
  */
-static _Bool getlocation(Board board, Move *move) {   
+static int getlocation(Board board, Move *move) {   
     uint8_t piece = move->piece & PIECE_MASK;
     switch (piece) {
         case PAWN: return pawn_getlocation(board, move);
@@ -215,7 +214,7 @@
         case BISHOP: return bishop_getlocation(board, move);
         case QUEEN: return queen_getlocation(board, move);
         case KING: return king_getlocation(board, move);
-        default: return FALSE;
+        default: return INVALID_MOVE_SYNTAX;
     }
 }
 
@@ -227,9 +226,9 @@
  * @param mycolor the color of the current player
  * @param mstr the input string to parse
  * @param move a pointer to object where the move data shall be stored
- * @return TRUE, if the move is syntactically valid, FALSE otherwise
+ * @return status code (see rules/rules.h for the list of codes)
  */
-static _Bool eval_move(Board board, uint8_t mycolor, char *mstr, Move *move) {
+static int eval_move(Board board, uint8_t mycolor, char *mstr, Move *move) {
     memset(move, 0, sizeof(Move));
     move->fromfile = POS_UNSPECIFIED;
     move->fromrow = POS_UNSPECIFIED;
@@ -331,14 +330,13 @@
         move->piece |= mycolor;
         if (move->fromfile == POS_UNSPECIFIED
             || move->fromrow == POS_UNSPECIFIED) {
-            return getlocation(board, move) && chkidx(move);
+            return getlocation(board, move);
         } else {
-            return chkidx(move);
+            return chkidx(move) ? VALID_MOVE_SYNTAX : INVALID_POSITION;
         }
     } else {
-        return FALSE;
+        return INVALID_MOVE_SYNTAX;
     }
-    // TODO: return status code to indicate the error type
 }
 
 static int sendmove(Board board, uint8_t mycolor, int opponent) {
@@ -366,6 +364,7 @@
 
         if (strncmp(movestr, "surr", buflen) == 0) {
             printw("You surrendered!");
+            clrtoeol();
             refresh();
             net_send_code(opponent, NETCODE_SURRENDER);
             return 1;
@@ -385,28 +384,40 @@
             }
         } else {
             Move move;
-            if (eval_move(board, mycolor, movestr, &move)) {
-                net_send_code(opponent, NETCODE_MOVE);
-                net_send_data(opponent, &move, sizeof(Move));
-                code = net_recieve_code(opponent);
-                move.check = code == NETCODE_CHECK;
-                move.checkmate = code == NETCODE_CHECKMATE;
-                // TODO: record move
-                if (code == NETCODE_DECLINE) {
-                    printw("Invalid move.");
-                    clrtoeol();
-                } else {
-                    apply_move(board, &move);
-                    if (move.checkmate) {
-                        printw("Checkmate!");
-                        return 1;
+            int eval_result = eval_move(board, mycolor, movestr, &move);
+            switch (eval_result) {
+                case VALID_MOVE_SYNTAX:
+                    net_send_code(opponent, NETCODE_MOVE);
+                    net_send_data(opponent, &move, sizeof(Move));
+                    code = net_recieve_code(opponent);
+                    move.check = code == NETCODE_CHECK;
+                    move.checkmate = code == NETCODE_CHECKMATE;
+                    // TODO: record move
+                    if (code == NETCODE_DECLINE) {
+                        printw("Invalid move.");
                     } else {
-                        return 0;
+                        apply_move(board, &move);
+                        if (move.checkmate) {
+                            printw("Checkmate!");
+                            clrtoeol();
+                            return 1;
+                        } else {
+                            return 0;
+                        }
                     }
-                }
-            } else {
-                printw("Can't interpret move - please use algebraic notation.");
+                    break;
+                case AMBIGUOUS_MOVE:
+                    printw("Ambiguous move - "
+                        "please specify the piece to move.");
+                    break;
+                case INVALID_POSITION:
+                    printw("Cannot find the piece that shall be moved.");
+                    break;
+                default:
+                    printw("Can't interpret move - "
+                        "please use algebraic notation.");
             }
+            clrtoeol();
         }
     }
 }
--- a/src/game.h	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/game.h	Fri Mar 28 14:32:52 2014 +0100
@@ -78,8 +78,8 @@
 } Move;
 
 #define POS_UNSPECIFIED UINT8_MAX
-#define mdst(b,m) b[m->torow][m->tofile]
-#define msrc(b,m) b[m->fromrow][m->fromfile]
+#define mdst(b,m) b[(m)->torow][(m)->tofile]
+#define msrc(b,m) b[(m)->fromrow][(m)->fromfile]
 
 #define isidx(idx) ((uint8_t)idx < 8)
 
@@ -89,8 +89,8 @@
 #define rowidx(row) (row-'1')
 #define fileidx(file) (file-'a')
 
-#define chkidx(move) (isidx(move->fromfile) && isidx(move->fromrow) && \
-        isidx(move->tofile) && isidx(move->torow))
+#define chkidx(move) (isidx((move)->fromfile) && isidx((move)->fromrow) && \
+        isidx((move)->tofile) && isidx((move)->torow))
 
 /* secure versions - use, if index is not checked with isidx() */
 #define fileidx_s(c) (isfile(c)?fileidx(c):POS_UNSPECIFIED)
--- a/src/main.c	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/main.c	Fri Mar 28 14:32:52 2014 +0100
@@ -159,7 +159,7 @@
             "Example: -t 150s\n"
         );
         return EXIT_SUCCESS;
-    }
+    }    
     tchess_window = initscr();
     cbreak();
     if (has_colors()) {
--- a/src/rules/bishop.c	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/bishop.c	Fri Mar 28 14:32:52 2014 +0100
@@ -28,8 +28,9 @@
  */
 
 #include "bishop.h"
+#include "rules.h"
 
-_Bool bishop_chkrules(Board board, Move* move) {
+_Bool bishop_chkrules(Move* move) {
     // TODO: implement
     return FALSE;
 }
@@ -39,7 +40,7 @@
     return TRUE;
 }
 
-_Bool bishop_getlocation(Board board, Move *move) {
+int bishop_getlocation(Board board, Move *move) {
     // TODO: implement
-    return FALSE;
+    return INVALID_MOVE_SYNTAX;
 }
--- a/src/rules/bishop.h	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/bishop.h	Fri Mar 28 14:32:52 2014 +0100
@@ -36,9 +36,9 @@
 extern "C" {
 #endif
 
-_Bool bishop_chkrules(Board board, Move *move);
+_Bool bishop_chkrules(Move *move);
 _Bool bishop_isblocked(Board board, Move *move);
-_Bool bishop_getlocation(Board board, Move *move);
+int bishop_getlocation(Board board, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/rules/king.c	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/king.c	Fri Mar 28 14:32:52 2014 +0100
@@ -27,6 +27,7 @@
  *
  */
 
+#include "rules.h"
 #include "king.h"
 
 _Bool king_chkrules(Board board, Move* move) {
@@ -39,7 +40,7 @@
     return TRUE;
 }
 
-_Bool king_getlocation(Board board, Move *move) {
+int king_getlocation(Board board, Move *move) {
     // TODO: implement
-    return FALSE;
+    return INVALID_MOVE_SYNTAX;
 }
--- a/src/rules/king.h	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/king.h	Fri Mar 28 14:32:52 2014 +0100
@@ -39,7 +39,7 @@
 
 _Bool king_chkrules(Board board, Move *move);
 _Bool king_isblocked(Board board, Move *move);
-_Bool king_getlocation(Board board, Move *move);
+int king_getlocation(Board board, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/rules/knight.c	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/knight.c	Fri Mar 28 14:32:52 2014 +0100
@@ -28,18 +28,106 @@
  */
 
 #include "knight.h"
+#include "rules.h"
+#include <math.h>
 
-_Bool knight_chkrules(Board board, Move *move) {
-    // TODO: implement
-    return FALSE;
+_Bool knight_chkrules(Move *move) {
+    int dx = abs(move->fromfile - move->tofile);
+    int dy = abs(move->fromrow - move->torow);
+    
+    return (dx == 2 && dy == 1) || (dx == 1 && dy == 2);
+}
+
+static int knight_getloc_fixedrow(Board board, 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) {
+            if (move->fromfile == POS_UNSPECIFIED) {
+                move->fromfile = move->tofile + d;
+                return VALID_MOVE_SYNTAX;
+            } else {
+                return AMBIGUOUS_MOVE;
+            }
+        }
+        if (move->tofile > 1 &&
+            board[move->fromrow][move->tofile - d] == move->piece) {
+            if (move->fromfile == POS_UNSPECIFIED) {
+                move->fromfile = move->tofile - d;
+                return VALID_MOVE_SYNTAX;
+            } else {
+                return AMBIGUOUS_MOVE;
+            }
+        }
+    }
+    
+    return INVALID_POSITION;
 }
 
-_Bool knight_isblocked(Board board, Move *move) {
-    // TODO: implement
-    return TRUE;
+static int knight_getloc_fixedfile(Board board, 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) {
+            if (move->fromrow == POS_UNSPECIFIED) {
+                move->fromrow = move->torow + d;
+                return VALID_MOVE_SYNTAX;
+            } else {
+                return AMBIGUOUS_MOVE;
+            }
+        }
+        if (move->torow > 1 &&
+            board[move->torow - d][move->fromfile] == move->piece) {
+            if (move->fromrow == POS_UNSPECIFIED) {
+                move->fromrow = move->torow - d;
+                return VALID_MOVE_SYNTAX;
+            } else {
+                return AMBIGUOUS_MOVE;
+            }
+        }
+    }
+    
+    return INVALID_POSITION;
 }
 
-_Bool knight_getlocation(Board board, Move *move) {
-    // TODO: implement
-    return FALSE;
+int knight_getlocation(Board board, Move *move) {
+    
+    if (move->fromfile != POS_UNSPECIFIED) {
+        return knight_getloc_fixedfile(board, move);
+    }
+    
+    if (move->fromrow != POS_UNSPECIFIED) {
+        return knight_getloc_fixedrow(board, move);
+    }
+    
+    for (int x = -2 ; x <= 2 ; x++) {
+        if (x == 0) {
+            continue;
+        }
+        for (int y = -2 ; y <= 2 ; y++) {
+            if (y == 0 || y == x) {
+                continue;
+            }
+            uint8_t cx = move->tofile + x;
+            uint8_t cy = move->torow + y;
+
+            if (isidx(cx) && isidx(cy) && board[cy][cx] == move->piece) {
+                if (move->fromfile == POS_UNSPECIFIED
+                    && move->fromrow == POS_UNSPECIFIED) {
+                    move->fromfile = cx;
+                    move->fromrow = cy;
+                } else {
+                    return AMBIGUOUS_MOVE;
+                }
+            }
+        }
+    }
+    
+    if (move->fromfile == POS_UNSPECIFIED || move->fromrow == POS_UNSPECIFIED) {
+        return INVALID_POSITION;
+    } else {
+        return VALID_MOVE_SYNTAX;
+    }
 }
--- a/src/rules/knight.h	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/knight.h	Fri Mar 28 14:32:52 2014 +0100
@@ -36,9 +36,9 @@
 extern "C" {
 #endif
 
-_Bool knight_chkrules(Board board, Move *move);
-_Bool knight_isblocked(Board board, Move *move);
-_Bool knight_getlocation(Board board, Move *move);
+_Bool knight_chkrules(Move *move);
+#define knight_isblocked(b,m) FALSE
+int knight_getlocation(Board board, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/rules/pawn.c	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/pawn.c	Fri Mar 28 14:32:52 2014 +0100
@@ -28,6 +28,7 @@
  */
 
 #include "pawn.h"
+#include "rules.h"
 
 _Bool pawn_chkrules(Board board, Move *move) {
     int8_t d = ((move->piece & COLOR_MASK) == WHITE ? -1 : 1);
@@ -56,7 +57,7 @@
     return mdst(board,move) && !move->capture;
 }
 
-_Bool pawn_getlocation(Board board, Move *move) {
+int pawn_getlocation(Board board, Move *move) {
     int8_t d = ((move->piece & COLOR_MASK) == WHITE ? -1 : 1);
     
     if (move->fromfile == POS_UNSPECIFIED) {
@@ -64,7 +65,7 @@
     }
     move->fromrow = move->torow + d;
     if (move->fromrow > 6) {
-        return FALSE;
+        return INVALID_POSITION;
     } else {
         /* advanced first move */
         if (move->fromrow == (d < 0 ? 2 : 5) &&
@@ -72,9 +73,9 @@
 
             move->fromrow += d;
             if (move->fromrow > 6) {
-                return FALSE;
+                return INVALID_POSITION;
             }
         }
     }
-    return TRUE;
+    return VALID_MOVE_SYNTAX;
 }
--- a/src/rules/pawn.h	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/pawn.h	Fri Mar 28 14:32:52 2014 +0100
@@ -38,7 +38,7 @@
 
 _Bool pawn_chkrules(Board board, Move *move);
 _Bool pawn_isblocked(Board board, Move *move);
-_Bool pawn_getlocation(Board board, Move *move);
+int pawn_getlocation(Board board, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/rules/queen.c	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/queen.c	Fri Mar 28 14:32:52 2014 +0100
@@ -27,9 +27,10 @@
  *
  */
 
+#include "rules.h"
 #include "queen.h"
 
-_Bool queen_chkrules(Board board, Move* move) {
+_Bool queen_chkrules(Move* move) {
     // TODO: implement
     return FALSE;
 }
@@ -39,7 +40,7 @@
     return TRUE;
 }
 
-_Bool queen_getlocation(Board board, Move *move) {
+int queen_getlocation(Board board, Move *move) {
     // TODO: implement
-    return FALSE;
+    return INVALID_MOVE_SYNTAX;
 }
--- a/src/rules/queen.h	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/queen.h	Fri Mar 28 14:32:52 2014 +0100
@@ -36,9 +36,9 @@
 extern "C" {
 #endif
 
-_Bool queen_chkrules(Board board, Move *move);
+_Bool queen_chkrules(Move *move);
 _Bool queen_isblocked(Board board, Move *move);
-_Bool queen_getlocation(Board board, Move *move);
+int queen_getlocation(Board board, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/rules/rook.c	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/rook.c	Fri Mar 28 14:32:52 2014 +0100
@@ -27,9 +27,10 @@
  *
  */
 
+#include "rules.h"
 #include "rook.h"
 
-_Bool rook_chkrules(Board board, Move *move) {
+_Bool rook_chkrules(Move *move) {
     // TODO: implement
     return FALSE;
 }
@@ -39,7 +40,7 @@
     return TRUE;
 }
 
-_Bool rook_getlocation(Board board, Move *move) {
+int rook_getlocation(Board board, Move *move) {
     // TODO: implement
-    return FALSE;
+    return INVALID_MOVE_SYNTAX;
 }
--- a/src/rules/rook.h	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/rook.h	Fri Mar 28 14:32:52 2014 +0100
@@ -36,9 +36,9 @@
 extern "C" {
 #endif
 
-_Bool rook_chkrules(Board board, Move *move);
+_Bool rook_chkrules(Move *move);
 _Bool rook_isblocked(Board board, Move *move);
-_Bool rook_getlocation(Board board, Move *move);
+int rook_getlocation(Board board, Move *move);
 
 #ifdef	__cplusplus
 }
--- a/src/rules/rules.h	Fri Mar 28 11:45:01 2014 +0100
+++ b/src/rules/rules.h	Fri Mar 28 14:32:52 2014 +0100
@@ -37,5 +37,10 @@
 #include "queen.h"
 #include "king.h"
 
+#define VALID_MOVE_SYNTAX   0
+#define INVALID_MOVE_SYNTAX 1
+#define INVALID_POSITION    2
+#define AMBIGUOUS_MOVE      3
+
 #endif	/* RULES_H */
 

mercurial