hadif azli / Mbed 2 deprecated TEST123

Dependencies:   mbed Blynk

Committer:
lixianyu
Date:
Fri Jun 10 15:20:20 2016 +0000
Revision:
0:d8f4c441e032
u8glib???????????i2c???

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lixianyu 0:d8f4c441e032 1 /*
lixianyu 0:d8f4c441e032 2 chessengine.c
lixianyu 0:d8f4c441e032 3
lixianyu 0:d8f4c441e032 4 "Little Rook Chess" (lrc)
lixianyu 0:d8f4c441e032 5
lixianyu 0:d8f4c441e032 6 Port to u8g library
lixianyu 0:d8f4c441e032 7
lixianyu 0:d8f4c441e032 8 chess for embedded 8-Bit controllers
lixianyu 0:d8f4c441e032 9
lixianyu 0:d8f4c441e032 10 Copyright (c) 2012, olikraus@gmail.com
lixianyu 0:d8f4c441e032 11 All rights reserved.
lixianyu 0:d8f4c441e032 12
lixianyu 0:d8f4c441e032 13 Redistribution and use in source and binary forms, with or without modification,
lixianyu 0:d8f4c441e032 14 are permitted provided that the following conditions are met:
lixianyu 0:d8f4c441e032 15
lixianyu 0:d8f4c441e032 16 * Redistributions of source code must retain the above copyright notice, this list
lixianyu 0:d8f4c441e032 17 of conditions and the following disclaimer.
lixianyu 0:d8f4c441e032 18
lixianyu 0:d8f4c441e032 19 * Redistributions in binary form must reproduce the above copyright notice, this
lixianyu 0:d8f4c441e032 20 list of conditions and the following disclaimer in the documentation and/or other
lixianyu 0:d8f4c441e032 21 materials provided with the distribution.
lixianyu 0:d8f4c441e032 22
lixianyu 0:d8f4c441e032 23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
lixianyu 0:d8f4c441e032 24 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
lixianyu 0:d8f4c441e032 25 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
lixianyu 0:d8f4c441e032 26 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
lixianyu 0:d8f4c441e032 27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
lixianyu 0:d8f4c441e032 28 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
lixianyu 0:d8f4c441e032 29 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
lixianyu 0:d8f4c441e032 30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
lixianyu 0:d8f4c441e032 31 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
lixianyu 0:d8f4c441e032 32 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
lixianyu 0:d8f4c441e032 33 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
lixianyu 0:d8f4c441e032 34 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
lixianyu 0:d8f4c441e032 35 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
lixianyu 0:d8f4c441e032 36
lixianyu 0:d8f4c441e032 37 Note:
lixianyu 0:d8f4c441e032 38 UNIX_MAIN --> unix console executable
lixianyu 0:d8f4c441e032 39
lixianyu 0:d8f4c441e032 40 Current Rule Limitation
lixianyu 0:d8f4c441e032 41 - no minor promotion, only "Queening" of the pawn
lixianyu 0:d8f4c441e032 42 - threefold repetition is not detected (same board situation appears three times)
lixianyu 0:d8f4c441e032 43 Note: Could be implemented, but requires tracking of the complete game
lixianyu 0:d8f4c441e032 44 - Fifty-move rule is not checked (no pawn move, no capture within last 50 moves)
lixianyu 0:d8f4c441e032 45
lixianyu 0:d8f4c441e032 46 Words
lixianyu 0:d8f4c441e032 47 Ply a half move
lixianyu 0:d8f4c441e032 48
lixianyu 0:d8f4c441e032 49 General Links
lixianyu 0:d8f4c441e032 50 http://chessprogramming.wikispaces.com/
lixianyu 0:d8f4c441e032 51
lixianyu 0:d8f4c441e032 52 Arduino specific
lixianyu 0:d8f4c441e032 53 http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1260055596
lixianyu 0:d8f4c441e032 54
lixianyu 0:d8f4c441e032 55 Prefixes
lixianyu 0:d8f4c441e032 56 chess_ Generic Chess Application Interface
lixianyu 0:d8f4c441e032 57 ce_ Chess engine, used internally, these function should not be called directly
lixianyu 0:d8f4c441e032 58 cu_ Chess utility function
lixianyu 0:d8f4c441e032 59 stack_ Internal function for stack handling
lixianyu 0:d8f4c441e032 60
lixianyu 0:d8f4c441e032 61 Issues
lixianyu 0:d8f4c441e032 62 10.01.2011
lixianyu 0:d8f4c441e032 63 - castling to the right does not move the rook
lixianyu 0:d8f4c441e032 64 --> done
lixianyu 0:d8f4c441e032 65 - castling to the left: King can only move two squares
lixianyu 0:d8f4c441e032 66 --> done
lixianyu 0:d8f4c441e032 67
lixianyu 0:d8f4c441e032 68 11.01.2011
lixianyu 0:d8f4c441e032 69 Next Steps:
lixianyu 0:d8f4c441e032 70 - replace stack_NextCurrentPos with cu_NextPos, cleanup code according to the loop variable
lixianyu 0:d8f4c441e032 71 --> done
lixianyu 0:d8f4c441e032 72 - Castling: Need to check for fields under attack
lixianyu 0:d8f4c441e032 73 --> done
lixianyu 0:d8f4c441e032 74
lixianyu 0:d8f4c441e032 75 - Check for WIN / LOOSE situation, perhaps call ce_Eval() once on the top-level board setup
lixianyu 0:d8f4c441e032 76 just after the real move
lixianyu 0:d8f4c441e032 77 - cleanup cu_Move
lixianyu 0:d8f4c441e032 78 --> almost done
lixianyu 0:d8f4c441e032 79 - add some heuristics to the eval procedure
lixianyu 0:d8f4c441e032 80 - add right side menu
lixianyu 0:d8f4c441e032 81 --> done
lixianyu 0:d8f4c441e032 82 - clean up chess_ManualMove
lixianyu 0:d8f4c441e032 83 --> done
lixianyu 0:d8f4c441e032 84 - finish menu (consider is_game_end, undo move)
lixianyu 0:d8f4c441e032 85 - end condition: if KING is under attack and if KING can not move to a field which is under attack...
lixianyu 0:d8f4c441e032 86 then the game is lost. What will be returned by the Eval procedure? is it -INF?
lixianyu 0:d8f4c441e032 87 --> finished
lixianyu 0:d8f4c441e032 88
lixianyu 0:d8f4c441e032 89 - reduce the use of variable color, all should be reduced to board_orientation and ply&1
lixianyu 0:d8f4c441e032 90
lixianyu 0:d8f4c441e032 91 - chess_GetNextMarked shoud make use of cu_NextPos
lixianyu 0:d8f4c441e032 92 --> done
lixianyu 0:d8f4c441e032 93 - chess_ManualMove: again cleanup, solve draw issue (KING is not in check and no legal moves are available)
lixianyu 0:d8f4c441e032 94 --> done
lixianyu 0:d8f4c441e032 95 22.01.2011
lixianyu 0:d8f4c441e032 96 - simplify eval_t ce_Eval(void)
lixianyu 0:d8f4c441e032 97 - position eval does not work, still moves side pawn :-(
lixianyu 0:d8f4c441e032 98 maybe because all pieces are considered
lixianyu 0:d8f4c441e032 99 --> done
lixianyu 0:d8f4c441e032 100
lixianyu 0:d8f4c441e032 101 */
lixianyu 0:d8f4c441e032 102
lixianyu 0:d8f4c441e032 103 #include "u8g.h"
lixianyu 0:d8f4c441e032 104
lixianyu 0:d8f4c441e032 105 //#ifndef __unix__
lixianyu 0:d8f4c441e032 106 //#else
lixianyu 0:d8f4c441e032 107 //#include <assert.h>
lixianyu 0:d8f4c441e032 108 //#define U8G_NOINLINE
lixianyu 0:d8f4c441e032 109 //#endif
lixianyu 0:d8f4c441e032 110
lixianyu 0:d8f4c441e032 111 /*
lixianyu 0:d8f4c441e032 112 SAN identifies each piece by a single upper case letter. The standard English
lixianyu 0:d8f4c441e032 113 values: pawn = "P", knight = "N", bishop = "B", rook = "R", queen = "Q", and
lixianyu 0:d8f4c441e032 114 king = "K".
lixianyu 0:d8f4c441e032 115 */
lixianyu 0:d8f4c441e032 116
lixianyu 0:d8f4c441e032 117 /* numbers for the various pieces */
lixianyu 0:d8f4c441e032 118 #define PIECE_NONE 0
lixianyu 0:d8f4c441e032 119 #define PIECE_PAWN 1
lixianyu 0:d8f4c441e032 120 #define PIECE_KNIGHT 2
lixianyu 0:d8f4c441e032 121 #define PIECE_BISHOP 3
lixianyu 0:d8f4c441e032 122 #define PIECE_ROOK 4
lixianyu 0:d8f4c441e032 123 #define PIECE_QUEEN 5
lixianyu 0:d8f4c441e032 124 #define PIECE_KING 6
lixianyu 0:d8f4c441e032 125
lixianyu 0:d8f4c441e032 126 /* color definitions */
lixianyu 0:d8f4c441e032 127 #define COLOR_WHITE 0
lixianyu 0:d8f4c441e032 128 #define COLOR_BLACK 1
lixianyu 0:d8f4c441e032 129
lixianyu 0:d8f4c441e032 130 /* a mask, which includes COLOR and PIECE number */
lixianyu 0:d8f4c441e032 131 #define COLOR_PIECE_MASK 0x01f
lixianyu 0:d8f4c441e032 132
lixianyu 0:d8f4c441e032 133 #define CP_MARK_MASK 0x20
lixianyu 0:d8f4c441e032 134
lixianyu 0:d8f4c441e032 135 #define ILLEGAL_POSITION 255
lixianyu 0:d8f4c441e032 136
lixianyu 0:d8f4c441e032 137 /* This is the build in upper limit of the search stack */
lixianyu 0:d8f4c441e032 138 /* This value defines the amount of memory allocated for the search stack */
lixianyu 0:d8f4c441e032 139 /* The search depth of this chess engine can never exceed this value */
lixianyu 0:d8f4c441e032 140 #define STACK_MAX_SIZE 5
lixianyu 0:d8f4c441e032 141
lixianyu 0:d8f4c441e032 142 /* chess half move stack: twice the number of undo's, a user can do */
lixianyu 0:d8f4c441e032 143 #define CHM_USER_SIZE 6
lixianyu 0:d8f4c441e032 144
lixianyu 0:d8f4c441e032 145 /* the CHM_LIST_SIZE must be larger than the maximum search depth */
lixianyu 0:d8f4c441e032 146 /* the overall size of ste half move stack */
lixianyu 0:d8f4c441e032 147 #define CHM_LIST_SIZE (STACK_MAX_SIZE+CHM_USER_SIZE+2)
lixianyu 0:d8f4c441e032 148
lixianyu 0:d8f4c441e032 149 typedef int16_t eval_t; /* a variable type to store results from the evaluation */
lixianyu 0:d8f4c441e032 150 //#define EVAL_T_LOST -32768
lixianyu 0:d8f4c441e032 151 #define EVAL_T_MIN -32767
lixianyu 0:d8f4c441e032 152 #define EVAL_T_MAX 32767
lixianyu 0:d8f4c441e032 153 //#define EVAL_T_WIN 32767
lixianyu 0:d8f4c441e032 154
lixianyu 0:d8f4c441e032 155 /* for maintainance of our own stack: this is the definition of one element on the stack */
lixianyu 0:d8f4c441e032 156 struct _stack_element_struct
lixianyu 0:d8f4c441e032 157 {
lixianyu 0:d8f4c441e032 158 /* the current source position which is investigated */
lixianyu 0:d8f4c441e032 159 uint8_t current_pos;
lixianyu 0:d8f4c441e032 160 uint8_t current_cp;
lixianyu 0:d8f4c441e032 161 uint8_t current_color; /* COLOR_WHITE or COLOR_BLACK: must be predefines */
lixianyu 0:d8f4c441e032 162
lixianyu 0:d8f4c441e032 163 /* the move which belongs to that value, both values are game positions */
lixianyu 0:d8f4c441e032 164 uint8_t best_from_pos;
lixianyu 0:d8f4c441e032 165 uint8_t best_to_pos;
lixianyu 0:d8f4c441e032 166 /* the best value, which has been dicovered so far */
lixianyu 0:d8f4c441e032 167 eval_t best_eval;
lixianyu 0:d8f4c441e032 168 };
lixianyu 0:d8f4c441e032 169 typedef struct _stack_element_struct stack_element_t;
lixianyu 0:d8f4c441e032 170 typedef struct _stack_element_struct *stack_element_p;
lixianyu 0:d8f4c441e032 171
lixianyu 0:d8f4c441e032 172 /* chess half move history */
lixianyu 0:d8f4c441e032 173 struct _chm_struct
lixianyu 0:d8f4c441e032 174 {
lixianyu 0:d8f4c441e032 175 uint8_t main_cp; /* the main piece, which is moved */
lixianyu 0:d8f4c441e032 176 uint8_t main_src; /* the source position of the main piece */
lixianyu 0:d8f4c441e032 177 uint8_t main_dest; /* the destination of the main piece */
lixianyu 0:d8f4c441e032 178
lixianyu 0:d8f4c441e032 179 uint8_t other_cp; /* another piece: the captured one, the ROOK in case of castling or PIECE_NONE */
lixianyu 0:d8f4c441e032 180 uint8_t other_src; /* the delete position of other_cp. Often identical to main_dest except for e.p. and castling */
lixianyu 0:d8f4c441e032 181 uint8_t other_dest; /* only used for castling: ROOK destination pos */
lixianyu 0:d8f4c441e032 182
lixianyu 0:d8f4c441e032 183 /* the position of the last pawn, which did a double move forward */
lixianyu 0:d8f4c441e032 184 /* this is required to check en passant conditions */
lixianyu 0:d8f4c441e032 185 /* this array can be indexed by the color of the current player */
lixianyu 0:d8f4c441e032 186 /* this is the condition BEFORE the move was done */
lixianyu 0:d8f4c441e032 187 uint8_t pawn_dbl_move[2];
lixianyu 0:d8f4c441e032 188
lixianyu 0:d8f4c441e032 189 /* flags for the movement of rook and king; required for castling */
lixianyu 0:d8f4c441e032 190 /* a 1 means: castling is (still) possible */
lixianyu 0:d8f4c441e032 191 /* a 0 means: castling not possible */
lixianyu 0:d8f4c441e032 192 /* bit 0 left side white */
lixianyu 0:d8f4c441e032 193 /* bit 1 right side white */
lixianyu 0:d8f4c441e032 194 /* bit 2 left side black */
lixianyu 0:d8f4c441e032 195 /* bit 3 right side black */
lixianyu 0:d8f4c441e032 196 /* this is the condition BEFORE the move was done */
lixianyu 0:d8f4c441e032 197 uint8_t castling_possible;
lixianyu 0:d8f4c441e032 198 };
lixianyu 0:d8f4c441e032 199
lixianyu 0:d8f4c441e032 200 typedef struct _chm_struct chm_t;
lixianyu 0:d8f4c441e032 201 typedef struct _chm_struct *chm_p;
lixianyu 0:d8f4c441e032 202
lixianyu 0:d8f4c441e032 203 /* little rook chess, main structure */
lixianyu 0:d8f4c441e032 204 struct _lrc_struct
lixianyu 0:d8f4c441e032 205 {
lixianyu 0:d8f4c441e032 206 /* half-move (ply) counter: Counts the number of half-moves so far. Starts with 0 */
lixianyu 0:d8f4c441e032 207 /* the lowest bit is used to derive the color of the current player */
lixianyu 0:d8f4c441e032 208 /* will be set to zero in chess_SetupBoard() */
lixianyu 0:d8f4c441e032 209 uint8_t ply_count;
lixianyu 0:d8f4c441e032 210
lixianyu 0:d8f4c441e032 211 /* the half move stack position counter, counts the number of elements in chm_list */
lixianyu 0:d8f4c441e032 212 uint8_t chm_pos;
lixianyu 0:d8f4c441e032 213
lixianyu 0:d8f4c441e032 214 /* each element contains a colored piece, empty fields have value 0 */
lixianyu 0:d8f4c441e032 215 /* the field with index 0 is black (lower left) */
lixianyu 0:d8f4c441e032 216 uint8_t board[64];
lixianyu 0:d8f4c441e032 217 /* the position of the last pawn, which did a double move forward */
lixianyu 0:d8f4c441e032 218 /* this is required to check en passant conditions */
lixianyu 0:d8f4c441e032 219 /* this array can be indexed by the color of the current player */
lixianyu 0:d8f4c441e032 220 uint8_t pawn_dbl_move[2];
lixianyu 0:d8f4c441e032 221
lixianyu 0:d8f4c441e032 222 /* flags for the movement of rook and king; required for castling */
lixianyu 0:d8f4c441e032 223 /* a 1 means: castling is (still) possible */
lixianyu 0:d8f4c441e032 224 /* a 0 means: castling not possible */
lixianyu 0:d8f4c441e032 225 /* bit 0 left side white */
lixianyu 0:d8f4c441e032 226 /* bit 1 right side white */
lixianyu 0:d8f4c441e032 227 /* bit 2 left side black */
lixianyu 0:d8f4c441e032 228 /* bit 3 right side black */
lixianyu 0:d8f4c441e032 229 uint8_t castling_possible;
lixianyu 0:d8f4c441e032 230
lixianyu 0:d8f4c441e032 231 /* board orientation */
lixianyu 0:d8f4c441e032 232 /* 0: white is below COLOR_WHITE */
lixianyu 0:d8f4c441e032 233 /* 1: black is below COLOR_BLACK */
lixianyu 0:d8f4c441e032 234 /* bascially, this can be used as a color */
lixianyu 0:d8f4c441e032 235 uint8_t orientation;
lixianyu 0:d8f4c441e032 236
lixianyu 0:d8f4c441e032 237 /* exchange colors of the pieces */
lixianyu 0:d8f4c441e032 238 /* 0: white has an empty body, use this for bright background color */
lixianyu 0:d8f4c441e032 239 /* 1: black has an empty body, use this for dark backround color */
lixianyu 0:d8f4c441e032 240 uint8_t strike_out_color;
lixianyu 0:d8f4c441e032 241
lixianyu 0:d8f4c441e032 242 /* 0, when the game is ongoing */
lixianyu 0:d8f4c441e032 243 /* 1, when the game is stopped (lost or draw) */
lixianyu 0:d8f4c441e032 244 uint8_t is_game_end;
lixianyu 0:d8f4c441e032 245 /* the color of the side which lost the game */
lixianyu 0:d8f4c441e032 246 /* this value is only valid, when is_game_end is not 0 */
lixianyu 0:d8f4c441e032 247 /* values 0 and 1 represent WHITE and BLACK, 2 means a draw */
lixianyu 0:d8f4c441e032 248 uint8_t lost_side_color;
lixianyu 0:d8f4c441e032 249
lixianyu 0:d8f4c441e032 250
lixianyu 0:d8f4c441e032 251
lixianyu 0:d8f4c441e032 252 /* checks are executed in ce_LoopRecur */
lixianyu 0:d8f4c441e032 253 /* these checks will put some marks on the board */
lixianyu 0:d8f4c441e032 254 /* this will be used by the interface to find out */
lixianyu 0:d8f4c441e032 255 /* legal moves */
lixianyu 0:d8f4c441e032 256 uint8_t check_src_pos;
lixianyu 0:d8f4c441e032 257 uint8_t check_mode; /* CHECK_MODE_NONE, CHECK_MODE_MOVEABLE, CHECK_MODE_TARGET_MOVE */
lixianyu 0:d8f4c441e032 258
lixianyu 0:d8f4c441e032 259
lixianyu 0:d8f4c441e032 260 /* count of the attacking pieces, indexed by color */
lixianyu 0:d8f4c441e032 261 uint8_t find_piece_cnt[2];
lixianyu 0:d8f4c441e032 262
lixianyu 0:d8f4c441e032 263 /* sum of the attacking pieces, indexed by color */
lixianyu 0:d8f4c441e032 264 uint8_t find_piece_weight[2];
lixianyu 0:d8f4c441e032 265
lixianyu 0:d8f4c441e032 266 /* points to the current element of the search stack */
lixianyu 0:d8f4c441e032 267 /* this stack is NEVER empty. The value 0 points to the first element of the stack */
lixianyu 0:d8f4c441e032 268 /* actually "curr_depth" represent half-moves (plies) */
lixianyu 0:d8f4c441e032 269 uint8_t curr_depth;
lixianyu 0:d8f4c441e032 270 uint8_t max_depth;
lixianyu 0:d8f4c441e032 271 stack_element_p curr_element;
lixianyu 0:d8f4c441e032 272
lixianyu 0:d8f4c441e032 273 /* allocated memory for the search stack */
lixianyu 0:d8f4c441e032 274 stack_element_t stack_memory[STACK_MAX_SIZE];
lixianyu 0:d8f4c441e032 275
lixianyu 0:d8f4c441e032 276 /* the half move stack, used for move undo and depth search, size is stored in chm_pos */
lixianyu 0:d8f4c441e032 277 chm_t chm_list[CHM_LIST_SIZE];
lixianyu 0:d8f4c441e032 278 };
lixianyu 0:d8f4c441e032 279 typedef struct _lrc_struct lrc_t;
lixianyu 0:d8f4c441e032 280
lixianyu 0:d8f4c441e032 281 #define CHECK_MODE_NONE 0
lixianyu 0:d8f4c441e032 282 #define CHECK_MODE_MOVEABLE 1
lixianyu 0:d8f4c441e032 283 #define CHECK_MODE_TARGET_MOVE 2
lixianyu 0:d8f4c441e032 284
lixianyu 0:d8f4c441e032 285
lixianyu 0:d8f4c441e032 286
lixianyu 0:d8f4c441e032 287 /*==============================================================*/
lixianyu 0:d8f4c441e032 288 /* global variables */
lixianyu 0:d8f4c441e032 289 /*==============================================================*/
lixianyu 0:d8f4c441e032 290
lixianyu 0:d8f4c441e032 291 u8g_t *lrc_u8g;
lixianyu 0:d8f4c441e032 292
lixianyu 0:d8f4c441e032 293 lrc_t lrc_obj;
lixianyu 0:d8f4c441e032 294
lixianyu 0:d8f4c441e032 295
lixianyu 0:d8f4c441e032 296 /*==============================================================*/
lixianyu 0:d8f4c441e032 297 /* forward declarations */
lixianyu 0:d8f4c441e032 298 /*==============================================================*/
lixianyu 0:d8f4c441e032 299
lixianyu 0:d8f4c441e032 300 /*
lixianyu 0:d8f4c441e032 301 apply no inline to some of the functions:
lixianyu 0:d8f4c441e032 302 avr-gcc very often inlines functions, however not inline saves a lot of program memory!
lixianyu 0:d8f4c441e032 303 On the other hand there are some really short procedures which should be inlined (like cp_GetColor)
lixianyu 0:d8f4c441e032 304 These procedures are marked static to prevent the generation of the expanded procedure, which
lixianyu 0:d8f4c441e032 305 also saves space.
lixianyu 0:d8f4c441e032 306 */
lixianyu 0:d8f4c441e032 307
lixianyu 0:d8f4c441e032 308 uint8_t stack_Push(uint8_t color) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 309 void stack_Pop(void) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 310 void stack_InitCurrElement(void) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 311 void stack_Init(uint8_t max) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 312 void stack_SetMove(eval_t val, uint8_t to_pos) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 313 uint8_t cu_NextPos(uint8_t pos) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 314 static uint8_t cu_gpos2bpos(uint8_t gpos);
lixianyu 0:d8f4c441e032 315 static uint8_t cp_Construct(uint8_t color, uint8_t piece);
lixianyu 0:d8f4c441e032 316 static uint8_t cp_GetPiece(uint8_t cp);
lixianyu 0:d8f4c441e032 317 static uint8_t cp_GetColor(uint8_t cp);
lixianyu 0:d8f4c441e032 318 uint8_t cp_GetFromBoard(uint8_t pos) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 319 void cp_SetOnBoard(uint8_t pos, uint8_t cp) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 320
lixianyu 0:d8f4c441e032 321 void cu_ClearBoard(void) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 322 void chess_SetupBoard(void) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 323 eval_t ce_Eval(void);
lixianyu 0:d8f4c441e032 324
lixianyu 0:d8f4c441e032 325 void cu_ClearMoveHistory(void) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 326 void cu_ReduceHistoryByFullMove(void) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 327 void cu_UndoHalfMove(void) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 328 chm_p cu_PushHalfMove(void) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 329
lixianyu 0:d8f4c441e032 330
lixianyu 0:d8f4c441e032 331 void ce_CalculatePositionWeight(uint8_t pos);
lixianyu 0:d8f4c441e032 332 uint8_t ce_GetPositionAttackWeight(uint8_t pos, uint8_t color);
lixianyu 0:d8f4c441e032 333
lixianyu 0:d8f4c441e032 334 void chess_Thinking(void);
lixianyu 0:d8f4c441e032 335 void ce_LoopPieces(void);
lixianyu 0:d8f4c441e032 336
lixianyu 0:d8f4c441e032 337
lixianyu 0:d8f4c441e032 338 /*==============================================================*/
lixianyu 0:d8f4c441e032 339 /* search stack */
lixianyu 0:d8f4c441e032 340 /*==============================================================*/
lixianyu 0:d8f4c441e032 341
lixianyu 0:d8f4c441e032 342 /* get current element from stack */
lixianyu 0:d8f4c441e032 343 stack_element_p stack_GetCurrElement(void)
lixianyu 0:d8f4c441e032 344 {
lixianyu 0:d8f4c441e032 345 return lrc_obj.curr_element;
lixianyu 0:d8f4c441e032 346 }
lixianyu 0:d8f4c441e032 347
lixianyu 0:d8f4c441e032 348 uint8_t stack_Push(uint8_t color)
lixianyu 0:d8f4c441e032 349 {
lixianyu 0:d8f4c441e032 350 if ( lrc_obj.curr_depth == lrc_obj.max_depth )
lixianyu 0:d8f4c441e032 351 return 0;
lixianyu 0:d8f4c441e032 352 lrc_obj.curr_depth++;
lixianyu 0:d8f4c441e032 353 lrc_obj.curr_element = lrc_obj.stack_memory+lrc_obj.curr_depth;
lixianyu 0:d8f4c441e032 354
lixianyu 0:d8f4c441e032 355 /* change view for the evaluation */
lixianyu 0:d8f4c441e032 356 color ^= 1;
lixianyu 0:d8f4c441e032 357 stack_GetCurrElement()->current_color = color;
lixianyu 0:d8f4c441e032 358
lixianyu 0:d8f4c441e032 359 return 1;
lixianyu 0:d8f4c441e032 360 }
lixianyu 0:d8f4c441e032 361
lixianyu 0:d8f4c441e032 362 void stack_Pop(void)
lixianyu 0:d8f4c441e032 363 {
lixianyu 0:d8f4c441e032 364 lrc_obj.curr_depth--;
lixianyu 0:d8f4c441e032 365 lrc_obj.curr_element = lrc_obj.stack_memory+lrc_obj.curr_depth;
lixianyu 0:d8f4c441e032 366 }
lixianyu 0:d8f4c441e032 367
lixianyu 0:d8f4c441e032 368 /* reset the current element on the stack */
lixianyu 0:d8f4c441e032 369 void stack_InitCurrElement(void)
lixianyu 0:d8f4c441e032 370 {
lixianyu 0:d8f4c441e032 371 stack_element_p e = stack_GetCurrElement();
lixianyu 0:d8f4c441e032 372 e->best_eval = EVAL_T_MIN;
lixianyu 0:d8f4c441e032 373 e->best_from_pos = ILLEGAL_POSITION;
lixianyu 0:d8f4c441e032 374 e->best_to_pos = ILLEGAL_POSITION;
lixianyu 0:d8f4c441e032 375 }
lixianyu 0:d8f4c441e032 376
lixianyu 0:d8f4c441e032 377 /* resets the search stack (and the check mode) */
lixianyu 0:d8f4c441e032 378 void stack_Init(uint8_t max)
lixianyu 0:d8f4c441e032 379 {
lixianyu 0:d8f4c441e032 380 lrc_obj.curr_depth = 0;
lixianyu 0:d8f4c441e032 381 lrc_obj.curr_element = lrc_obj.stack_memory;
lixianyu 0:d8f4c441e032 382 lrc_obj.max_depth = max;
lixianyu 0:d8f4c441e032 383 lrc_obj.check_mode = CHECK_MODE_NONE;
lixianyu 0:d8f4c441e032 384 stack_InitCurrElement();
lixianyu 0:d8f4c441e032 385 stack_GetCurrElement()->current_color = lrc_obj.ply_count;
lixianyu 0:d8f4c441e032 386 stack_GetCurrElement()->current_color &= 1;
lixianyu 0:d8f4c441e032 387 }
lixianyu 0:d8f4c441e032 388
lixianyu 0:d8f4c441e032 389 /* assign evaluation value and store the move, if this is the best move */
lixianyu 0:d8f4c441e032 390 /* assumes, that current_pos contains the source position */
lixianyu 0:d8f4c441e032 391 void stack_SetMove(eval_t val, uint8_t to_pos)
lixianyu 0:d8f4c441e032 392 {
lixianyu 0:d8f4c441e032 393 stack_element_p e = stack_GetCurrElement();
lixianyu 0:d8f4c441e032 394 if ( e->best_eval < val )
lixianyu 0:d8f4c441e032 395 {
lixianyu 0:d8f4c441e032 396 e->best_eval = val;
lixianyu 0:d8f4c441e032 397 e->best_from_pos = e->current_pos;
lixianyu 0:d8f4c441e032 398 e->best_to_pos = to_pos;
lixianyu 0:d8f4c441e032 399 }
lixianyu 0:d8f4c441e032 400 }
lixianyu 0:d8f4c441e032 401
lixianyu 0:d8f4c441e032 402 /*
lixianyu 0:d8f4c441e032 403 calculate next position on a 0x88 board
lixianyu 0:d8f4c441e032 404 loop is constructed in this way:
lixianyu 0:d8f4c441e032 405 i = 0;
lixianyu 0:d8f4c441e032 406 do
lixianyu 0:d8f4c441e032 407 {
lixianyu 0:d8f4c441e032 408 ...
lixianyu 0:d8f4c441e032 409 i = cu_NextPos(i);
lixianyu 0:d8f4c441e032 410 } while( i != 0 );
lixianyu 0:d8f4c441e032 411
lixianyu 0:d8f4c441e032 412 next pos might be started with an illegal position like 255
lixianyu 0:d8f4c441e032 413 */
lixianyu 0:d8f4c441e032 414 uint8_t cu_NextPos(uint8_t pos)
lixianyu 0:d8f4c441e032 415 {
lixianyu 0:d8f4c441e032 416 /* calculate next gpos */
lixianyu 0:d8f4c441e032 417 pos++;
lixianyu 0:d8f4c441e032 418 if ( ( pos & 0x08 ) != 0 )
lixianyu 0:d8f4c441e032 419 {
lixianyu 0:d8f4c441e032 420 pos+= 0x10;
lixianyu 0:d8f4c441e032 421 pos&= 0xf0;
lixianyu 0:d8f4c441e032 422 }
lixianyu 0:d8f4c441e032 423 if ( ( pos & 0x80 ) != 0 )
lixianyu 0:d8f4c441e032 424 pos = 0;
lixianyu 0:d8f4c441e032 425 return pos;
lixianyu 0:d8f4c441e032 426 }
lixianyu 0:d8f4c441e032 427
lixianyu 0:d8f4c441e032 428 uint8_t cu_PrevPos(uint8_t pos)
lixianyu 0:d8f4c441e032 429 {
lixianyu 0:d8f4c441e032 430 /* calculate prev gpos */
lixianyu 0:d8f4c441e032 431 pos--;
lixianyu 0:d8f4c441e032 432 if ( ( pos & 0x80 ) != 0 )
lixianyu 0:d8f4c441e032 433 pos = 0x077;
lixianyu 0:d8f4c441e032 434 else if ( ( pos & 0x08 ) != 0 )
lixianyu 0:d8f4c441e032 435 {
lixianyu 0:d8f4c441e032 436 pos &= 0xf0;
lixianyu 0:d8f4c441e032 437 pos |= 0x07;
lixianyu 0:d8f4c441e032 438 }
lixianyu 0:d8f4c441e032 439 return pos;
lixianyu 0:d8f4c441e032 440 }
lixianyu 0:d8f4c441e032 441
lixianyu 0:d8f4c441e032 442
lixianyu 0:d8f4c441e032 443 /*==============================================================*/
lixianyu 0:d8f4c441e032 444 /* position transltion */
lixianyu 0:d8f4c441e032 445 /*==============================================================*/
lixianyu 0:d8f4c441e032 446 /*
lixianyu 0:d8f4c441e032 447 there are two positions
lixianyu 0:d8f4c441e032 448 1. game position (gpos): BCD encoded x-y values
lixianyu 0:d8f4c441e032 449 2. board position (bpos): a number between 0 and 63, only used to access the board.
lixianyu 0:d8f4c441e032 450 */
lixianyu 0:d8f4c441e032 451 /*
lixianyu 0:d8f4c441e032 452 gpos: game position value
lixianyu 0:d8f4c441e032 453 returns: board position
lixianyu 0:d8f4c441e032 454 note: does not do any checks
lixianyu 0:d8f4c441e032 455 */
lixianyu 0:d8f4c441e032 456 static uint8_t cu_gpos2bpos(uint8_t gpos)
lixianyu 0:d8f4c441e032 457 {
lixianyu 0:d8f4c441e032 458 uint8_t bpos = gpos;
lixianyu 0:d8f4c441e032 459 bpos &= 0xf0;
lixianyu 0:d8f4c441e032 460 bpos >>= 1;
lixianyu 0:d8f4c441e032 461 gpos &= 0x0f;
lixianyu 0:d8f4c441e032 462 bpos |= gpos;
lixianyu 0:d8f4c441e032 463 return bpos;
lixianyu 0:d8f4c441e032 464 }
lixianyu 0:d8f4c441e032 465
lixianyu 0:d8f4c441e032 466 #define gpos_IsIllegal(gpos) ((gpos) & 0x088)
lixianyu 0:d8f4c441e032 467
lixianyu 0:d8f4c441e032 468
lixianyu 0:d8f4c441e032 469 /*==============================================================*/
lixianyu 0:d8f4c441e032 470 /* colored piece handling */
lixianyu 0:d8f4c441e032 471 /*==============================================================*/
lixianyu 0:d8f4c441e032 472
lixianyu 0:d8f4c441e032 473 #define cp_IsMarked(cp) ((cp) & CP_MARK_MASK)
lixianyu 0:d8f4c441e032 474
lixianyu 0:d8f4c441e032 475
lixianyu 0:d8f4c441e032 476 /*
lixianyu 0:d8f4c441e032 477 piece: one of PIECE_xxx
lixianyu 0:d8f4c441e032 478 color: COLOR_WHITE or COLOR_BLACK
lixianyu 0:d8f4c441e032 479
lixianyu 0:d8f4c441e032 480 returns: A colored piece
lixianyu 0:d8f4c441e032 481 */
lixianyu 0:d8f4c441e032 482 static uint8_t cp_Construct(uint8_t color, uint8_t piece)
lixianyu 0:d8f4c441e032 483 {
lixianyu 0:d8f4c441e032 484 color <<= 4;
lixianyu 0:d8f4c441e032 485 color |= piece;
lixianyu 0:d8f4c441e032 486 return color;
lixianyu 0:d8f4c441e032 487 }
lixianyu 0:d8f4c441e032 488
lixianyu 0:d8f4c441e032 489 /* inline is better than a macro */
lixianyu 0:d8f4c441e032 490 static uint8_t cp_GetPiece(uint8_t cp)
lixianyu 0:d8f4c441e032 491 {
lixianyu 0:d8f4c441e032 492 cp &= 0x0f;
lixianyu 0:d8f4c441e032 493 return cp;
lixianyu 0:d8f4c441e032 494 }
lixianyu 0:d8f4c441e032 495
lixianyu 0:d8f4c441e032 496 /*
lixianyu 0:d8f4c441e032 497 we could use a macro:
lixianyu 0:d8f4c441e032 498 #define cp_GetColor(cp) (((cp) >> 4)&1)
lixianyu 0:d8f4c441e032 499 however, inlined functions are sometimes much better
lixianyu 0:d8f4c441e032 500 */
lixianyu 0:d8f4c441e032 501 static uint8_t cp_GetColor(uint8_t cp)
lixianyu 0:d8f4c441e032 502 {
lixianyu 0:d8f4c441e032 503 cp >>= 4;
lixianyu 0:d8f4c441e032 504 cp &= 1;
lixianyu 0:d8f4c441e032 505 return cp;
lixianyu 0:d8f4c441e032 506 }
lixianyu 0:d8f4c441e032 507
lixianyu 0:d8f4c441e032 508 /*
lixianyu 0:d8f4c441e032 509 pos: game position
lixianyu 0:d8f4c441e032 510 returns the colored piece at the given position
lixianyu 0:d8f4c441e032 511 */
lixianyu 0:d8f4c441e032 512 uint8_t cp_GetFromBoard(uint8_t pos)
lixianyu 0:d8f4c441e032 513 {
lixianyu 0:d8f4c441e032 514 return lrc_obj.board[cu_gpos2bpos(pos)];
lixianyu 0:d8f4c441e032 515 }
lixianyu 0:d8f4c441e032 516
lixianyu 0:d8f4c441e032 517 /*
lixianyu 0:d8f4c441e032 518 pos: game position
lixianyu 0:d8f4c441e032 519 cp: colored piece
lixianyu 0:d8f4c441e032 520 */
lixianyu 0:d8f4c441e032 521 void cp_SetOnBoard(uint8_t pos, uint8_t cp)
lixianyu 0:d8f4c441e032 522 {
lixianyu 0:d8f4c441e032 523 /*printf("cp_SetOnBoard gpos:%02x cp:%02x\n", pos, cp);*/
lixianyu 0:d8f4c441e032 524 lrc_obj.board[cu_gpos2bpos(pos)] = cp;
lixianyu 0:d8f4c441e032 525 }
lixianyu 0:d8f4c441e032 526
lixianyu 0:d8f4c441e032 527 /*==============================================================*/
lixianyu 0:d8f4c441e032 528 /* global board access */
lixianyu 0:d8f4c441e032 529 /*==============================================================*/
lixianyu 0:d8f4c441e032 530
lixianyu 0:d8f4c441e032 531 void cu_ClearBoard(void)
lixianyu 0:d8f4c441e032 532 {
lixianyu 0:d8f4c441e032 533 uint8_t i;
lixianyu 0:d8f4c441e032 534 /* clear the board */
lixianyu 0:d8f4c441e032 535 for( i = 0; i < 64; i++ )
lixianyu 0:d8f4c441e032 536 lrc_obj.board[i] = PIECE_NONE;
lixianyu 0:d8f4c441e032 537
lixianyu 0:d8f4c441e032 538 lrc_obj.ply_count = 0;
lixianyu 0:d8f4c441e032 539 lrc_obj.orientation = COLOR_WHITE;
lixianyu 0:d8f4c441e032 540
lixianyu 0:d8f4c441e032 541 lrc_obj.pawn_dbl_move[0] = ILLEGAL_POSITION;
lixianyu 0:d8f4c441e032 542 lrc_obj.pawn_dbl_move[1] = ILLEGAL_POSITION;
lixianyu 0:d8f4c441e032 543
lixianyu 0:d8f4c441e032 544 lrc_obj.castling_possible = 0x0f;
lixianyu 0:d8f4c441e032 545
lixianyu 0:d8f4c441e032 546 lrc_obj.is_game_end = 0;
lixianyu 0:d8f4c441e032 547 lrc_obj.lost_side_color = 0;
lixianyu 0:d8f4c441e032 548
lixianyu 0:d8f4c441e032 549 /* clear half move history */
lixianyu 0:d8f4c441e032 550 cu_ClearMoveHistory();
lixianyu 0:d8f4c441e032 551
lixianyu 0:d8f4c441e032 552 }
lixianyu 0:d8f4c441e032 553
lixianyu 0:d8f4c441e032 554 /*
lixianyu 0:d8f4c441e032 555 test setup
lixianyu 0:d8f4c441e032 556 white wins in one move
lixianyu 0:d8f4c441e032 557 */
lixianyu 0:d8f4c441e032 558 void chess_SetupBoardTest01(void)
lixianyu 0:d8f4c441e032 559 {
lixianyu 0:d8f4c441e032 560 cu_ClearBoard();
lixianyu 0:d8f4c441e032 561 lrc_obj.board[7+7*8] = cp_Construct(COLOR_BLACK, PIECE_KING);
lixianyu 0:d8f4c441e032 562 lrc_obj.board[7+5*8] = cp_Construct(COLOR_WHITE, PIECE_PAWN);
lixianyu 0:d8f4c441e032 563 lrc_obj.board[3] = cp_Construct(COLOR_WHITE, PIECE_KING);
lixianyu 0:d8f4c441e032 564 lrc_obj.board[0+7*8] = cp_Construct(COLOR_BLACK, PIECE_ROOK);
lixianyu 0:d8f4c441e032 565 lrc_obj.board[6] = cp_Construct(COLOR_WHITE, PIECE_QUEEN);
lixianyu 0:d8f4c441e032 566 }
lixianyu 0:d8f4c441e032 567
lixianyu 0:d8f4c441e032 568 /* setup the global board */
lixianyu 0:d8f4c441e032 569 void chess_SetupBoard(void)
lixianyu 0:d8f4c441e032 570 {
lixianyu 0:d8f4c441e032 571 uint8_t i;
lixianyu 0:d8f4c441e032 572 register uint8_t bp, wp;
lixianyu 0:d8f4c441e032 573
lixianyu 0:d8f4c441e032 574 /* clear the board */
lixianyu 0:d8f4c441e032 575 cu_ClearBoard();
lixianyu 0:d8f4c441e032 576
lixianyu 0:d8f4c441e032 577 /* precronstruct pawns */
lixianyu 0:d8f4c441e032 578 wp = cp_Construct(COLOR_WHITE, PIECE_PAWN);
lixianyu 0:d8f4c441e032 579 bp = cp_Construct(COLOR_BLACK, PIECE_PAWN);
lixianyu 0:d8f4c441e032 580
lixianyu 0:d8f4c441e032 581 /* setup pawn */
lixianyu 0:d8f4c441e032 582 for( i = 0; i < 8; i++ )
lixianyu 0:d8f4c441e032 583 {
lixianyu 0:d8f4c441e032 584 lrc_obj.board[i+8] = wp;
lixianyu 0:d8f4c441e032 585 lrc_obj.board[i+6*8] = bp;
lixianyu 0:d8f4c441e032 586 }
lixianyu 0:d8f4c441e032 587
lixianyu 0:d8f4c441e032 588 /* assign remaining pieces */
lixianyu 0:d8f4c441e032 589
lixianyu 0:d8f4c441e032 590 lrc_obj.board[0] = cp_Construct(COLOR_WHITE, PIECE_ROOK);
lixianyu 0:d8f4c441e032 591 lrc_obj.board[1] = cp_Construct(COLOR_WHITE, PIECE_KNIGHT);
lixianyu 0:d8f4c441e032 592 lrc_obj.board[2] = cp_Construct(COLOR_WHITE, PIECE_BISHOP);
lixianyu 0:d8f4c441e032 593 lrc_obj.board[3] = cp_Construct(COLOR_WHITE, PIECE_QUEEN);
lixianyu 0:d8f4c441e032 594 lrc_obj.board[4] = cp_Construct(COLOR_WHITE, PIECE_KING);
lixianyu 0:d8f4c441e032 595 lrc_obj.board[5] = cp_Construct(COLOR_WHITE, PIECE_BISHOP);
lixianyu 0:d8f4c441e032 596 lrc_obj.board[6] = cp_Construct(COLOR_WHITE, PIECE_KNIGHT);
lixianyu 0:d8f4c441e032 597 lrc_obj.board[7] = cp_Construct(COLOR_WHITE, PIECE_ROOK);
lixianyu 0:d8f4c441e032 598
lixianyu 0:d8f4c441e032 599 lrc_obj.board[0+7*8] = cp_Construct(COLOR_BLACK, PIECE_ROOK);
lixianyu 0:d8f4c441e032 600 lrc_obj.board[1+7*8] = cp_Construct(COLOR_BLACK, PIECE_KNIGHT);
lixianyu 0:d8f4c441e032 601 lrc_obj.board[2+7*8] = cp_Construct(COLOR_BLACK, PIECE_BISHOP);
lixianyu 0:d8f4c441e032 602 lrc_obj.board[3+7*8] = cp_Construct(COLOR_BLACK, PIECE_QUEEN);
lixianyu 0:d8f4c441e032 603 lrc_obj.board[4+7*8] = cp_Construct(COLOR_BLACK, PIECE_KING);
lixianyu 0:d8f4c441e032 604 lrc_obj.board[5+7*8] = cp_Construct(COLOR_BLACK, PIECE_BISHOP);
lixianyu 0:d8f4c441e032 605 lrc_obj.board[6+7*8] = cp_Construct(COLOR_BLACK, PIECE_KNIGHT);
lixianyu 0:d8f4c441e032 606 lrc_obj.board[7+7*8] = cp_Construct(COLOR_BLACK, PIECE_ROOK);
lixianyu 0:d8f4c441e032 607
lixianyu 0:d8f4c441e032 608 //chess_SetupBoardTest01();
lixianyu 0:d8f4c441e032 609
lixianyu 0:d8f4c441e032 610 }
lixianyu 0:d8f4c441e032 611
lixianyu 0:d8f4c441e032 612
lixianyu 0:d8f4c441e032 613
lixianyu 0:d8f4c441e032 614 /*==============================================================*/
lixianyu 0:d8f4c441e032 615 /* checks */
lixianyu 0:d8f4c441e032 616 /*==============================================================*/
lixianyu 0:d8f4c441e032 617
lixianyu 0:d8f4c441e032 618 /*
lixianyu 0:d8f4c441e032 619 checks if the position is somehow illegal
lixianyu 0:d8f4c441e032 620 */
lixianyu 0:d8f4c441e032 621 uint8_t cu_IsIllegalPosition(uint8_t pos, uint8_t my_color)
lixianyu 0:d8f4c441e032 622 {
lixianyu 0:d8f4c441e032 623 uint8_t board_cp;
lixianyu 0:d8f4c441e032 624 /* check, if the position is offboard */
lixianyu 0:d8f4c441e032 625 if ( gpos_IsIllegal(pos) != 0 )
lixianyu 0:d8f4c441e032 626 return 1;
lixianyu 0:d8f4c441e032 627 /* get the piece from the board */
lixianyu 0:d8f4c441e032 628 board_cp = cp_GetFromBoard(pos);
lixianyu 0:d8f4c441e032 629 /* check if hit our own pieces */
lixianyu 0:d8f4c441e032 630 if ( board_cp != 0 )
lixianyu 0:d8f4c441e032 631 if ( cp_GetColor(board_cp) == my_color )
lixianyu 0:d8f4c441e032 632 return 1;
lixianyu 0:d8f4c441e032 633 /* all ok, we could go to this position */
lixianyu 0:d8f4c441e032 634 return 0;
lixianyu 0:d8f4c441e032 635 }
lixianyu 0:d8f4c441e032 636
lixianyu 0:d8f4c441e032 637 /*==============================================================*/
lixianyu 0:d8f4c441e032 638 /* evaluation procedure */
lixianyu 0:d8f4c441e032 639 /*==============================================================*/
lixianyu 0:d8f4c441e032 640
lixianyu 0:d8f4c441e032 641 /*
lixianyu 0:d8f4c441e032 642 basic idea is to return a value between EVAL_T_MIN and EVAL_T_MAX
lixianyu 0:d8f4c441e032 643 */
lixianyu 0:d8f4c441e032 644
lixianyu 0:d8f4c441e032 645 /*
lixianyu 0:d8f4c441e032 646 the weight table uses the PIECE number as index:
lixianyu 0:d8f4c441e032 647 #define PIECE_NONE 0
lixianyu 0:d8f4c441e032 648 #define PIECE_PAWN 1
lixianyu 0:d8f4c441e032 649 #define PIECE_KNIGHT 2
lixianyu 0:d8f4c441e032 650 #define PIECE_BISHOP 3
lixianyu 0:d8f4c441e032 651 #define PIECE_ROOK 4
lixianyu 0:d8f4c441e032 652 #define PIECE_QUEEN 5
lixianyu 0:d8f4c441e032 653 #define PIECE_KING 6
lixianyu 0:d8f4c441e032 654 the king itself is not counted
lixianyu 0:d8f4c441e032 655 */
lixianyu 0:d8f4c441e032 656 uint8_t ce_piece_weight[] = { 0, 1, 3, 3, 5, 9, 0 };
lixianyu 0:d8f4c441e032 657 uint8_t ce_pos_weight[] = { 0, 1, 1, 2, 2, 1, 1, 0};
lixianyu 0:d8f4c441e032 658 /*
lixianyu 0:d8f4c441e032 659 evaluate the current situation on the global board
lixianyu 0:d8f4c441e032 660 */
lixianyu 0:d8f4c441e032 661 eval_t ce_Eval(void)
lixianyu 0:d8f4c441e032 662 {
lixianyu 0:d8f4c441e032 663 uint8_t cp;
lixianyu 0:d8f4c441e032 664 uint8_t is_my_king_present = 0;
lixianyu 0:d8f4c441e032 665 uint8_t is_opposit_king_present = 0;
lixianyu 0:d8f4c441e032 666 eval_t material_my_color = 0;
lixianyu 0:d8f4c441e032 667 eval_t material_opposit_color = 0;
lixianyu 0:d8f4c441e032 668 eval_t position_my_color = 0;
lixianyu 0:d8f4c441e032 669 eval_t position_opposit_color = 0;
lixianyu 0:d8f4c441e032 670 eval_t result;
lixianyu 0:d8f4c441e032 671 uint8_t pos;
lixianyu 0:d8f4c441e032 672
lixianyu 0:d8f4c441e032 673 pos = 0;
lixianyu 0:d8f4c441e032 674 do
lixianyu 0:d8f4c441e032 675 {
lixianyu 0:d8f4c441e032 676 /* get colored piece from the board */
lixianyu 0:d8f4c441e032 677 cp = cp_GetFromBoard(pos);
lixianyu 0:d8f4c441e032 678
lixianyu 0:d8f4c441e032 679 if ( cp_GetPiece(cp) != PIECE_NONE )
lixianyu 0:d8f4c441e032 680 {
lixianyu 0:d8f4c441e032 681 if ( stack_GetCurrElement()->current_color == cp_GetColor(cp) )
lixianyu 0:d8f4c441e032 682 {
lixianyu 0:d8f4c441e032 683 /* this is our color */
lixianyu 0:d8f4c441e032 684 /* check if we found our king */
lixianyu 0:d8f4c441e032 685 if ( cp_GetPiece(cp) == PIECE_KING )
lixianyu 0:d8f4c441e032 686 is_my_king_present = 1;
lixianyu 0:d8f4c441e032 687 material_my_color += ce_piece_weight[cp_GetPiece(cp)];
lixianyu 0:d8f4c441e032 688 if ( cp_GetPiece(cp) == PIECE_PAWN || cp_GetPiece(cp) == PIECE_KNIGHT )
lixianyu 0:d8f4c441e032 689 {
lixianyu 0:d8f4c441e032 690 position_my_color += ce_pos_weight[pos&7]*ce_pos_weight[(pos>>4)&7];
lixianyu 0:d8f4c441e032 691 }
lixianyu 0:d8f4c441e032 692 }
lixianyu 0:d8f4c441e032 693 else
lixianyu 0:d8f4c441e032 694 {
lixianyu 0:d8f4c441e032 695 /* this is the opposit color */
lixianyu 0:d8f4c441e032 696 if ( cp_GetPiece(cp) == PIECE_KING )
lixianyu 0:d8f4c441e032 697 is_opposit_king_present = 1;
lixianyu 0:d8f4c441e032 698 material_opposit_color += ce_piece_weight[cp_GetPiece(cp)];
lixianyu 0:d8f4c441e032 699 if ( cp_GetPiece(cp) == PIECE_PAWN || cp_GetPiece(cp) == PIECE_KNIGHT )
lixianyu 0:d8f4c441e032 700 {
lixianyu 0:d8f4c441e032 701 position_opposit_color += ce_pos_weight[pos&7]*ce_pos_weight[(pos>>4)&7];
lixianyu 0:d8f4c441e032 702 }
lixianyu 0:d8f4c441e032 703 }
lixianyu 0:d8f4c441e032 704 }
lixianyu 0:d8f4c441e032 705 pos = cu_NextPos(pos);
lixianyu 0:d8f4c441e032 706 } while( pos != 0 );
lixianyu 0:d8f4c441e032 707
lixianyu 0:d8f4c441e032 708
lixianyu 0:d8f4c441e032 709 /* decide if we lost or won the game */
lixianyu 0:d8f4c441e032 710 if ( is_my_king_present == 0 )
lixianyu 0:d8f4c441e032 711 return EVAL_T_MIN; /*_LOST*/
lixianyu 0:d8f4c441e032 712 if ( is_opposit_king_present == 0 )
lixianyu 0:d8f4c441e032 713 return EVAL_T_MAX; /*_WIN*/
lixianyu 0:d8f4c441e032 714
lixianyu 0:d8f4c441e032 715 /* here is the evaluation function */
lixianyu 0:d8f4c441e032 716
lixianyu 0:d8f4c441e032 717 result = material_my_color - material_opposit_color;
lixianyu 0:d8f4c441e032 718 result <<= 3;
lixianyu 0:d8f4c441e032 719 result += position_my_color - position_opposit_color;
lixianyu 0:d8f4c441e032 720 return result;
lixianyu 0:d8f4c441e032 721 }
lixianyu 0:d8f4c441e032 722
lixianyu 0:d8f4c441e032 723 /*==============================================================*/
lixianyu 0:d8f4c441e032 724 /* move backup and restore */
lixianyu 0:d8f4c441e032 725 /*==============================================================*/
lixianyu 0:d8f4c441e032 726
lixianyu 0:d8f4c441e032 727
lixianyu 0:d8f4c441e032 728 /* this procedure must be called to keep the size as low as possible */
lixianyu 0:d8f4c441e032 729 /* if the chm_list is large enough, it could hold the complete history */
lixianyu 0:d8f4c441e032 730 /* but for an embedded controler... it is deleted for every engine search */
lixianyu 0:d8f4c441e032 731 void cu_ClearMoveHistory(void)
lixianyu 0:d8f4c441e032 732 {
lixianyu 0:d8f4c441e032 733 lrc_obj.chm_pos = 0;
lixianyu 0:d8f4c441e032 734 }
lixianyu 0:d8f4c441e032 735
lixianyu 0:d8f4c441e032 736 void cu_ReduceHistoryByFullMove(void)
lixianyu 0:d8f4c441e032 737 {
lixianyu 0:d8f4c441e032 738 uint8_t i;
lixianyu 0:d8f4c441e032 739 while( lrc_obj.chm_pos > CHM_USER_SIZE )
lixianyu 0:d8f4c441e032 740 {
lixianyu 0:d8f4c441e032 741 i = 0;
lixianyu 0:d8f4c441e032 742 for(;;)
lixianyu 0:d8f4c441e032 743 {
lixianyu 0:d8f4c441e032 744 if ( i+2 >= lrc_obj.chm_pos )
lixianyu 0:d8f4c441e032 745 break;
lixianyu 0:d8f4c441e032 746 lrc_obj.chm_list[i] = lrc_obj.chm_list[i+2];
lixianyu 0:d8f4c441e032 747 i++;
lixianyu 0:d8f4c441e032 748 }
lixianyu 0:d8f4c441e032 749 lrc_obj.chm_pos -= 2;
lixianyu 0:d8f4c441e032 750 }
lixianyu 0:d8f4c441e032 751 }
lixianyu 0:d8f4c441e032 752
lixianyu 0:d8f4c441e032 753 void cu_UndoHalfMove(void)
lixianyu 0:d8f4c441e032 754 {
lixianyu 0:d8f4c441e032 755 chm_p chm;
lixianyu 0:d8f4c441e032 756
lixianyu 0:d8f4c441e032 757 if ( lrc_obj.chm_pos == 0 )
lixianyu 0:d8f4c441e032 758 return;
lixianyu 0:d8f4c441e032 759
lixianyu 0:d8f4c441e032 760 lrc_obj.chm_pos--;
lixianyu 0:d8f4c441e032 761
lixianyu 0:d8f4c441e032 762 chm = lrc_obj.chm_list+lrc_obj.chm_pos;
lixianyu 0:d8f4c441e032 763
lixianyu 0:d8f4c441e032 764 lrc_obj.pawn_dbl_move[0] = chm->pawn_dbl_move[0];
lixianyu 0:d8f4c441e032 765 lrc_obj.pawn_dbl_move[1] = chm->pawn_dbl_move[1];
lixianyu 0:d8f4c441e032 766 lrc_obj.castling_possible = chm->castling_possible;
lixianyu 0:d8f4c441e032 767
lixianyu 0:d8f4c441e032 768 cp_SetOnBoard(chm->main_src, chm->main_cp);
lixianyu 0:d8f4c441e032 769 cp_SetOnBoard(chm->main_dest, PIECE_NONE);
lixianyu 0:d8f4c441e032 770
lixianyu 0:d8f4c441e032 771 if ( chm->other_src != ILLEGAL_POSITION )
lixianyu 0:d8f4c441e032 772 cp_SetOnBoard(chm->other_src, chm->other_cp);
lixianyu 0:d8f4c441e032 773 if ( chm->other_dest != ILLEGAL_POSITION )
lixianyu 0:d8f4c441e032 774 cp_SetOnBoard(chm->other_dest, PIECE_NONE);
lixianyu 0:d8f4c441e032 775
lixianyu 0:d8f4c441e032 776 }
lixianyu 0:d8f4c441e032 777
lixianyu 0:d8f4c441e032 778 /*
lixianyu 0:d8f4c441e032 779 assumes, that the following members of the returned chm structure are filled
lixianyu 0:d8f4c441e032 780 uint8_t main_cp; the main piece, which is moved
lixianyu 0:d8f4c441e032 781 uint8_t main_src; the source position of the main piece
lixianyu 0:d8f4c441e032 782 uint8_t main_dest; the destination of the main piece
lixianyu 0:d8f4c441e032 783
lixianyu 0:d8f4c441e032 784 uint8_t other_cp; another piece: the captured one, the ROOK in case of castling or PIECE_NONE
lixianyu 0:d8f4c441e032 785 uint8_t other_src; the delete position of other_cp. Often identical to main_dest except for e.p. and castling
lixianyu 0:d8f4c441e032 786 uint8_t other_dest; only used for castling: ROOK destination pos
lixianyu 0:d8f4c441e032 787
lixianyu 0:d8f4c441e032 788 */
lixianyu 0:d8f4c441e032 789 chm_p cu_PushHalfMove(void)
lixianyu 0:d8f4c441e032 790 {
lixianyu 0:d8f4c441e032 791 chm_p chm;
lixianyu 0:d8f4c441e032 792
lixianyu 0:d8f4c441e032 793 chm = lrc_obj.chm_list+lrc_obj.chm_pos;
lixianyu 0:d8f4c441e032 794 if ( lrc_obj.chm_pos < CHM_LIST_SIZE-1)
lixianyu 0:d8f4c441e032 795 lrc_obj.chm_pos++;
lixianyu 0:d8f4c441e032 796
lixianyu 0:d8f4c441e032 797 chm->pawn_dbl_move[0] = lrc_obj.pawn_dbl_move[0];
lixianyu 0:d8f4c441e032 798 chm->pawn_dbl_move[1] = lrc_obj.pawn_dbl_move[1];
lixianyu 0:d8f4c441e032 799 chm->castling_possible = lrc_obj.castling_possible;
lixianyu 0:d8f4c441e032 800 return chm;
lixianyu 0:d8f4c441e032 801 }
lixianyu 0:d8f4c441e032 802
lixianyu 0:d8f4c441e032 803
lixianyu 0:d8f4c441e032 804 char chess_piece_to_char[] = "NBRQK";
lixianyu 0:d8f4c441e032 805
lixianyu 0:d8f4c441e032 806 /*
lixianyu 0:d8f4c441e032 807 simple moves on empty field: Ka1-b2
lixianyu 0:d8f4c441e032 808 capture moves: Ka1xb2
lixianyu 0:d8f4c441e032 809 castling: 0-0 or 0-0-0
lixianyu 0:d8f4c441e032 810 */
lixianyu 0:d8f4c441e032 811
lixianyu 0:d8f4c441e032 812 static void cu_add_pos(char *s, uint8_t pos) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 813
lixianyu 0:d8f4c441e032 814 static void cu_add_pos(char *s, uint8_t pos)
lixianyu 0:d8f4c441e032 815 {
lixianyu 0:d8f4c441e032 816 *s = pos;
lixianyu 0:d8f4c441e032 817 *s >>= 4;
lixianyu 0:d8f4c441e032 818 *s += 'a';
lixianyu 0:d8f4c441e032 819 s++;
lixianyu 0:d8f4c441e032 820 *s = pos;
lixianyu 0:d8f4c441e032 821 *s &= 15;
lixianyu 0:d8f4c441e032 822 *s += '1';
lixianyu 0:d8f4c441e032 823 }
lixianyu 0:d8f4c441e032 824
lixianyu 0:d8f4c441e032 825 const char *cu_GetHalfMoveStr(uint8_t idx)
lixianyu 0:d8f4c441e032 826 {
lixianyu 0:d8f4c441e032 827 chm_p chm;
lixianyu 0:d8f4c441e032 828 static char buf[7]; /*Ka1-b2*/
lixianyu 0:d8f4c441e032 829 char *p = buf;
lixianyu 0:d8f4c441e032 830 chm = lrc_obj.chm_list+idx;
lixianyu 0:d8f4c441e032 831
lixianyu 0:d8f4c441e032 832 if ( cp_GetPiece(chm->main_cp) != PIECE_NONE )
lixianyu 0:d8f4c441e032 833 {
lixianyu 0:d8f4c441e032 834 if ( cp_GetPiece(chm->main_cp) > PIECE_PAWN )
lixianyu 0:d8f4c441e032 835 {
lixianyu 0:d8f4c441e032 836 *p++ = chess_piece_to_char[cp_GetPiece(chm->main_cp)-2];
lixianyu 0:d8f4c441e032 837 }
lixianyu 0:d8f4c441e032 838 cu_add_pos(p, chm->main_src);
lixianyu 0:d8f4c441e032 839 p+=2;
lixianyu 0:d8f4c441e032 840 if ( cp_GetPiece(chm->other_cp) == PIECE_NONE )
lixianyu 0:d8f4c441e032 841 *p++ = '-';
lixianyu 0:d8f4c441e032 842 else
lixianyu 0:d8f4c441e032 843 *p++ = 'x';
lixianyu 0:d8f4c441e032 844 cu_add_pos(p, chm->main_dest);
lixianyu 0:d8f4c441e032 845 p+=2;
lixianyu 0:d8f4c441e032 846 }
lixianyu 0:d8f4c441e032 847 *p = '\0';
lixianyu 0:d8f4c441e032 848 return buf;
lixianyu 0:d8f4c441e032 849 }
lixianyu 0:d8f4c441e032 850
lixianyu 0:d8f4c441e032 851
lixianyu 0:d8f4c441e032 852
lixianyu 0:d8f4c441e032 853
lixianyu 0:d8f4c441e032 854
lixianyu 0:d8f4c441e032 855 /*==============================================================*/
lixianyu 0:d8f4c441e032 856 /* move */
lixianyu 0:d8f4c441e032 857 /*==============================================================*/
lixianyu 0:d8f4c441e032 858
lixianyu 0:d8f4c441e032 859 /*
lixianyu 0:d8f4c441e032 860 Move a piece from source position to a destination on the board
lixianyu 0:d8f4c441e032 861 This function
lixianyu 0:d8f4c441e032 862 - does not perform any checking
lixianyu 0:d8f4c441e032 863 - however it processes "en passant" and casteling
lixianyu 0:d8f4c441e032 864 - backup the move and allow 1x undo
lixianyu 0:d8f4c441e032 865
lixianyu 0:d8f4c441e032 866 2011-02-05:
lixianyu 0:d8f4c441e032 867 - fill pawn_dbl_move[] for double pawn moves
lixianyu 0:d8f4c441e032 868 --> done
lixianyu 0:d8f4c441e032 869 - Implement casteling
lixianyu 0:d8f4c441e032 870 --> done
lixianyu 0:d8f4c441e032 871 - en passant
lixianyu 0:d8f4c441e032 872 --> done
lixianyu 0:d8f4c441e032 873 - pawn conversion/promotion
lixianyu 0:d8f4c441e032 874 --> done
lixianyu 0:d8f4c441e032 875 - half-move backup
lixianyu 0:d8f4c441e032 876 --> done
lixianyu 0:d8f4c441e032 877 - cleanup everything, minimize variables
lixianyu 0:d8f4c441e032 878 --> done
lixianyu 0:d8f4c441e032 879 */
lixianyu 0:d8f4c441e032 880
lixianyu 0:d8f4c441e032 881 void cu_Move(uint8_t src, uint8_t dest)
lixianyu 0:d8f4c441e032 882 {
lixianyu 0:d8f4c441e032 883 /* start backup structure */
lixianyu 0:d8f4c441e032 884 chm_p chm = cu_PushHalfMove();
lixianyu 0:d8f4c441e032 885
lixianyu 0:d8f4c441e032 886 /* these are the values from the board at the positions, provided as arguments to this function */
lixianyu 0:d8f4c441e032 887 uint8_t cp_src, cp_dest;
lixianyu 0:d8f4c441e032 888
lixianyu 0:d8f4c441e032 889 /* Maybe a second position is cleared and one additional location is set */
lixianyu 0:d8f4c441e032 890 uint8_t clr_pos2;
lixianyu 0:d8f4c441e032 891 uint8_t set_pos2;
lixianyu 0:d8f4c441e032 892 uint8_t set_cp2;
lixianyu 0:d8f4c441e032 893
lixianyu 0:d8f4c441e032 894 /* get values from board */
lixianyu 0:d8f4c441e032 895 cp_src = cp_GetFromBoard(src);
lixianyu 0:d8f4c441e032 896 cp_dest = cp_GetFromBoard(dest);
lixianyu 0:d8f4c441e032 897
lixianyu 0:d8f4c441e032 898 /* fill backup structure */
lixianyu 0:d8f4c441e032 899
lixianyu 0:d8f4c441e032 900 chm->main_cp = cp_src;
lixianyu 0:d8f4c441e032 901 chm->main_src = src;
lixianyu 0:d8f4c441e032 902 chm->main_dest = dest;
lixianyu 0:d8f4c441e032 903
lixianyu 0:d8f4c441e032 904 chm->other_cp = cp_dest; /* prepace capture backup */
lixianyu 0:d8f4c441e032 905 chm->other_src = dest;
lixianyu 0:d8f4c441e032 906 chm->other_dest = ILLEGAL_POSITION;
lixianyu 0:d8f4c441e032 907
lixianyu 0:d8f4c441e032 908 /* setup results as far as possible with some suitable values */
lixianyu 0:d8f4c441e032 909
lixianyu 0:d8f4c441e032 910 clr_pos2 = ILLEGAL_POSITION; /* for en passant and castling, two positions might be cleared */
lixianyu 0:d8f4c441e032 911 set_pos2 = ILLEGAL_POSITION; /* only used for castling */
lixianyu 0:d8f4c441e032 912 set_cp2 = PIECE_NONE; /* ROOK for castling */
lixianyu 0:d8f4c441e032 913
lixianyu 0:d8f4c441e032 914 /* check for PAWN */
lixianyu 0:d8f4c441e032 915 if ( cp_GetPiece(cp_src) == PIECE_PAWN )
lixianyu 0:d8f4c441e032 916 {
lixianyu 0:d8f4c441e032 917
lixianyu 0:d8f4c441e032 918 /* double step: is the distance 2 rows */
lixianyu 0:d8f4c441e032 919 if ( (src - dest == 32) || ( dest - src == 32 ) )
lixianyu 0:d8f4c441e032 920 {
lixianyu 0:d8f4c441e032 921 /* remember the destination position */
lixianyu 0:d8f4c441e032 922 lrc_obj.pawn_dbl_move[cp_GetColor(cp_src)] = dest;
lixianyu 0:d8f4c441e032 923 }
lixianyu 0:d8f4c441e032 924
lixianyu 0:d8f4c441e032 925 /* check if the PAWN is able to promote */
lixianyu 0:d8f4c441e032 926 else if ( (dest>>4) == 0 || (dest>>4) == 7 )
lixianyu 0:d8f4c441e032 927 {
lixianyu 0:d8f4c441e032 928 /* do simple "queening" */
lixianyu 0:d8f4c441e032 929 cp_src &= ~PIECE_PAWN;
lixianyu 0:d8f4c441e032 930 cp_src |= PIECE_QUEEN;
lixianyu 0:d8f4c441e032 931 }
lixianyu 0:d8f4c441e032 932
lixianyu 0:d8f4c441e032 933 /* is it en passant capture? */
lixianyu 0:d8f4c441e032 934 /* check for side move */
lixianyu 0:d8f4c441e032 935 else if ( ((src + dest) & 1) != 0 )
lixianyu 0:d8f4c441e032 936 {
lixianyu 0:d8f4c441e032 937 /* check, if target field is empty */
lixianyu 0:d8f4c441e032 938 if ( cp_GetPiece(cp_dest) == PIECE_NONE )
lixianyu 0:d8f4c441e032 939 {
lixianyu 0:d8f4c441e032 940 /* this is en passant */
lixianyu 0:d8f4c441e032 941 /* no further checking required, because legal moves are assumed here */
lixianyu 0:d8f4c441e032 942 /* however... the captured pawn position must be valid */
lixianyu 0:d8f4c441e032 943 clr_pos2 = lrc_obj.pawn_dbl_move[cp_GetColor(cp_src) ^ 1];
lixianyu 0:d8f4c441e032 944 chm->other_src = clr_pos2;
lixianyu 0:d8f4c441e032 945 chm->other_cp = cp_GetFromBoard(clr_pos2);
lixianyu 0:d8f4c441e032 946 }
lixianyu 0:d8f4c441e032 947 }
lixianyu 0:d8f4c441e032 948 }
lixianyu 0:d8f4c441e032 949
lixianyu 0:d8f4c441e032 950 /* check for the KING */
lixianyu 0:d8f4c441e032 951 else if ( cp_GetPiece(cp_src) == PIECE_KING )
lixianyu 0:d8f4c441e032 952 {
lixianyu 0:d8f4c441e032 953 /* disallow castling, if the KING has moved */
lixianyu 0:d8f4c441e032 954 if ( cp_GetColor(cp_src) == COLOR_WHITE )
lixianyu 0:d8f4c441e032 955 {
lixianyu 0:d8f4c441e032 956 /* if white KING has moved, disallow castling for white */
lixianyu 0:d8f4c441e032 957 lrc_obj.castling_possible &= 0x0c;
lixianyu 0:d8f4c441e032 958 }
lixianyu 0:d8f4c441e032 959 else
lixianyu 0:d8f4c441e032 960 {
lixianyu 0:d8f4c441e032 961 /* if black KING has moved, disallow castling for black */
lixianyu 0:d8f4c441e032 962 lrc_obj.castling_possible &= 0x03;
lixianyu 0:d8f4c441e032 963 }
lixianyu 0:d8f4c441e032 964
lixianyu 0:d8f4c441e032 965 /* has it been castling to the left? */
lixianyu 0:d8f4c441e032 966 if ( src - dest == 2 )
lixianyu 0:d8f4c441e032 967 {
lixianyu 0:d8f4c441e032 968 /* let the ROOK move to pos2 */
lixianyu 0:d8f4c441e032 969 set_pos2 = src-1;
lixianyu 0:d8f4c441e032 970 set_cp2 = cp_GetFromBoard(src-4);
lixianyu 0:d8f4c441e032 971
lixianyu 0:d8f4c441e032 972 /* the ROOK must be cleared from the original position */
lixianyu 0:d8f4c441e032 973 clr_pos2 = src-4;
lixianyu 0:d8f4c441e032 974
lixianyu 0:d8f4c441e032 975 chm->other_cp = set_cp2;
lixianyu 0:d8f4c441e032 976 chm->other_src = clr_pos2;
lixianyu 0:d8f4c441e032 977 chm->other_dest = set_pos2;
lixianyu 0:d8f4c441e032 978 }
lixianyu 0:d8f4c441e032 979
lixianyu 0:d8f4c441e032 980 /* has it been castling to the right? */
lixianyu 0:d8f4c441e032 981 else if ( dest - src == 2 )
lixianyu 0:d8f4c441e032 982 {
lixianyu 0:d8f4c441e032 983 /* let the ROOK move to pos2 */
lixianyu 0:d8f4c441e032 984 set_pos2 = src+1;
lixianyu 0:d8f4c441e032 985 set_cp2 = cp_GetFromBoard(src+3);
lixianyu 0:d8f4c441e032 986
lixianyu 0:d8f4c441e032 987 /* the ROOK must be cleared from the original position */
lixianyu 0:d8f4c441e032 988 clr_pos2 = src+3;
lixianyu 0:d8f4c441e032 989
lixianyu 0:d8f4c441e032 990 chm->other_cp = set_cp2;
lixianyu 0:d8f4c441e032 991 chm->other_src = clr_pos2;
lixianyu 0:d8f4c441e032 992 chm->other_dest = set_pos2;
lixianyu 0:d8f4c441e032 993
lixianyu 0:d8f4c441e032 994 }
lixianyu 0:d8f4c441e032 995
lixianyu 0:d8f4c441e032 996 }
lixianyu 0:d8f4c441e032 997
lixianyu 0:d8f4c441e032 998 /* check for the ROOK */
lixianyu 0:d8f4c441e032 999 else if ( cp_GetPiece(cp_src) == PIECE_ROOK )
lixianyu 0:d8f4c441e032 1000 {
lixianyu 0:d8f4c441e032 1001 /* disallow white left castling */
lixianyu 0:d8f4c441e032 1002 if ( src == 0x00 )
lixianyu 0:d8f4c441e032 1003 lrc_obj.castling_possible &= ~0x01;
lixianyu 0:d8f4c441e032 1004 /* disallow white right castling */
lixianyu 0:d8f4c441e032 1005 if ( src == 0x07 )
lixianyu 0:d8f4c441e032 1006 lrc_obj.castling_possible &= ~0x02;
lixianyu 0:d8f4c441e032 1007 /* disallow black left castling */
lixianyu 0:d8f4c441e032 1008 if ( src == 0x70 )
lixianyu 0:d8f4c441e032 1009 lrc_obj.castling_possible &= ~0x04;
lixianyu 0:d8f4c441e032 1010 /* disallow black right castling */
lixianyu 0:d8f4c441e032 1011 if ( src == 0x77 )
lixianyu 0:d8f4c441e032 1012 lrc_obj.castling_possible &= ~0x08;
lixianyu 0:d8f4c441e032 1013 }
lixianyu 0:d8f4c441e032 1014
lixianyu 0:d8f4c441e032 1015
lixianyu 0:d8f4c441e032 1016 /* apply new board situation */
lixianyu 0:d8f4c441e032 1017
lixianyu 0:d8f4c441e032 1018 cp_SetOnBoard(dest, cp_src);
lixianyu 0:d8f4c441e032 1019
lixianyu 0:d8f4c441e032 1020 if ( set_pos2 != ILLEGAL_POSITION )
lixianyu 0:d8f4c441e032 1021 cp_SetOnBoard(set_pos2, set_cp2);
lixianyu 0:d8f4c441e032 1022
lixianyu 0:d8f4c441e032 1023 cp_SetOnBoard(src, PIECE_NONE);
lixianyu 0:d8f4c441e032 1024
lixianyu 0:d8f4c441e032 1025 if ( clr_pos2 != ILLEGAL_POSITION )
lixianyu 0:d8f4c441e032 1026 cp_SetOnBoard(clr_pos2, PIECE_NONE);
lixianyu 0:d8f4c441e032 1027
lixianyu 0:d8f4c441e032 1028
lixianyu 0:d8f4c441e032 1029 }
lixianyu 0:d8f4c441e032 1030
lixianyu 0:d8f4c441e032 1031 /*
lixianyu 0:d8f4c441e032 1032 this subprocedure decides for evaluation of the current board situation or further (deeper) investigation
lixianyu 0:d8f4c441e032 1033 Argument pos is the new target position if the current piece
lixianyu 0:d8f4c441e032 1034
lixianyu 0:d8f4c441e032 1035 */
lixianyu 0:d8f4c441e032 1036 uint8_t ce_LoopRecur(uint8_t pos)
lixianyu 0:d8f4c441e032 1037 {
lixianyu 0:d8f4c441e032 1038 eval_t eval;
lixianyu 0:d8f4c441e032 1039
lixianyu 0:d8f4c441e032 1040 /* 1. check if target position is occupied by the same player (my_color) */
lixianyu 0:d8f4c441e032 1041 /* of if pos is somehow illegal or not valid */
lixianyu 0:d8f4c441e032 1042 if ( cu_IsIllegalPosition(pos, stack_GetCurrElement()->current_color) != 0 )
lixianyu 0:d8f4c441e032 1043 return 0;
lixianyu 0:d8f4c441e032 1044
lixianyu 0:d8f4c441e032 1045 /* 2. move piece to the specified position, capture opponent piece if required */
lixianyu 0:d8f4c441e032 1046 cu_Move(stack_GetCurrElement()->current_pos, pos);
lixianyu 0:d8f4c441e032 1047
lixianyu 0:d8f4c441e032 1048
lixianyu 0:d8f4c441e032 1049 /* 3. */
lixianyu 0:d8f4c441e032 1050 /* if depth reached: evaluate */
lixianyu 0:d8f4c441e032 1051 /* else: go down next level */
lixianyu 0:d8f4c441e032 1052 /* no eval if there had been any valid half-moves, so the default value (MIN) will be returned. */
lixianyu 0:d8f4c441e032 1053 if ( stack_Push(stack_GetCurrElement()->current_color) == 0 )
lixianyu 0:d8f4c441e032 1054 {
lixianyu 0:d8f4c441e032 1055 eval = ce_Eval();
lixianyu 0:d8f4c441e032 1056 }
lixianyu 0:d8f4c441e032 1057 else
lixianyu 0:d8f4c441e032 1058 {
lixianyu 0:d8f4c441e032 1059 /* init the element, which has been pushed */
lixianyu 0:d8f4c441e032 1060 stack_InitCurrElement();
lixianyu 0:d8f4c441e032 1061 /* start over with ntext level */
lixianyu 0:d8f4c441e032 1062 ce_LoopPieces();
lixianyu 0:d8f4c441e032 1063 /* get the best move from opponents view, so invert the result */
lixianyu 0:d8f4c441e032 1064 eval = -stack_GetCurrElement()->best_eval;
lixianyu 0:d8f4c441e032 1065 stack_Pop();
lixianyu 0:d8f4c441e032 1066 }
lixianyu 0:d8f4c441e032 1067
lixianyu 0:d8f4c441e032 1068 /* 4. store result */
lixianyu 0:d8f4c441e032 1069 stack_SetMove(eval, pos);
lixianyu 0:d8f4c441e032 1070
lixianyu 0:d8f4c441e032 1071 /* 5. undo the move */
lixianyu 0:d8f4c441e032 1072 cu_UndoHalfMove();
lixianyu 0:d8f4c441e032 1073
lixianyu 0:d8f4c441e032 1074 /* 6. check special modes */
lixianyu 0:d8f4c441e032 1075 /* the purpose of these checks is to mark special pieces and positions on the board */
lixianyu 0:d8f4c441e032 1076 /* these marks can be checked by the user interface to highlight special positions */
lixianyu 0:d8f4c441e032 1077 if ( lrc_obj.check_mode != 0 )
lixianyu 0:d8f4c441e032 1078 {
lixianyu 0:d8f4c441e032 1079 stack_element_p e = stack_GetCurrElement();
lixianyu 0:d8f4c441e032 1080 if ( lrc_obj.check_mode == CHECK_MODE_MOVEABLE )
lixianyu 0:d8f4c441e032 1081 {
lixianyu 0:d8f4c441e032 1082 cp_SetOnBoard(e->current_pos, e->current_cp | CP_MARK_MASK );
lixianyu 0:d8f4c441e032 1083 }
lixianyu 0:d8f4c441e032 1084 else if ( lrc_obj.check_mode == CHECK_MODE_TARGET_MOVE )
lixianyu 0:d8f4c441e032 1085 {
lixianyu 0:d8f4c441e032 1086 if ( e->current_pos == lrc_obj.check_src_pos )
lixianyu 0:d8f4c441e032 1087 {
lixianyu 0:d8f4c441e032 1088 cp_SetOnBoard(pos, cp_GetFromBoard(pos) | CP_MARK_MASK );
lixianyu 0:d8f4c441e032 1089 }
lixianyu 0:d8f4c441e032 1090 }
lixianyu 0:d8f4c441e032 1091 }
lixianyu 0:d8f4c441e032 1092 return 1;
lixianyu 0:d8f4c441e032 1093 }
lixianyu 0:d8f4c441e032 1094
lixianyu 0:d8f4c441e032 1095 /*==============================================================*/
lixianyu 0:d8f4c441e032 1096 /* move pieces which can move one or more steps into a direction */
lixianyu 0:d8f4c441e032 1097 /*==============================================================*/
lixianyu 0:d8f4c441e032 1098
lixianyu 0:d8f4c441e032 1099 /*
lixianyu 0:d8f4c441e032 1100 subprocedure to generate various target positions for some pieces
lixianyu 0:d8f4c441e032 1101 special cases are handled in the piece specific sub-procedure
lixianyu 0:d8f4c441e032 1102
lixianyu 0:d8f4c441e032 1103 Arguments:
lixianyu 0:d8f4c441e032 1104 d: a list of potential directions
lixianyu 0:d8f4c441e032 1105 is_multi_step: if the piece can only do one step (zero for KING and KNIGHT)
lixianyu 0:d8f4c441e032 1106 */
lixianyu 0:d8f4c441e032 1107 static const uint8_t ce_dir_offset_rook[] PROGMEM = { 1, 16, -16, -1, 0 };
lixianyu 0:d8f4c441e032 1108 static const uint8_t ce_dir_offset_bishop[] PROGMEM = { 15, 17, -17, -15, 0 };
lixianyu 0:d8f4c441e032 1109 static const uint8_t ce_dir_offset_queen[] PROGMEM = { 1, 16, -16, -1, 15, 17, -17, -15, 0 };
lixianyu 0:d8f4c441e032 1110 static const uint8_t ce_dir_offset_knight[] PROGMEM = {14, -14, 18, -18, 31, -31, 33, -33, 0};
lixianyu 0:d8f4c441e032 1111
lixianyu 0:d8f4c441e032 1112 void ce_LoopDirsSingleMultiStep(const uint8_t *d, uint8_t is_multi_step)
lixianyu 0:d8f4c441e032 1113 {
lixianyu 0:d8f4c441e032 1114 uint8_t loop_pos;
lixianyu 0:d8f4c441e032 1115
lixianyu 0:d8f4c441e032 1116 /* with all directions */
lixianyu 0:d8f4c441e032 1117 for(;;)
lixianyu 0:d8f4c441e032 1118 {
lixianyu 0:d8f4c441e032 1119 if ( u8g_pgm_read(d) == 0 )
lixianyu 0:d8f4c441e032 1120 break;
lixianyu 0:d8f4c441e032 1121
lixianyu 0:d8f4c441e032 1122 /* start again from the initial position */
lixianyu 0:d8f4c441e032 1123 loop_pos = stack_GetCurrElement()->current_pos;
lixianyu 0:d8f4c441e032 1124
lixianyu 0:d8f4c441e032 1125 /* check direction */
lixianyu 0:d8f4c441e032 1126 do
lixianyu 0:d8f4c441e032 1127 {
lixianyu 0:d8f4c441e032 1128 /* check next position into one direction */
lixianyu 0:d8f4c441e032 1129 loop_pos += u8g_pgm_read(d);
lixianyu 0:d8f4c441e032 1130
lixianyu 0:d8f4c441e032 1131 /*
lixianyu 0:d8f4c441e032 1132 go further to ce_LoopRecur()
lixianyu 0:d8f4c441e032 1133 0 will be returned if the target position is illegal or a piece of the own color
lixianyu 0:d8f4c441e032 1134 this is used to stop walking into one direction
lixianyu 0:d8f4c441e032 1135 */
lixianyu 0:d8f4c441e032 1136 if ( ce_LoopRecur(loop_pos) == 0 )
lixianyu 0:d8f4c441e032 1137 break;
lixianyu 0:d8f4c441e032 1138
lixianyu 0:d8f4c441e032 1139 /* stop if we had hit another piece */
lixianyu 0:d8f4c441e032 1140 if ( cp_GetPiece(cp_GetFromBoard(loop_pos)) != PIECE_NONE )
lixianyu 0:d8f4c441e032 1141 break;
lixianyu 0:d8f4c441e032 1142 } while( is_multi_step );
lixianyu 0:d8f4c441e032 1143 d++;
lixianyu 0:d8f4c441e032 1144 }
lixianyu 0:d8f4c441e032 1145 }
lixianyu 0:d8f4c441e032 1146
lixianyu 0:d8f4c441e032 1147 void ce_LoopRook(void)
lixianyu 0:d8f4c441e032 1148 {
lixianyu 0:d8f4c441e032 1149 ce_LoopDirsSingleMultiStep(ce_dir_offset_rook, 1);
lixianyu 0:d8f4c441e032 1150 }
lixianyu 0:d8f4c441e032 1151
lixianyu 0:d8f4c441e032 1152 void ce_LoopBishop(void)
lixianyu 0:d8f4c441e032 1153 {
lixianyu 0:d8f4c441e032 1154 ce_LoopDirsSingleMultiStep(ce_dir_offset_bishop, 1);
lixianyu 0:d8f4c441e032 1155 }
lixianyu 0:d8f4c441e032 1156
lixianyu 0:d8f4c441e032 1157 void ce_LoopQueen(void)
lixianyu 0:d8f4c441e032 1158 {
lixianyu 0:d8f4c441e032 1159 ce_LoopDirsSingleMultiStep(ce_dir_offset_queen, 1);
lixianyu 0:d8f4c441e032 1160 }
lixianyu 0:d8f4c441e032 1161
lixianyu 0:d8f4c441e032 1162 void ce_LoopKnight(void)
lixianyu 0:d8f4c441e032 1163 {
lixianyu 0:d8f4c441e032 1164 ce_LoopDirsSingleMultiStep(ce_dir_offset_knight, 0);
lixianyu 0:d8f4c441e032 1165 }
lixianyu 0:d8f4c441e032 1166
lixianyu 0:d8f4c441e032 1167
lixianyu 0:d8f4c441e032 1168
lixianyu 0:d8f4c441e032 1169 /*==============================================================*/
lixianyu 0:d8f4c441e032 1170 /* move king */
lixianyu 0:d8f4c441e032 1171 /*==============================================================*/
lixianyu 0:d8f4c441e032 1172
lixianyu 0:d8f4c441e032 1173 uint8_t cu_IsKingCastling(uint8_t mask, int8_t direction, uint8_t cnt) U8G_NOINLINE;
lixianyu 0:d8f4c441e032 1174
lixianyu 0:d8f4c441e032 1175 /*
lixianyu 0:d8f4c441e032 1176 checks, if the king can do castling
lixianyu 0:d8f4c441e032 1177
lixianyu 0:d8f4c441e032 1178 Arguments:
lixianyu 0:d8f4c441e032 1179 mask: the bit-mask for the global "castling possible" flag
lixianyu 0:d8f4c441e032 1180 direction: left castling: -1, right castling 1
lixianyu 0:d8f4c441e032 1181 cnt: number of fields to be checked: 3 or 2
lixianyu 0:d8f4c441e032 1182 */
lixianyu 0:d8f4c441e032 1183 uint8_t cu_IsKingCastling(uint8_t mask, int8_t direction, uint8_t cnt)
lixianyu 0:d8f4c441e032 1184 {
lixianyu 0:d8f4c441e032 1185 uint8_t pos;
lixianyu 0:d8f4c441e032 1186 uint8_t opponent_color;
lixianyu 0:d8f4c441e032 1187
lixianyu 0:d8f4c441e032 1188 /* check if the current board state allows castling */
lixianyu 0:d8f4c441e032 1189 if ( (lrc_obj.castling_possible & mask) == 0 )
lixianyu 0:d8f4c441e032 1190 return 0; /* castling not allowed */
lixianyu 0:d8f4c441e032 1191
lixianyu 0:d8f4c441e032 1192 /* get the position of the KING, could be white or black king */
lixianyu 0:d8f4c441e032 1193 pos = stack_GetCurrElement()->current_pos;
lixianyu 0:d8f4c441e032 1194
lixianyu 0:d8f4c441e032 1195 /* calculate the color of the opponent */
lixianyu 0:d8f4c441e032 1196 opponent_color = 1;
lixianyu 0:d8f4c441e032 1197 opponent_color -= stack_GetCurrElement()->current_color;
lixianyu 0:d8f4c441e032 1198
lixianyu 0:d8f4c441e032 1199 /* if the KING itself is given check... */
lixianyu 0:d8f4c441e032 1200 if ( ce_GetPositionAttackWeight(pos, opponent_color) > 0 )
lixianyu 0:d8f4c441e032 1201 return 0;
lixianyu 0:d8f4c441e032 1202
lixianyu 0:d8f4c441e032 1203
lixianyu 0:d8f4c441e032 1204 /* check if fields in the desired direction are emtpy */
lixianyu 0:d8f4c441e032 1205 for(;;)
lixianyu 0:d8f4c441e032 1206 {
lixianyu 0:d8f4c441e032 1207 /* go to the next field */
lixianyu 0:d8f4c441e032 1208 pos += direction;
lixianyu 0:d8f4c441e032 1209 /* check for a piece */
lixianyu 0:d8f4c441e032 1210 if ( cp_GetPiece(cp_GetFromBoard(pos)) != PIECE_NONE )
lixianyu 0:d8f4c441e032 1211 return 0; /* castling not allowed */
lixianyu 0:d8f4c441e032 1212
lixianyu 0:d8f4c441e032 1213 /* if some of the fields are under attack */
lixianyu 0:d8f4c441e032 1214 if ( ce_GetPositionAttackWeight(pos, opponent_color) > 0 )
lixianyu 0:d8f4c441e032 1215 return 0;
lixianyu 0:d8f4c441e032 1216
lixianyu 0:d8f4c441e032 1217 cnt--;
lixianyu 0:d8f4c441e032 1218 if ( cnt == 0 )
lixianyu 0:d8f4c441e032 1219 break;
lixianyu 0:d8f4c441e032 1220 }
lixianyu 0:d8f4c441e032 1221 return 1; /* castling allowed */
lixianyu 0:d8f4c441e032 1222 }
lixianyu 0:d8f4c441e032 1223
lixianyu 0:d8f4c441e032 1224 void ce_LoopKing(void)
lixianyu 0:d8f4c441e032 1225 {
lixianyu 0:d8f4c441e032 1226 /*
lixianyu 0:d8f4c441e032 1227 there is an interessting timing problem in this procedure
lixianyu 0:d8f4c441e032 1228 it must be checked for castling first and as second step the normal
lixianyu 0:d8f4c441e032 1229 KING movement. If we would first check for normal moves, than
lixianyu 0:d8f4c441e032 1230 any marks might be overwritten by the ROOK in the case of castling.
lixianyu 0:d8f4c441e032 1231 */
lixianyu 0:d8f4c441e032 1232
lixianyu 0:d8f4c441e032 1233 /* castling (this must be done before checking normal moves (see above) */
lixianyu 0:d8f4c441e032 1234 if ( stack_GetCurrElement()->current_color == COLOR_WHITE )
lixianyu 0:d8f4c441e032 1235 {
lixianyu 0:d8f4c441e032 1236 /* white left castling */
lixianyu 0:d8f4c441e032 1237 if ( cu_IsKingCastling(1, -1, 3) != 0 )
lixianyu 0:d8f4c441e032 1238 {
lixianyu 0:d8f4c441e032 1239 /* check for attacked fields */
lixianyu 0:d8f4c441e032 1240 ce_LoopRecur(stack_GetCurrElement()->current_pos-2);
lixianyu 0:d8f4c441e032 1241 }
lixianyu 0:d8f4c441e032 1242 /* white right castling */
lixianyu 0:d8f4c441e032 1243 if ( cu_IsKingCastling(2, 1, 2) != 0 )
lixianyu 0:d8f4c441e032 1244 {
lixianyu 0:d8f4c441e032 1245 /* check for attacked fields */
lixianyu 0:d8f4c441e032 1246 ce_LoopRecur(stack_GetCurrElement()->current_pos+2);
lixianyu 0:d8f4c441e032 1247 }
lixianyu 0:d8f4c441e032 1248 }
lixianyu 0:d8f4c441e032 1249 else
lixianyu 0:d8f4c441e032 1250 {
lixianyu 0:d8f4c441e032 1251 /* black left castling */
lixianyu 0:d8f4c441e032 1252 if ( cu_IsKingCastling(4, -1, 3) != 0 )
lixianyu 0:d8f4c441e032 1253 {
lixianyu 0:d8f4c441e032 1254 /* check for attacked fields */
lixianyu 0:d8f4c441e032 1255 ce_LoopRecur(stack_GetCurrElement()->current_pos-2);
lixianyu 0:d8f4c441e032 1256 }
lixianyu 0:d8f4c441e032 1257 /* black right castling */
lixianyu 0:d8f4c441e032 1258 if ( cu_IsKingCastling(8, 1, 2) != 0 )
lixianyu 0:d8f4c441e032 1259 {
lixianyu 0:d8f4c441e032 1260 /* check for attacked fields */
lixianyu 0:d8f4c441e032 1261 ce_LoopRecur(stack_GetCurrElement()->current_pos+2);
lixianyu 0:d8f4c441e032 1262 }
lixianyu 0:d8f4c441e032 1263 }
lixianyu 0:d8f4c441e032 1264
lixianyu 0:d8f4c441e032 1265 /* reuse queen directions */
lixianyu 0:d8f4c441e032 1266 ce_LoopDirsSingleMultiStep(ce_dir_offset_queen, 0);
lixianyu 0:d8f4c441e032 1267 }
lixianyu 0:d8f4c441e032 1268
lixianyu 0:d8f4c441e032 1269
lixianyu 0:d8f4c441e032 1270 /*==============================================================*/
lixianyu 0:d8f4c441e032 1271 /* move pawn */
lixianyu 0:d8f4c441e032 1272 /*==============================================================*/
lixianyu 0:d8f4c441e032 1273
lixianyu 0:d8f4c441e032 1274 /*
lixianyu 0:d8f4c441e032 1275 doppelschritt: nur von der grundlinie aus, beide (!) felder vor dem bauern müssen frei sein
lixianyu 0:d8f4c441e032 1276 en passant: nur unmittelbar nachdem ein doppelschritt ausgeführt wurde.
lixianyu 0:d8f4c441e032 1277 */
lixianyu 0:d8f4c441e032 1278 void ce_LoopPawnSideCapture(uint8_t loop_pos)
lixianyu 0:d8f4c441e032 1279 {
lixianyu 0:d8f4c441e032 1280 if ( gpos_IsIllegal(loop_pos) == 0 )
lixianyu 0:d8f4c441e032 1281 {
lixianyu 0:d8f4c441e032 1282 /* get the piece from the board */
lixianyu 0:d8f4c441e032 1283 /* if the field is NOT empty */
lixianyu 0:d8f4c441e032 1284 if ( cp_GetPiece(cp_GetFromBoard(loop_pos)) != PIECE_NONE )
lixianyu 0:d8f4c441e032 1285 {
lixianyu 0:d8f4c441e032 1286 /* normal capture */
lixianyu 0:d8f4c441e032 1287 ce_LoopRecur(loop_pos);
lixianyu 0:d8f4c441e032 1288 /* TODO: check for pawn conversion/promotion */
lixianyu 0:d8f4c441e032 1289 }
lixianyu 0:d8f4c441e032 1290 else
lixianyu 0:d8f4c441e032 1291 {
lixianyu 0:d8f4c441e032 1292 /* check conditions for en passant capture */
lixianyu 0:d8f4c441e032 1293 if ( stack_GetCurrElement()->current_color == COLOR_WHITE )
lixianyu 0:d8f4c441e032 1294 {
lixianyu 0:d8f4c441e032 1295 if ( lrc_obj.pawn_dbl_move[COLOR_BLACK]+16 == loop_pos )
lixianyu 0:d8f4c441e032 1296 {
lixianyu 0:d8f4c441e032 1297 ce_LoopRecur(loop_pos);
lixianyu 0:d8f4c441e032 1298 /* note: pawn conversion/promotion can not occur */
lixianyu 0:d8f4c441e032 1299 }
lixianyu 0:d8f4c441e032 1300 }
lixianyu 0:d8f4c441e032 1301 else
lixianyu 0:d8f4c441e032 1302 {
lixianyu 0:d8f4c441e032 1303 if ( lrc_obj.pawn_dbl_move[COLOR_WHITE] == loop_pos+16 )
lixianyu 0:d8f4c441e032 1304 {
lixianyu 0:d8f4c441e032 1305 ce_LoopRecur(loop_pos);
lixianyu 0:d8f4c441e032 1306 /* note: pawn conversion/promotion can not occur */
lixianyu 0:d8f4c441e032 1307 }
lixianyu 0:d8f4c441e032 1308 }
lixianyu 0:d8f4c441e032 1309 }
lixianyu 0:d8f4c441e032 1310 }
lixianyu 0:d8f4c441e032 1311 }
lixianyu 0:d8f4c441e032 1312
lixianyu 0:d8f4c441e032 1313 void ce_LoopPawn(void)
lixianyu 0:d8f4c441e032 1314 {
lixianyu 0:d8f4c441e032 1315 uint8_t initial_pos = stack_GetCurrElement()->current_pos;
lixianyu 0:d8f4c441e032 1316 uint8_t my_color = stack_GetCurrElement()->current_color;
lixianyu 0:d8f4c441e032 1317
lixianyu 0:d8f4c441e032 1318 uint8_t loop_pos;
lixianyu 0:d8f4c441e032 1319 uint8_t line;
lixianyu 0:d8f4c441e032 1320
lixianyu 0:d8f4c441e032 1321 /* one step forward */
lixianyu 0:d8f4c441e032 1322
lixianyu 0:d8f4c441e032 1323 loop_pos = initial_pos;
lixianyu 0:d8f4c441e032 1324 line = initial_pos;
lixianyu 0:d8f4c441e032 1325 line >>= 4;
lixianyu 0:d8f4c441e032 1326 if ( my_color == COLOR_WHITE )
lixianyu 0:d8f4c441e032 1327 loop_pos += 16;
lixianyu 0:d8f4c441e032 1328 else
lixianyu 0:d8f4c441e032 1329 loop_pos -= 16;
lixianyu 0:d8f4c441e032 1330 if ( gpos_IsIllegal(loop_pos) == 0 )
lixianyu 0:d8f4c441e032 1331 {
lixianyu 0:d8f4c441e032 1332 /* if the field is empty */
lixianyu 0:d8f4c441e032 1333 if ( cp_GetPiece(cp_GetFromBoard(loop_pos)) == PIECE_NONE )
lixianyu 0:d8f4c441e032 1334 {
lixianyu 0:d8f4c441e032 1335 /* TODO: check for and loop through piece conversion/promotion */
lixianyu 0:d8f4c441e032 1336 ce_LoopRecur(loop_pos);
lixianyu 0:d8f4c441e032 1337
lixianyu 0:d8f4c441e032 1338 /* second step forward */
lixianyu 0:d8f4c441e032 1339
lixianyu 0:d8f4c441e032 1340 /* if pawn is on his starting line */
lixianyu 0:d8f4c441e032 1341 if ( (my_color == COLOR_WHITE && line == 1) || (my_color == COLOR_BLACK && line == 6 ) )
lixianyu 0:d8f4c441e032 1342 {
lixianyu 0:d8f4c441e032 1343 /* the place before the pawn is not occupied, so we can do double moves, see above */
lixianyu 0:d8f4c441e032 1344
lixianyu 0:d8f4c441e032 1345 if ( my_color == COLOR_WHITE )
lixianyu 0:d8f4c441e032 1346 loop_pos += 16;
lixianyu 0:d8f4c441e032 1347 else
lixianyu 0:d8f4c441e032 1348 loop_pos -= 16;
lixianyu 0:d8f4c441e032 1349 if ( cp_GetPiece(cp_GetFromBoard(loop_pos)) == PIECE_NONE )
lixianyu 0:d8f4c441e032 1350 {
lixianyu 0:d8f4c441e032 1351 /* this is a special case, other promotions of the pawn can not occur */
lixianyu 0:d8f4c441e032 1352 ce_LoopRecur(loop_pos);
lixianyu 0:d8f4c441e032 1353 }
lixianyu 0:d8f4c441e032 1354 }
lixianyu 0:d8f4c441e032 1355 }
lixianyu 0:d8f4c441e032 1356 }
lixianyu 0:d8f4c441e032 1357
lixianyu 0:d8f4c441e032 1358 /* capture */
lixianyu 0:d8f4c441e032 1359
lixianyu 0:d8f4c441e032 1360 loop_pos = initial_pos;
lixianyu 0:d8f4c441e032 1361 if ( my_color == COLOR_WHITE )
lixianyu 0:d8f4c441e032 1362 loop_pos += 15;
lixianyu 0:d8f4c441e032 1363 else
lixianyu 0:d8f4c441e032 1364 loop_pos -= 15;
lixianyu 0:d8f4c441e032 1365 ce_LoopPawnSideCapture(loop_pos);
lixianyu 0:d8f4c441e032 1366
lixianyu 0:d8f4c441e032 1367
lixianyu 0:d8f4c441e032 1368 loop_pos = initial_pos;
lixianyu 0:d8f4c441e032 1369 if ( my_color == COLOR_WHITE )
lixianyu 0:d8f4c441e032 1370 loop_pos += 17;
lixianyu 0:d8f4c441e032 1371 else
lixianyu 0:d8f4c441e032 1372 loop_pos -= 17;
lixianyu 0:d8f4c441e032 1373 ce_LoopPawnSideCapture(loop_pos);
lixianyu 0:d8f4c441e032 1374 }
lixianyu 0:d8f4c441e032 1375
lixianyu 0:d8f4c441e032 1376 /*==============================================================*/
lixianyu 0:d8f4c441e032 1377 /* attacked */
lixianyu 0:d8f4c441e032 1378 /*==============================================================*/
lixianyu 0:d8f4c441e032 1379
lixianyu 0:d8f4c441e032 1380 /*
lixianyu 0:d8f4c441e032 1381 from a starting position, search for a piece, that might jump to that postion.
lixianyu 0:d8f4c441e032 1382 return:
lixianyu 0:d8f4c441e032 1383 the two global variables
lixianyu 0:d8f4c441e032 1384 lrc_obj.find_piece_weight[0];
lixianyu 0:d8f4c441e032 1385 lrc_obj.find_piece_weight[1];
lixianyu 0:d8f4c441e032 1386 will be increased by the weight of the attacked pieces of that color.
lixianyu 0:d8f4c441e032 1387 it is usually required to reset these global variables to zero, before using
lixianyu 0:d8f4c441e032 1388 this function.
lixianyu 0:d8f4c441e032 1389 */
lixianyu 0:d8f4c441e032 1390
lixianyu 0:d8f4c441e032 1391 void ce_FindPieceByStep(uint8_t start_pos, uint8_t piece, const uint8_t *d, uint8_t is_multi_step)
lixianyu 0:d8f4c441e032 1392 {
lixianyu 0:d8f4c441e032 1393 uint8_t loop_pos, cp;
lixianyu 0:d8f4c441e032 1394
lixianyu 0:d8f4c441e032 1395 /* with all directions */
lixianyu 0:d8f4c441e032 1396 for(;;)
lixianyu 0:d8f4c441e032 1397 {
lixianyu 0:d8f4c441e032 1398 if ( u8g_pgm_read(d) == 0 )
lixianyu 0:d8f4c441e032 1399 break;
lixianyu 0:d8f4c441e032 1400
lixianyu 0:d8f4c441e032 1401 /* start again from the initial position */
lixianyu 0:d8f4c441e032 1402 loop_pos = start_pos;
lixianyu 0:d8f4c441e032 1403
lixianyu 0:d8f4c441e032 1404 /* check direction */
lixianyu 0:d8f4c441e032 1405 do
lixianyu 0:d8f4c441e032 1406 {
lixianyu 0:d8f4c441e032 1407 /* check next position into one direction */
lixianyu 0:d8f4c441e032 1408 loop_pos += u8g_pgm_read(d);
lixianyu 0:d8f4c441e032 1409
lixianyu 0:d8f4c441e032 1410 /* check if the board boundary has been crossed */
lixianyu 0:d8f4c441e032 1411 if ( (loop_pos & 0x088) != 0 )
lixianyu 0:d8f4c441e032 1412 break;
lixianyu 0:d8f4c441e032 1413
lixianyu 0:d8f4c441e032 1414 /* get the colored piece from the board */
lixianyu 0:d8f4c441e032 1415 cp = cp_GetFromBoard(loop_pos);
lixianyu 0:d8f4c441e032 1416
lixianyu 0:d8f4c441e032 1417 /* stop if we had hit another piece */
lixianyu 0:d8f4c441e032 1418 if ( cp_GetPiece(cp) != PIECE_NONE )
lixianyu 0:d8f4c441e032 1419 {
lixianyu 0:d8f4c441e032 1420 /* if it is the piece we are looking for, then add the weight */
lixianyu 0:d8f4c441e032 1421 if ( cp_GetPiece(cp) == piece )
lixianyu 0:d8f4c441e032 1422 {
lixianyu 0:d8f4c441e032 1423 lrc_obj.find_piece_weight[cp_GetColor(cp)] += ce_piece_weight[piece];
lixianyu 0:d8f4c441e032 1424 lrc_obj.find_piece_cnt[cp_GetColor(cp)]++;
lixianyu 0:d8f4c441e032 1425 }
lixianyu 0:d8f4c441e032 1426 /* in any case, break out of the inner loop */
lixianyu 0:d8f4c441e032 1427 break;
lixianyu 0:d8f4c441e032 1428 }
lixianyu 0:d8f4c441e032 1429 } while( is_multi_step );
lixianyu 0:d8f4c441e032 1430 d++;
lixianyu 0:d8f4c441e032 1431 }
lixianyu 0:d8f4c441e032 1432 }
lixianyu 0:d8f4c441e032 1433
lixianyu 0:d8f4c441e032 1434 void ce_FindPawnPiece(uint8_t dest_pos, uint8_t color)
lixianyu 0:d8f4c441e032 1435 {
lixianyu 0:d8f4c441e032 1436 uint8_t cp;
lixianyu 0:d8f4c441e032 1437 /* check if the board boundary has been crossed */
lixianyu 0:d8f4c441e032 1438 if ( (dest_pos & 0x088) == 0 )
lixianyu 0:d8f4c441e032 1439 {
lixianyu 0:d8f4c441e032 1440 /* get the colored piece from the board */
lixianyu 0:d8f4c441e032 1441 cp = cp_GetFromBoard(dest_pos);
lixianyu 0:d8f4c441e032 1442 /* only if there is a pawn of the matching color */
lixianyu 0:d8f4c441e032 1443 if ( cp_GetPiece(cp) == PIECE_PAWN )
lixianyu 0:d8f4c441e032 1444 {
lixianyu 0:d8f4c441e032 1445 if ( cp_GetColor(cp) == color )
lixianyu 0:d8f4c441e032 1446 {
lixianyu 0:d8f4c441e032 1447 /* the weight of the PAWN */
lixianyu 0:d8f4c441e032 1448 lrc_obj.find_piece_weight[color] += 1;
lixianyu 0:d8f4c441e032 1449 lrc_obj.find_piece_cnt[color]++;
lixianyu 0:d8f4c441e032 1450 }
lixianyu 0:d8f4c441e032 1451 }
lixianyu 0:d8f4c441e032 1452 }
lixianyu 0:d8f4c441e032 1453 }
lixianyu 0:d8f4c441e032 1454
lixianyu 0:d8f4c441e032 1455
lixianyu 0:d8f4c441e032 1456 /*
lixianyu 0:d8f4c441e032 1457 find out, which pieces do attack a specified field
lixianyu 0:d8f4c441e032 1458 used to
lixianyu 0:d8f4c441e032 1459 - check if the KING can do castling
lixianyu 0:d8f4c441e032 1460 - check if the KING must move
lixianyu 0:d8f4c441e032 1461
lixianyu 0:d8f4c441e032 1462 may be used in the eval procedure ... once...
lixianyu 0:d8f4c441e032 1463
lixianyu 0:d8f4c441e032 1464 the result is stored in the global array
lixianyu 0:d8f4c441e032 1465 uint8_t lrc_obj.find_piece_weight[2];
lixianyu 0:d8f4c441e032 1466 which is indexed with the color.
lixianyu 0:d8f4c441e032 1467 lrc_obj.find_piece_weight[COLOR_WHITE] is the sum of all white pieces
lixianyu 0:d8f4c441e032 1468 which can directly move to this field.
lixianyu 0:d8f4c441e032 1469
lixianyu 0:d8f4c441e032 1470 example:
lixianyu 0:d8f4c441e032 1471 if the black KING is at "pos" and lrc_obj.find_piece_weight[COLOR_WHITE] is not zero
lixianyu 0:d8f4c441e032 1472 (after executing ce_CalculatePositionWeight(pos)) then the KING must be protected or moveed, because
lixianyu 0:d8f4c441e032 1473 the KING was given check.
lixianyu 0:d8f4c441e032 1474 */
lixianyu 0:d8f4c441e032 1475
lixianyu 0:d8f4c441e032 1476 void ce_CalculatePositionWeight(uint8_t pos)
lixianyu 0:d8f4c441e032 1477 {
lixianyu 0:d8f4c441e032 1478
lixianyu 0:d8f4c441e032 1479 lrc_obj.find_piece_weight[0] = 0;
lixianyu 0:d8f4c441e032 1480 lrc_obj.find_piece_weight[1] = 0;
lixianyu 0:d8f4c441e032 1481 lrc_obj.find_piece_cnt[0] = 0;
lixianyu 0:d8f4c441e032 1482 lrc_obj.find_piece_cnt[1] = 0;
lixianyu 0:d8f4c441e032 1483
lixianyu 0:d8f4c441e032 1484 if ( (pos & 0x088) != 0 )
lixianyu 0:d8f4c441e032 1485 return;
lixianyu 0:d8f4c441e032 1486
lixianyu 0:d8f4c441e032 1487 ce_FindPieceByStep(pos, PIECE_ROOK, ce_dir_offset_rook, 1);
lixianyu 0:d8f4c441e032 1488 ce_FindPieceByStep(pos, PIECE_BISHOP, ce_dir_offset_bishop, 1);
lixianyu 0:d8f4c441e032 1489 ce_FindPieceByStep(pos, PIECE_QUEEN, ce_dir_offset_queen, 1);
lixianyu 0:d8f4c441e032 1490 ce_FindPieceByStep(pos, PIECE_KNIGHT, ce_dir_offset_knight, 0);
lixianyu 0:d8f4c441e032 1491 ce_FindPieceByStep(pos, PIECE_KING, ce_dir_offset_queen, 0);
lixianyu 0:d8f4c441e032 1492
lixianyu 0:d8f4c441e032 1493 ce_FindPawnPiece(pos+17, COLOR_BLACK);
lixianyu 0:d8f4c441e032 1494 ce_FindPawnPiece(pos+15, COLOR_BLACK);
lixianyu 0:d8f4c441e032 1495 ce_FindPawnPiece(pos-17, COLOR_WHITE);
lixianyu 0:d8f4c441e032 1496 ce_FindPawnPiece(pos-15, COLOR_WHITE);
lixianyu 0:d8f4c441e032 1497 }
lixianyu 0:d8f4c441e032 1498
lixianyu 0:d8f4c441e032 1499 /*
lixianyu 0:d8f4c441e032 1500 calculate the summed weight of pieces with specified color which can move to a specified position
lixianyu 0:d8f4c441e032 1501
lixianyu 0:d8f4c441e032 1502 argument:
lixianyu 0:d8f4c441e032 1503 pos: the position which should be analysed
lixianyu 0:d8f4c441e032 1504 color: the color of those pieces which should be analysed
lixianyu 0:d8f4c441e032 1505 e.g. if a black piece is at 'pos' and 'color' is white then this procedure returns the white atting count
lixianyu 0:d8f4c441e032 1506 */
lixianyu 0:d8f4c441e032 1507 uint8_t ce_GetPositionAttackWeight(uint8_t pos, uint8_t color)
lixianyu 0:d8f4c441e032 1508 {
lixianyu 0:d8f4c441e032 1509 ce_CalculatePositionWeight(pos);
lixianyu 0:d8f4c441e032 1510 return lrc_obj.find_piece_weight[color];
lixianyu 0:d8f4c441e032 1511 }
lixianyu 0:d8f4c441e032 1512
lixianyu 0:d8f4c441e032 1513 uint8_t ce_GetPositionAttackCount(uint8_t pos, uint8_t color)
lixianyu 0:d8f4c441e032 1514 {
lixianyu 0:d8f4c441e032 1515 ce_CalculatePositionWeight(pos);
lixianyu 0:d8f4c441e032 1516 return lrc_obj.find_piece_cnt[color];
lixianyu 0:d8f4c441e032 1517 }
lixianyu 0:d8f4c441e032 1518
lixianyu 0:d8f4c441e032 1519
lixianyu 0:d8f4c441e032 1520 /*==============================================================*/
lixianyu 0:d8f4c441e032 1521 /* depth search starts here: loop over all pieces of the current color on the board */
lixianyu 0:d8f4c441e032 1522 /*==============================================================*/
lixianyu 0:d8f4c441e032 1523
lixianyu 0:d8f4c441e032 1524 void ce_LoopPieces(void)
lixianyu 0:d8f4c441e032 1525 {
lixianyu 0:d8f4c441e032 1526 stack_element_p e = stack_GetCurrElement();
lixianyu 0:d8f4c441e032 1527 /* start with lower left position (A1) */
lixianyu 0:d8f4c441e032 1528 e->current_pos = 0;
lixianyu 0:d8f4c441e032 1529 do
lixianyu 0:d8f4c441e032 1530 {
lixianyu 0:d8f4c441e032 1531 e->current_cp = cp_GetFromBoard(e->current_pos);
lixianyu 0:d8f4c441e032 1532 /* check if the position on the board is empty */
lixianyu 0:d8f4c441e032 1533 if ( e->current_cp != 0 )
lixianyu 0:d8f4c441e032 1534 {
lixianyu 0:d8f4c441e032 1535 /* only generate moves for the current color */
lixianyu 0:d8f4c441e032 1536 if ( e->current_color == cp_GetColor(e->current_cp) )
lixianyu 0:d8f4c441e032 1537 {
lixianyu 0:d8f4c441e032 1538 chess_Thinking();
lixianyu 0:d8f4c441e032 1539
lixianyu 0:d8f4c441e032 1540 /* find out which piece is used */
lixianyu 0:d8f4c441e032 1541 switch(cp_GetPiece(e->current_cp))
lixianyu 0:d8f4c441e032 1542 {
lixianyu 0:d8f4c441e032 1543 case PIECE_NONE:
lixianyu 0:d8f4c441e032 1544 break;
lixianyu 0:d8f4c441e032 1545 case PIECE_PAWN:
lixianyu 0:d8f4c441e032 1546 ce_LoopPawn();
lixianyu 0:d8f4c441e032 1547 break;
lixianyu 0:d8f4c441e032 1548 case PIECE_KNIGHT:
lixianyu 0:d8f4c441e032 1549 ce_LoopKnight();
lixianyu 0:d8f4c441e032 1550 break;
lixianyu 0:d8f4c441e032 1551 case PIECE_BISHOP:
lixianyu 0:d8f4c441e032 1552 ce_LoopBishop();
lixianyu 0:d8f4c441e032 1553 break;
lixianyu 0:d8f4c441e032 1554 case PIECE_ROOK:
lixianyu 0:d8f4c441e032 1555 ce_LoopRook();
lixianyu 0:d8f4c441e032 1556 break;
lixianyu 0:d8f4c441e032 1557 case PIECE_QUEEN:
lixianyu 0:d8f4c441e032 1558 ce_LoopQueen();
lixianyu 0:d8f4c441e032 1559 break;
lixianyu 0:d8f4c441e032 1560 case PIECE_KING:
lixianyu 0:d8f4c441e032 1561 ce_LoopKing();
lixianyu 0:d8f4c441e032 1562 break;
lixianyu 0:d8f4c441e032 1563 }
lixianyu 0:d8f4c441e032 1564 }
lixianyu 0:d8f4c441e032 1565 }
lixianyu 0:d8f4c441e032 1566 e->current_pos = cu_NextPos(e->current_pos);
lixianyu 0:d8f4c441e032 1567 } while( e->current_pos != 0 );
lixianyu 0:d8f4c441e032 1568 }
lixianyu 0:d8f4c441e032 1569
lixianyu 0:d8f4c441e032 1570 /*==============================================================*/
lixianyu 0:d8f4c441e032 1571 /* user interface */
lixianyu 0:d8f4c441e032 1572 /*==============================================================*/
lixianyu 0:d8f4c441e032 1573
lixianyu 0:d8f4c441e032 1574 /*
lixianyu 0:d8f4c441e032 1575 eval_t chess_EvalCurrBoard(uint8_t color)
lixianyu 0:d8f4c441e032 1576 {
lixianyu 0:d8f4c441e032 1577 stack_Init(0);
lixianyu 0:d8f4c441e032 1578 stack_GetCurrElement()->current_color = color;
lixianyu 0:d8f4c441e032 1579 ce_LoopPieces();
lixianyu 0:d8f4c441e032 1580 return stack_GetCurrElement()->best_eval;
lixianyu 0:d8f4c441e032 1581 }
lixianyu 0:d8f4c441e032 1582 */
lixianyu 0:d8f4c441e032 1583
lixianyu 0:d8f4c441e032 1584 /* clear any marks on the board */
lixianyu 0:d8f4c441e032 1585 void chess_ClearMarks(void)
lixianyu 0:d8f4c441e032 1586 {
lixianyu 0:d8f4c441e032 1587 uint8_t i;
lixianyu 0:d8f4c441e032 1588 for( i = 0; i < 64; i++ )
lixianyu 0:d8f4c441e032 1589 lrc_obj.board[i] &= ~CP_MARK_MASK;
lixianyu 0:d8f4c441e032 1590 }
lixianyu 0:d8f4c441e032 1591
lixianyu 0:d8f4c441e032 1592 /*
lixianyu 0:d8f4c441e032 1593 Mark all pieces which can do moves. This is done by setting flags on the global board
lixianyu 0:d8f4c441e032 1594 */
lixianyu 0:d8f4c441e032 1595 void chess_MarkMovable(void)
lixianyu 0:d8f4c441e032 1596 {
lixianyu 0:d8f4c441e032 1597 stack_Init(0);
lixianyu 0:d8f4c441e032 1598 //stack_GetCurrElement()->current_color = color;
lixianyu 0:d8f4c441e032 1599 lrc_obj.check_mode = CHECK_MODE_MOVEABLE;
lixianyu 0:d8f4c441e032 1600 ce_LoopPieces();
lixianyu 0:d8f4c441e032 1601 }
lixianyu 0:d8f4c441e032 1602
lixianyu 0:d8f4c441e032 1603 /*
lixianyu 0:d8f4c441e032 1604 Checks, if the piece can move from src_pos to dest_pos
lixianyu 0:d8f4c441e032 1605
lixianyu 0:d8f4c441e032 1606 src_pos: The game position of a piece on the chess board
lixianyu 0:d8f4c441e032 1607 */
lixianyu 0:d8f4c441e032 1608 void chess_MarkTargetMoves(uint8_t src_pos)
lixianyu 0:d8f4c441e032 1609 {
lixianyu 0:d8f4c441e032 1610 stack_Init(0);
lixianyu 0:d8f4c441e032 1611 stack_GetCurrElement()->current_color = cp_GetColor(cp_GetFromBoard(src_pos));
lixianyu 0:d8f4c441e032 1612 lrc_obj.check_src_pos = src_pos;
lixianyu 0:d8f4c441e032 1613 lrc_obj.check_mode = CHECK_MODE_TARGET_MOVE;
lixianyu 0:d8f4c441e032 1614 ce_LoopPieces();
lixianyu 0:d8f4c441e032 1615 }
lixianyu 0:d8f4c441e032 1616
lixianyu 0:d8f4c441e032 1617 /*
lixianyu 0:d8f4c441e032 1618 first call should start with 255
lixianyu 0:d8f4c441e032 1619 this procedure will return 255 if
lixianyu 0:d8f4c441e032 1620 - there are no marks at all
lixianyu 0:d8f4c441e032 1621 - it has looped over all marks once
lixianyu 0:d8f4c441e032 1622 */
lixianyu 0:d8f4c441e032 1623 uint8_t chess_GetNextMarked(uint8_t arg, uint8_t is_prev)
lixianyu 0:d8f4c441e032 1624 {
lixianyu 0:d8f4c441e032 1625 uint8_t i;
lixianyu 0:d8f4c441e032 1626 uint8_t pos = arg;
lixianyu 0:d8f4c441e032 1627 for(i = 0; i < 64; i++)
lixianyu 0:d8f4c441e032 1628 {
lixianyu 0:d8f4c441e032 1629 if ( is_prev != 0 )
lixianyu 0:d8f4c441e032 1630 pos = cu_PrevPos(pos);
lixianyu 0:d8f4c441e032 1631 else
lixianyu 0:d8f4c441e032 1632 pos = cu_NextPos(pos);
lixianyu 0:d8f4c441e032 1633 if ( arg != 255 && pos == 0 )
lixianyu 0:d8f4c441e032 1634 return 255;
lixianyu 0:d8f4c441e032 1635 if ( cp_IsMarked(cp_GetFromBoard(pos)) )
lixianyu 0:d8f4c441e032 1636 return pos;
lixianyu 0:d8f4c441e032 1637 }
lixianyu 0:d8f4c441e032 1638 return 255;
lixianyu 0:d8f4c441e032 1639 }
lixianyu 0:d8f4c441e032 1640
lixianyu 0:d8f4c441e032 1641
lixianyu 0:d8f4c441e032 1642 /* make a manual move: this is a little bit more than cu_Move() */
lixianyu 0:d8f4c441e032 1643 void chess_ManualMove(uint8_t src, uint8_t dest)
lixianyu 0:d8f4c441e032 1644 {
lixianyu 0:d8f4c441e032 1645 uint8_t cp;
lixianyu 0:d8f4c441e032 1646
lixianyu 0:d8f4c441e032 1647 /* printf("chess_ManualMove %02x -> %02x\n", src, dest); */
lixianyu 0:d8f4c441e032 1648
lixianyu 0:d8f4c441e032 1649 /* if all other things fail, this is the place where the game is to be decided: */
lixianyu 0:d8f4c441e032 1650 /* ... if the KING is captured */
lixianyu 0:d8f4c441e032 1651 cp = cp_GetFromBoard(dest);
lixianyu 0:d8f4c441e032 1652 if ( cp_GetPiece(cp) == PIECE_KING )
lixianyu 0:d8f4c441e032 1653 {
lixianyu 0:d8f4c441e032 1654 lrc_obj.is_game_end = 1;
lixianyu 0:d8f4c441e032 1655 lrc_obj.lost_side_color = cp_GetColor(cp);
lixianyu 0:d8f4c441e032 1656 }
lixianyu 0:d8f4c441e032 1657
lixianyu 0:d8f4c441e032 1658 /* clear ply history here, to avoid memory overflow */
lixianyu 0:d8f4c441e032 1659 /* may be the last X moves can be kept here */
lixianyu 0:d8f4c441e032 1660 cu_ReduceHistoryByFullMove();
lixianyu 0:d8f4c441e032 1661 /* perform the move on the board */
lixianyu 0:d8f4c441e032 1662 cu_Move(src, dest);
lixianyu 0:d8f4c441e032 1663
lixianyu 0:d8f4c441e032 1664 /* update en passant double move positions: en passant position is removed after two half moves */
lixianyu 0:d8f4c441e032 1665 lrc_obj.pawn_dbl_move[lrc_obj.ply_count&1] = ILLEGAL_POSITION;
lixianyu 0:d8f4c441e032 1666
lixianyu 0:d8f4c441e032 1667 /* update the global half move counter */
lixianyu 0:d8f4c441e032 1668 lrc_obj.ply_count++;
lixianyu 0:d8f4c441e032 1669
lixianyu 0:d8f4c441e032 1670
lixianyu 0:d8f4c441e032 1671 /* make a small check about the end of the game */
lixianyu 0:d8f4c441e032 1672 /* use at least depth 1, because we must know if the king can still move */
lixianyu 0:d8f4c441e032 1673 /* this is: King moves at level 0 and will be captured at level 1 */
lixianyu 0:d8f4c441e032 1674 /* so we check if the king can move and will not be captured at search level 1 */
lixianyu 0:d8f4c441e032 1675
lixianyu 0:d8f4c441e032 1676 stack_Init(1);
lixianyu 0:d8f4c441e032 1677 ce_LoopPieces();
lixianyu 0:d8f4c441e032 1678
lixianyu 0:d8f4c441e032 1679 /* printf("chess_ManualMove/analysis best_from_pos %02x -> best_to_pos %02x\n", stack_GetCurrElement()->best_from_pos, stack_GetCurrElement()->best_to_pos); */
lixianyu 0:d8f4c441e032 1680
lixianyu 0:d8f4c441e032 1681 /* analyse the eval result */
lixianyu 0:d8f4c441e032 1682
lixianyu 0:d8f4c441e032 1683 /* check if the other player has any moves left */
lixianyu 0:d8f4c441e032 1684 if ( stack_GetCurrElement()->best_from_pos == ILLEGAL_POSITION )
lixianyu 0:d8f4c441e032 1685 {
lixianyu 0:d8f4c441e032 1686 uint8_t color;
lixianyu 0:d8f4c441e032 1687 /* conditions: */
lixianyu 0:d8f4c441e032 1688 /* 1. no King, should never happen, opposite color has won */
lixianyu 0:d8f4c441e032 1689 /* this is already checked above at the beginning if this procedure */
lixianyu 0:d8f4c441e032 1690 /* 2. King is under attack, opposite color has won */
lixianyu 0:d8f4c441e032 1691 /* 3. King is not under attack, game is a draw */
lixianyu 0:d8f4c441e032 1692
lixianyu 0:d8f4c441e032 1693 uint8_t i = 0;
lixianyu 0:d8f4c441e032 1694 color = lrc_obj.ply_count;
lixianyu 0:d8f4c441e032 1695 color &= 1;
lixianyu 0:d8f4c441e032 1696 do
lixianyu 0:d8f4c441e032 1697 {
lixianyu 0:d8f4c441e032 1698 cp = cp_GetFromBoard(i);
lixianyu 0:d8f4c441e032 1699 /* look for the King */
lixianyu 0:d8f4c441e032 1700 if ( cp_GetPiece(cp) == PIECE_KING )
lixianyu 0:d8f4c441e032 1701 {
lixianyu 0:d8f4c441e032 1702 if ( cp_GetColor(cp) == color )
lixianyu 0:d8f4c441e032 1703 {
lixianyu 0:d8f4c441e032 1704 /* check if KING is attacked */
lixianyu 0:d8f4c441e032 1705 if ( ce_GetPositionAttackCount(i, color^1) != 0 )
lixianyu 0:d8f4c441e032 1706 {
lixianyu 0:d8f4c441e032 1707 /* KING is under attack (check) and can not move: Game is lost */
lixianyu 0:d8f4c441e032 1708 lrc_obj.is_game_end = 1;
lixianyu 0:d8f4c441e032 1709 lrc_obj.lost_side_color = color;
lixianyu 0:d8f4c441e032 1710 }
lixianyu 0:d8f4c441e032 1711 else
lixianyu 0:d8f4c441e032 1712 {
lixianyu 0:d8f4c441e032 1713 /* KING is NOT under attack (check) but can not move: Game is a draw */
lixianyu 0:d8f4c441e032 1714 lrc_obj.is_game_end = 1;
lixianyu 0:d8f4c441e032 1715 lrc_obj.lost_side_color = 2;
lixianyu 0:d8f4c441e032 1716 }
lixianyu 0:d8f4c441e032 1717 /* break out of the loop */
lixianyu 0:d8f4c441e032 1718 break;
lixianyu 0:d8f4c441e032 1719 }
lixianyu 0:d8f4c441e032 1720 }
lixianyu 0:d8f4c441e032 1721 i = cu_NextPos(i);
lixianyu 0:d8f4c441e032 1722 } while( i != 0 );
lixianyu 0:d8f4c441e032 1723 }
lixianyu 0:d8f4c441e032 1724 }
lixianyu 0:d8f4c441e032 1725
lixianyu 0:d8f4c441e032 1726 /* let the computer do a move */
lixianyu 0:d8f4c441e032 1727 void chess_ComputerMove(uint8_t depth)
lixianyu 0:d8f4c441e032 1728 {
lixianyu 0:d8f4c441e032 1729 stack_Init(depth);
lixianyu 0:d8f4c441e032 1730
lixianyu 0:d8f4c441e032 1731 //stack_GetCurrElement()->current_color = lrc_obj.ply_count;
lixianyu 0:d8f4c441e032 1732 //stack_GetCurrElement()->current_color &= 1;
lixianyu 0:d8f4c441e032 1733
lixianyu 0:d8f4c441e032 1734 cu_ReduceHistoryByFullMove();
lixianyu 0:d8f4c441e032 1735 ce_LoopPieces();
lixianyu 0:d8f4c441e032 1736
lixianyu 0:d8f4c441e032 1737 chess_ManualMove(stack_GetCurrElement()->best_from_pos, stack_GetCurrElement()->best_to_pos);
lixianyu 0:d8f4c441e032 1738 }
lixianyu 0:d8f4c441e032 1739
lixianyu 0:d8f4c441e032 1740
lixianyu 0:d8f4c441e032 1741 /*==============================================================*/
lixianyu 0:d8f4c441e032 1742 /* unix code */
lixianyu 0:d8f4c441e032 1743 /*==============================================================*/
lixianyu 0:d8f4c441e032 1744
lixianyu 0:d8f4c441e032 1745 #ifdef UNIX_MAIN
lixianyu 0:d8f4c441e032 1746
lixianyu 0:d8f4c441e032 1747 #include <stdio.h>
lixianyu 0:d8f4c441e032 1748 #include <string.h>
lixianyu 0:d8f4c441e032 1749
lixianyu 0:d8f4c441e032 1750 char *piece_str[] = {
lixianyu 0:d8f4c441e032 1751 /* 0x00 */
lixianyu 0:d8f4c441e032 1752 " ",
lixianyu 0:d8f4c441e032 1753 "wP",
lixianyu 0:d8f4c441e032 1754 "wN",
lixianyu 0:d8f4c441e032 1755 "wB",
lixianyu 0:d8f4c441e032 1756
lixianyu 0:d8f4c441e032 1757 /* 0x04 */
lixianyu 0:d8f4c441e032 1758 "wR",
lixianyu 0:d8f4c441e032 1759 "wQ",
lixianyu 0:d8f4c441e032 1760 "wK",
lixianyu 0:d8f4c441e032 1761 "w?",
lixianyu 0:d8f4c441e032 1762
lixianyu 0:d8f4c441e032 1763 /* 0x08 */
lixianyu 0:d8f4c441e032 1764 "w?",
lixianyu 0:d8f4c441e032 1765 "w?",
lixianyu 0:d8f4c441e032 1766 "w?",
lixianyu 0:d8f4c441e032 1767 "w?",
lixianyu 0:d8f4c441e032 1768
lixianyu 0:d8f4c441e032 1769 /* 0x0c */
lixianyu 0:d8f4c441e032 1770 "w?",
lixianyu 0:d8f4c441e032 1771 "w?",
lixianyu 0:d8f4c441e032 1772 "w?",
lixianyu 0:d8f4c441e032 1773 "w?",
lixianyu 0:d8f4c441e032 1774
lixianyu 0:d8f4c441e032 1775 /* 0x10 */
lixianyu 0:d8f4c441e032 1776 "b ",
lixianyu 0:d8f4c441e032 1777 "bP",
lixianyu 0:d8f4c441e032 1778 "bN",
lixianyu 0:d8f4c441e032 1779 "bB",
lixianyu 0:d8f4c441e032 1780 "bR",
lixianyu 0:d8f4c441e032 1781 "bQ",
lixianyu 0:d8f4c441e032 1782 "bK",
lixianyu 0:d8f4c441e032 1783 "b?",
lixianyu 0:d8f4c441e032 1784
lixianyu 0:d8f4c441e032 1785 "b?",
lixianyu 0:d8f4c441e032 1786 "b?",
lixianyu 0:d8f4c441e032 1787 "b?",
lixianyu 0:d8f4c441e032 1788 "b?",
lixianyu 0:d8f4c441e032 1789 "b?",
lixianyu 0:d8f4c441e032 1790 "b?",
lixianyu 0:d8f4c441e032 1791 "b?",
lixianyu 0:d8f4c441e032 1792 "b?"
lixianyu 0:d8f4c441e032 1793 };
lixianyu 0:d8f4c441e032 1794
lixianyu 0:d8f4c441e032 1795 void chess_Thinking(void)
lixianyu 0:d8f4c441e032 1796 {
lixianyu 0:d8f4c441e032 1797 uint8_t i;
lixianyu 0:d8f4c441e032 1798 uint8_t cp = cp_GetPiece(stack_GetCurrElement()->current_cp);
lixianyu 0:d8f4c441e032 1799
lixianyu 0:d8f4c441e032 1800 printf("Thinking: ", piece_str[cp], stack_GetCurrElement()->current_pos);
lixianyu 0:d8f4c441e032 1801
lixianyu 0:d8f4c441e032 1802 for( i = 0; i <= lrc_obj.curr_depth; i++ )
lixianyu 0:d8f4c441e032 1803 printf("%s ", piece_str[(lrc_obj.stack_memory+i)->current_cp]);
lixianyu 0:d8f4c441e032 1804
lixianyu 0:d8f4c441e032 1805 printf(" \r");
lixianyu 0:d8f4c441e032 1806 }
lixianyu 0:d8f4c441e032 1807
lixianyu 0:d8f4c441e032 1808 void board_Show(void)
lixianyu 0:d8f4c441e032 1809 {
lixianyu 0:d8f4c441e032 1810 uint8_t i, j, cp;
lixianyu 0:d8f4c441e032 1811 char buf[10];
lixianyu 0:d8f4c441e032 1812 for ( i = 0; i < 8; i++ )
lixianyu 0:d8f4c441e032 1813 {
lixianyu 0:d8f4c441e032 1814 printf("%1d ", 7-i);
lixianyu 0:d8f4c441e032 1815 for ( j = 0; j < 8; j++ )
lixianyu 0:d8f4c441e032 1816 {
lixianyu 0:d8f4c441e032 1817 /* get piece from global board */
lixianyu 0:d8f4c441e032 1818 cp = lrc_obj.board[(7-i)*8+j];
lixianyu 0:d8f4c441e032 1819 strcpy(buf, piece_str[cp&COLOR_PIECE_MASK]);
lixianyu 0:d8f4c441e032 1820
lixianyu 0:d8f4c441e032 1821 if ( (cp & CP_MARK_MASK) != 0 )
lixianyu 0:d8f4c441e032 1822 {
lixianyu 0:d8f4c441e032 1823 buf[0] = '#';
lixianyu 0:d8f4c441e032 1824 }
lixianyu 0:d8f4c441e032 1825
lixianyu 0:d8f4c441e032 1826 /* mask out any bits except color and piece index */
lixianyu 0:d8f4c441e032 1827 cp &= COLOR_PIECE_MASK;
lixianyu 0:d8f4c441e032 1828 printf("%s %02x ", buf, cp);
lixianyu 0:d8f4c441e032 1829
lixianyu 0:d8f4c441e032 1830 }
lixianyu 0:d8f4c441e032 1831 printf("\n");
lixianyu 0:d8f4c441e032 1832 }
lixianyu 0:d8f4c441e032 1833 }
lixianyu 0:d8f4c441e032 1834
lixianyu 0:d8f4c441e032 1835 int main(void)
lixianyu 0:d8f4c441e032 1836 {
lixianyu 0:d8f4c441e032 1837 uint8_t depth = 3;
lixianyu 0:d8f4c441e032 1838 chess_SetupBoard();
lixianyu 0:d8f4c441e032 1839 board_Show();
lixianyu 0:d8f4c441e032 1840 puts("");
lixianyu 0:d8f4c441e032 1841
lixianyu 0:d8f4c441e032 1842
lixianyu 0:d8f4c441e032 1843 /*
lixianyu 0:d8f4c441e032 1844 chess_ClearMarks();
lixianyu 0:d8f4c441e032 1845 chess_MarkMovable(COLOR_WHITE);
lixianyu 0:d8f4c441e032 1846 board_Show();
lixianyu 0:d8f4c441e032 1847 */
lixianyu 0:d8f4c441e032 1848
lixianyu 0:d8f4c441e032 1849 chess_ManualMove(0x006, 0x066);
lixianyu 0:d8f4c441e032 1850
lixianyu 0:d8f4c441e032 1851 printf("lrc_obj.is_game_end: %d\n" , lrc_obj.is_game_end);
lixianyu 0:d8f4c441e032 1852 printf("lrc_obj.lost_side_color: %d\n" , lrc_obj.lost_side_color);
lixianyu 0:d8f4c441e032 1853
lixianyu 0:d8f4c441e032 1854 chess_ComputerMove(2);
lixianyu 0:d8f4c441e032 1855
lixianyu 0:d8f4c441e032 1856 printf("lrc_obj.is_game_end: %d\n" , lrc_obj.is_game_end);
lixianyu 0:d8f4c441e032 1857 printf("lrc_obj.lost_side_color: %d\n" , lrc_obj.lost_side_color);
lixianyu 0:d8f4c441e032 1858
lixianyu 0:d8f4c441e032 1859 board_Show();
lixianyu 0:d8f4c441e032 1860
lixianyu 0:d8f4c441e032 1861 }
lixianyu 0:d8f4c441e032 1862
lixianyu 0:d8f4c441e032 1863
lixianyu 0:d8f4c441e032 1864
lixianyu 0:d8f4c441e032 1865 #else
lixianyu 0:d8f4c441e032 1866
lixianyu 0:d8f4c441e032 1867 /*==============================================================*/
lixianyu 0:d8f4c441e032 1868 /* display menu */
lixianyu 0:d8f4c441e032 1869 /*==============================================================*/
lixianyu 0:d8f4c441e032 1870
lixianyu 0:d8f4c441e032 1871 //#define MNU_FONT font_5x7
lixianyu 0:d8f4c441e032 1872 #define MNU_FONT u8g_font_5x8r
lixianyu 0:d8f4c441e032 1873 //#define MNU_FONT font_6x9
lixianyu 0:d8f4c441e032 1874 #define MNU_ENTRY_HEIGHT 9
lixianyu 0:d8f4c441e032 1875
lixianyu 0:d8f4c441e032 1876 char *mnu_title = "Little Rook Chess";
lixianyu 0:d8f4c441e032 1877 char *mnu_list[] = { "New Game (White)", "New Game (Black)", "Undo Move", "Return" };
lixianyu 0:d8f4c441e032 1878 uint8_t mnu_pos = 0;
lixianyu 0:d8f4c441e032 1879 uint8_t mnu_max = 4;
lixianyu 0:d8f4c441e032 1880
lixianyu 0:d8f4c441e032 1881 void mnu_DrawHome(uint8_t is_highlight)
lixianyu 0:d8f4c441e032 1882 {
lixianyu 0:d8f4c441e032 1883 uint8_t x = lrc_u8g->width - 35;
lixianyu 0:d8f4c441e032 1884 uint8_t y = (lrc_u8g->height-1);
lixianyu 0:d8f4c441e032 1885 uint8_t t;
lixianyu 0:d8f4c441e032 1886
lixianyu 0:d8f4c441e032 1887 u8g_SetFont(lrc_u8g, u8g_font_5x7r);
lixianyu 0:d8f4c441e032 1888 u8g_SetDefaultForegroundColor(lrc_u8g);
lixianyu 0:d8f4c441e032 1889 t = u8g_DrawStrP(lrc_u8g, x, y -1, U8G_PSTR("Options"));
lixianyu 0:d8f4c441e032 1890
lixianyu 0:d8f4c441e032 1891 if ( is_highlight )
lixianyu 0:d8f4c441e032 1892 u8g_DrawFrame(lrc_u8g, x-1, y - MNU_ENTRY_HEIGHT +1, t, MNU_ENTRY_HEIGHT);
lixianyu 0:d8f4c441e032 1893 }
lixianyu 0:d8f4c441e032 1894
lixianyu 0:d8f4c441e032 1895 void mnu_DrawEntry(uint8_t y, char *str, uint8_t is_clr_background, uint8_t is_highlight)
lixianyu 0:d8f4c441e032 1896 {
lixianyu 0:d8f4c441e032 1897 uint8_t t, x;
lixianyu 0:d8f4c441e032 1898 u8g_SetFont(lrc_u8g, MNU_FONT);
lixianyu 0:d8f4c441e032 1899 t = u8g_GetStrWidth(lrc_u8g, str);
lixianyu 0:d8f4c441e032 1900 x = u8g_GetWidth(lrc_u8g);
lixianyu 0:d8f4c441e032 1901 x -= t;
lixianyu 0:d8f4c441e032 1902 x >>= 1;
lixianyu 0:d8f4c441e032 1903
lixianyu 0:d8f4c441e032 1904 if ( is_clr_background )
lixianyu 0:d8f4c441e032 1905 {
lixianyu 0:d8f4c441e032 1906 u8g_SetDefaultBackgroundColor(lrc_u8g);
lixianyu 0:d8f4c441e032 1907 u8g_DrawBox(lrc_u8g, x-3, (lrc_u8g->height-1) - (y+MNU_ENTRY_HEIGHT-1+2), t+5, MNU_ENTRY_HEIGHT+4);
lixianyu 0:d8f4c441e032 1908 }
lixianyu 0:d8f4c441e032 1909
lixianyu 0:d8f4c441e032 1910 u8g_SetDefaultForegroundColor(lrc_u8g);
lixianyu 0:d8f4c441e032 1911 u8g_DrawStr(lrc_u8g, x, (lrc_u8g->height-1) - y, str);
lixianyu 0:d8f4c441e032 1912
lixianyu 0:d8f4c441e032 1913 if ( is_highlight )
lixianyu 0:d8f4c441e032 1914 {
lixianyu 0:d8f4c441e032 1915 u8g_DrawFrame(lrc_u8g, x-1, (lrc_u8g->height-1) - y -MNU_ENTRY_HEIGHT +1, t, MNU_ENTRY_HEIGHT);
lixianyu 0:d8f4c441e032 1916 }
lixianyu 0:d8f4c441e032 1917 }
lixianyu 0:d8f4c441e032 1918
lixianyu 0:d8f4c441e032 1919 void mnu_Draw(void)
lixianyu 0:d8f4c441e032 1920 {
lixianyu 0:d8f4c441e032 1921 uint8_t i;
lixianyu 0:d8f4c441e032 1922 uint8_t t,y;
lixianyu 0:d8f4c441e032 1923 /* calculate hight of the complete menu */
lixianyu 0:d8f4c441e032 1924 y = mnu_max;
lixianyu 0:d8f4c441e032 1925 y++; /* consider also some space for the title */
lixianyu 0:d8f4c441e032 1926 y++; /* consider also some space for the title */
lixianyu 0:d8f4c441e032 1927 y *= MNU_ENTRY_HEIGHT;
lixianyu 0:d8f4c441e032 1928
lixianyu 0:d8f4c441e032 1929 /* calculate how much space will be left */
lixianyu 0:d8f4c441e032 1930 t = u8g_GetHeight(lrc_u8g);
lixianyu 0:d8f4c441e032 1931 t -= y;
lixianyu 0:d8f4c441e032 1932
lixianyu 0:d8f4c441e032 1933 /* topmost pos start half of that empty space from the top */
lixianyu 0:d8f4c441e032 1934 t >>= 1;
lixianyu 0:d8f4c441e032 1935 y = u8g_GetHeight(lrc_u8g);
lixianyu 0:d8f4c441e032 1936 y -= t;
lixianyu 0:d8f4c441e032 1937
lixianyu 0:d8f4c441e032 1938 y -= MNU_ENTRY_HEIGHT;
lixianyu 0:d8f4c441e032 1939 mnu_DrawEntry(y, mnu_title, 0, 0);
lixianyu 0:d8f4c441e032 1940
lixianyu 0:d8f4c441e032 1941 y -= MNU_ENTRY_HEIGHT;
lixianyu 0:d8f4c441e032 1942
lixianyu 0:d8f4c441e032 1943
lixianyu 0:d8f4c441e032 1944 for( i = 0; i < mnu_max; i++ )
lixianyu 0:d8f4c441e032 1945 {
lixianyu 0:d8f4c441e032 1946 y -= MNU_ENTRY_HEIGHT;
lixianyu 0:d8f4c441e032 1947 mnu_DrawEntry(y, mnu_list[i], 0, i == mnu_pos);
lixianyu 0:d8f4c441e032 1948 }
lixianyu 0:d8f4c441e032 1949 }
lixianyu 0:d8f4c441e032 1950
lixianyu 0:d8f4c441e032 1951 void mnu_Step(uint8_t key_cmd)
lixianyu 0:d8f4c441e032 1952 {
lixianyu 0:d8f4c441e032 1953 if ( key_cmd == CHESS_KEY_NEXT )
lixianyu 0:d8f4c441e032 1954 {
lixianyu 0:d8f4c441e032 1955 if ( mnu_pos+1 < mnu_max )
lixianyu 0:d8f4c441e032 1956 mnu_pos++;
lixianyu 0:d8f4c441e032 1957 }
lixianyu 0:d8f4c441e032 1958 else if ( key_cmd == CHESS_KEY_PREV )
lixianyu 0:d8f4c441e032 1959 {
lixianyu 0:d8f4c441e032 1960 if ( mnu_pos > 0 )
lixianyu 0:d8f4c441e032 1961 mnu_pos--;
lixianyu 0:d8f4c441e032 1962 }
lixianyu 0:d8f4c441e032 1963 }
lixianyu 0:d8f4c441e032 1964
lixianyu 0:d8f4c441e032 1965
lixianyu 0:d8f4c441e032 1966
lixianyu 0:d8f4c441e032 1967
lixianyu 0:d8f4c441e032 1968 uint8_t chess_key_code = 0;
lixianyu 0:d8f4c441e032 1969 uint8_t chess_key_cmd = 0;
lixianyu 0:d8f4c441e032 1970 #define CHESS_STATE_MENU 0
lixianyu 0:d8f4c441e032 1971 #define CHESS_STATE_SELECT_START 1
lixianyu 0:d8f4c441e032 1972 #define CHESS_STATE_SELECT_PIECE 2
lixianyu 0:d8f4c441e032 1973 #define CHESS_STATE_SELECT_TARGET_POS 3
lixianyu 0:d8f4c441e032 1974 #define CHESS_STATE_THINKING 4
lixianyu 0:d8f4c441e032 1975 #define CHESS_STATE_GAME_END 5
lixianyu 0:d8f4c441e032 1976 uint8_t chess_state = CHESS_STATE_MENU;
lixianyu 0:d8f4c441e032 1977 uint8_t chess_source_pos = 255;
lixianyu 0:d8f4c441e032 1978 uint8_t chess_target_pos = 255;
lixianyu 0:d8f4c441e032 1979
lixianyu 0:d8f4c441e032 1980 const uint8_t chess_pieces_body_bm[] PROGMEM =
lixianyu 0:d8f4c441e032 1981 {
lixianyu 0:d8f4c441e032 1982 /* PAWN */ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /* 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00, */
lixianyu 0:d8f4c441e032 1983 /* KNIGHT */ 0x00, 0x00, 0x1c, 0x2c, 0x04, 0x04, 0x0e, 0x00,
lixianyu 0:d8f4c441e032 1984 /* BISHOP */ 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0x08, 0x00, 0x00, /* 0x00, 0x00, 0x08, 0x1c, 0x1c, 0x08, 0x00, 0x00, */
lixianyu 0:d8f4c441e032 1985 /* ROOK */ 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x00,
lixianyu 0:d8f4c441e032 1986 /* QUEEN */ 0x00, 0x00, 0x14, 0x1c, 0x08, 0x1c, 0x08, 0x00,
lixianyu 0:d8f4c441e032 1987 /* KING */ 0x00, 0x00, 0x00, 0x08, 0x3e, 0x1c, 0x08, 0x00,
lixianyu 0:d8f4c441e032 1988 };
lixianyu 0:d8f4c441e032 1989
lixianyu 0:d8f4c441e032 1990 #ifdef NOT_REQUIRED
lixianyu 0:d8f4c441e032 1991 /* white pieces are constructed by painting black pieces and cutting out the white area */
lixianyu 0:d8f4c441e032 1992 const uint8_t chess_white_pieces_bm[] PROGMEM =
lixianyu 0:d8f4c441e032 1993 {
lixianyu 0:d8f4c441e032 1994 /* PAWN */ 0x00, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0x1e, 0x00,
lixianyu 0:d8f4c441e032 1995 /* KNIGHT */ 0x00, 0x1c, 0x22, 0x52, 0x6a, 0x0a, 0x11, 0x1f,
lixianyu 0:d8f4c441e032 1996 /* BISHOP */ 0x00, 0x08, 0x14, 0x22, 0x22, 0x14, 0x08, 0x7f,
lixianyu 0:d8f4c441e032 1997 /* ROOK */ 0x00, 0x55, 0x7f, 0x22, 0x22, 0x22, 0x22, 0x7f,
lixianyu 0:d8f4c441e032 1998 /* QUEEN */ 0x00, 0x55, 0x2a, 0x22, 0x14, 0x22, 0x14, 0x7f,
lixianyu 0:d8f4c441e032 1999 /* KING */ 0x08, 0x1c, 0x49, 0x77, 0x41, 0x22, 0x14, 0x7f,
lixianyu 0:d8f4c441e032 2000 };
lixianyu 0:d8f4c441e032 2001 #endif
lixianyu 0:d8f4c441e032 2002
lixianyu 0:d8f4c441e032 2003 const uint8_t chess_black_pieces_bm[] PROGMEM =
lixianyu 0:d8f4c441e032 2004 {
lixianyu 0:d8f4c441e032 2005 /* PAWN */ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x3c, 0x00, /* 0x00, 0x00, 0x0c, 0x1e, 0x1e, 0x0c, 0x1e, 0x00, */
lixianyu 0:d8f4c441e032 2006 /* KNIGHT */ 0x00, 0x1c, 0x3e, 0x7e, 0x6e, 0x0e, 0x1f, 0x1f,
lixianyu 0:d8f4c441e032 2007 /* BISHOP */ 0x00, 0x1c, 0x2e, 0x3e, 0x3e, 0x1c, 0x08, 0x7f, /*0x00, 0x08, 0x1c, 0x3e, 0x3e, 0x1c, 0x08, 0x7f,*/
lixianyu 0:d8f4c441e032 2008 /* ROOK */ 0x00, 0x55, 0x7f, 0x3e, 0x3e, 0x3e, 0x3e, 0x7f,
lixianyu 0:d8f4c441e032 2009 /* QUEEN */ 0x00, 0x55, 0x3e, 0x3e, 0x1c, 0x3e, 0x1c, 0x7f,
lixianyu 0:d8f4c441e032 2010 /* KING -*/ 0x08, 0x1c, 0x49, 0x7f, 0x7f, 0x3e, 0x1c, 0x7f,
lixianyu 0:d8f4c441e032 2011 };
lixianyu 0:d8f4c441e032 2012
lixianyu 0:d8f4c441e032 2013
lixianyu 0:d8f4c441e032 2014 #if defined(DOGXL160_HW_GR)
lixianyu 0:d8f4c441e032 2015 #define BOXSIZE 13
lixianyu 0:d8f4c441e032 2016 #define BOXOFFSET 3
lixianyu 0:d8f4c441e032 2017 #else
lixianyu 0:d8f4c441e032 2018 #define BOXSIZE 8
lixianyu 0:d8f4c441e032 2019 #define BOXOFFSET 1
lixianyu 0:d8f4c441e032 2020 #endif
lixianyu 0:d8f4c441e032 2021
lixianyu 0:d8f4c441e032 2022 u8g_uint_t chess_low_edge;
lixianyu 0:d8f4c441e032 2023 uint8_t chess_boxsize = 8;
lixianyu 0:d8f4c441e032 2024 uint8_t chess_boxoffset = 1;
lixianyu 0:d8f4c441e032 2025
lixianyu 0:d8f4c441e032 2026
lixianyu 0:d8f4c441e032 2027 void chess_DrawFrame(uint8_t pos, uint8_t is_bold)
lixianyu 0:d8f4c441e032 2028 {
lixianyu 0:d8f4c441e032 2029 u8g_uint_t x0, y0;
lixianyu 0:d8f4c441e032 2030
lixianyu 0:d8f4c441e032 2031 x0 = pos;
lixianyu 0:d8f4c441e032 2032 x0 &= 15;
lixianyu 0:d8f4c441e032 2033 if ( lrc_obj.orientation != COLOR_WHITE )
lixianyu 0:d8f4c441e032 2034 x0 ^= 7;
lixianyu 0:d8f4c441e032 2035
lixianyu 0:d8f4c441e032 2036 y0 = pos;
lixianyu 0:d8f4c441e032 2037 y0>>= 4;
lixianyu 0:d8f4c441e032 2038 if ( lrc_obj.orientation != COLOR_WHITE )
lixianyu 0:d8f4c441e032 2039 y0 ^= 7;
lixianyu 0:d8f4c441e032 2040
lixianyu 0:d8f4c441e032 2041 x0 *= chess_boxsize;
lixianyu 0:d8f4c441e032 2042 y0 *= chess_boxsize;
lixianyu 0:d8f4c441e032 2043
lixianyu 0:d8f4c441e032 2044 u8g_SetDefaultForegroundColor(lrc_u8g);
lixianyu 0:d8f4c441e032 2045 u8g_DrawFrame(lrc_u8g, x0, chess_low_edge - y0 - chess_boxsize+1, chess_boxsize, chess_boxsize);
lixianyu 0:d8f4c441e032 2046
lixianyu 0:d8f4c441e032 2047
lixianyu 0:d8f4c441e032 2048 if ( is_bold )
lixianyu 0:d8f4c441e032 2049 {
lixianyu 0:d8f4c441e032 2050 x0--;
lixianyu 0:d8f4c441e032 2051 y0++;
lixianyu 0:d8f4c441e032 2052
lixianyu 0:d8f4c441e032 2053 u8g_DrawFrame(lrc_u8g, x0, chess_low_edge - y0 - chess_boxsize +1, chess_boxsize+2, chess_boxsize+2);
lixianyu 0:d8f4c441e032 2054 }
lixianyu 0:d8f4c441e032 2055 }
lixianyu 0:d8f4c441e032 2056
lixianyu 0:d8f4c441e032 2057
lixianyu 0:d8f4c441e032 2058 void chess_DrawBoard(void)
lixianyu 0:d8f4c441e032 2059 {
lixianyu 0:d8f4c441e032 2060 uint8_t i, j, cp;
lixianyu 0:d8f4c441e032 2061 const uint8_t *ptr; /* pointer into PROGMEM */
lixianyu 0:d8f4c441e032 2062
lixianyu 0:d8f4c441e032 2063 if ( U8G_MODE_GET_BITS_PER_PIXEL(u8g_GetMode(lrc_u8g)) > 1 )
lixianyu 0:d8f4c441e032 2064 {
lixianyu 0:d8f4c441e032 2065 for( i = 0; i < 8; i++ )
lixianyu 0:d8f4c441e032 2066 for( j = 0; j < 8; j++ )
lixianyu 0:d8f4c441e032 2067 {
lixianyu 0:d8f4c441e032 2068 uint8_t x,y;
lixianyu 0:d8f4c441e032 2069 x = i;
lixianyu 0:d8f4c441e032 2070 x*=chess_boxsize;
lixianyu 0:d8f4c441e032 2071 y = j;
lixianyu 0:d8f4c441e032 2072 y*=chess_boxsize;
lixianyu 0:d8f4c441e032 2073 if ( ((i^j) & 1) == 0 )
lixianyu 0:d8f4c441e032 2074 u8g_SetDefaultMidColor(lrc_u8g);
lixianyu 0:d8f4c441e032 2075 else
lixianyu 0:d8f4c441e032 2076 u8g_SetDefaultBackgroundColor(lrc_u8g);
lixianyu 0:d8f4c441e032 2077 u8g_DrawBox(lrc_u8g, x,chess_low_edge-y-chess_boxsize+1,chess_boxsize,chess_boxsize);
lixianyu 0:d8f4c441e032 2078 }
lixianyu 0:d8f4c441e032 2079 //u8g_SetDefaultForegroundColor(lrc_u8g);
lixianyu 0:d8f4c441e032 2080 }
lixianyu 0:d8f4c441e032 2081 else
lixianyu 0:d8f4c441e032 2082 {
lixianyu 0:d8f4c441e032 2083 uint8_t x_offset = 1;
lixianyu 0:d8f4c441e032 2084 u8g_SetDefaultForegroundColor(lrc_u8g);
lixianyu 0:d8f4c441e032 2085 for( i = 0; i < 8*8; i+=8 )
lixianyu 0:d8f4c441e032 2086 {
lixianyu 0:d8f4c441e032 2087 for( j = 0; j < 8*8; j+=8 )
lixianyu 0:d8f4c441e032 2088 {
lixianyu 0:d8f4c441e032 2089 if ( ((i^j) & 8) == 0 )
lixianyu 0:d8f4c441e032 2090 {
lixianyu 0:d8f4c441e032 2091 u8g_DrawPixel(lrc_u8g, j+0+x_offset, chess_low_edge - i-0);
lixianyu 0:d8f4c441e032 2092 u8g_DrawPixel(lrc_u8g, j+0+x_offset, chess_low_edge - i-2);
lixianyu 0:d8f4c441e032 2093 u8g_DrawPixel(lrc_u8g, j+0+x_offset, chess_low_edge - i-4);
lixianyu 0:d8f4c441e032 2094 u8g_DrawPixel(lrc_u8g, j+0+x_offset, chess_low_edge - i-6);
lixianyu 0:d8f4c441e032 2095 u8g_DrawPixel(lrc_u8g, j+2+x_offset, chess_low_edge - i-0);
lixianyu 0:d8f4c441e032 2096 u8g_DrawPixel(lrc_u8g, j+2+x_offset, chess_low_edge - i-6);
lixianyu 0:d8f4c441e032 2097 u8g_DrawPixel(lrc_u8g, j+4+x_offset, chess_low_edge - i-0);
lixianyu 0:d8f4c441e032 2098 u8g_DrawPixel(lrc_u8g, j+4+x_offset, chess_low_edge - i-6);
lixianyu 0:d8f4c441e032 2099 u8g_DrawPixel(lrc_u8g, j+6+x_offset, chess_low_edge - i-0);
lixianyu 0:d8f4c441e032 2100 u8g_DrawPixel(lrc_u8g, j+6+x_offset, chess_low_edge - i-2);
lixianyu 0:d8f4c441e032 2101 u8g_DrawPixel(lrc_u8g, j+6+x_offset, chess_low_edge - i-4);
lixianyu 0:d8f4c441e032 2102 u8g_DrawPixel(lrc_u8g, j+6+x_offset, chess_low_edge - i-6);
lixianyu 0:d8f4c441e032 2103 }
lixianyu 0:d8f4c441e032 2104 }
lixianyu 0:d8f4c441e032 2105 }
lixianyu 0:d8f4c441e032 2106 }
lixianyu 0:d8f4c441e032 2107
lixianyu 0:d8f4c441e032 2108 for ( i = 0; i < 8; i++ )
lixianyu 0:d8f4c441e032 2109 {
lixianyu 0:d8f4c441e032 2110 for ( j = 0; j < 8; j++ )
lixianyu 0:d8f4c441e032 2111 {
lixianyu 0:d8f4c441e032 2112 /* get piece from global board */
lixianyu 0:d8f4c441e032 2113 if ( lrc_obj.orientation == COLOR_WHITE )
lixianyu 0:d8f4c441e032 2114 {
lixianyu 0:d8f4c441e032 2115 cp = lrc_obj.board[i*8+j];
lixianyu 0:d8f4c441e032 2116 }
lixianyu 0:d8f4c441e032 2117 else
lixianyu 0:d8f4c441e032 2118 {
lixianyu 0:d8f4c441e032 2119 cp = lrc_obj.board[(7-i)*8+7-j];
lixianyu 0:d8f4c441e032 2120 }
lixianyu 0:d8f4c441e032 2121 if ( cp_GetPiece(cp) != PIECE_NONE )
lixianyu 0:d8f4c441e032 2122 {
lixianyu 0:d8f4c441e032 2123 ptr = chess_black_pieces_bm;
lixianyu 0:d8f4c441e032 2124 ptr += (cp_GetPiece(cp)-1)*8;
lixianyu 0:d8f4c441e032 2125 u8g_SetDefaultForegroundColor(lrc_u8g);
lixianyu 0:d8f4c441e032 2126 u8g_DrawBitmapP(lrc_u8g, j*chess_boxsize+chess_boxoffset-1, chess_low_edge - (i*chess_boxsize+chess_boxsize-chess_boxoffset), 1, 8, ptr);
lixianyu 0:d8f4c441e032 2127
lixianyu 0:d8f4c441e032 2128 if ( cp_GetColor(cp) == lrc_obj.strike_out_color )
lixianyu 0:d8f4c441e032 2129 {
lixianyu 0:d8f4c441e032 2130 ptr = chess_pieces_body_bm;
lixianyu 0:d8f4c441e032 2131 ptr += (cp_GetPiece(cp)-1)*8;
lixianyu 0:d8f4c441e032 2132 u8g_SetDefaultBackgroundColor(lrc_u8g);
lixianyu 0:d8f4c441e032 2133 u8g_DrawBitmapP(lrc_u8g, j*chess_boxsize+chess_boxoffset-1, chess_low_edge - (i*chess_boxsize+chess_boxsize-chess_boxoffset), 1, 8, ptr);
lixianyu 0:d8f4c441e032 2134 }
lixianyu 0:d8f4c441e032 2135 }
lixianyu 0:d8f4c441e032 2136 }
lixianyu 0:d8f4c441e032 2137 }
lixianyu 0:d8f4c441e032 2138
lixianyu 0:d8f4c441e032 2139 if ( (chess_source_pos & 0x88) == 0 )
lixianyu 0:d8f4c441e032 2140 {
lixianyu 0:d8f4c441e032 2141 chess_DrawFrame(chess_source_pos, 1);
lixianyu 0:d8f4c441e032 2142 }
lixianyu 0:d8f4c441e032 2143
lixianyu 0:d8f4c441e032 2144 if ( (chess_target_pos & 0x88) == 0 )
lixianyu 0:d8f4c441e032 2145 {
lixianyu 0:d8f4c441e032 2146 chess_DrawFrame(chess_target_pos, 0);
lixianyu 0:d8f4c441e032 2147 }
lixianyu 0:d8f4c441e032 2148
lixianyu 0:d8f4c441e032 2149 }
lixianyu 0:d8f4c441e032 2150
lixianyu 0:d8f4c441e032 2151
lixianyu 0:d8f4c441e032 2152 void chess_Thinking(void)
lixianyu 0:d8f4c441e032 2153 {
lixianyu 0:d8f4c441e032 2154 }
lixianyu 0:d8f4c441e032 2155
lixianyu 0:d8f4c441e032 2156 void chess_Init(u8g_t *u8g, uint8_t body_color)
lixianyu 0:d8f4c441e032 2157 {
lixianyu 0:d8f4c441e032 2158 lrc_u8g = u8g;
lixianyu 0:d8f4c441e032 2159
lixianyu 0:d8f4c441e032 2160 chess_low_edge = u8g_GetHeight(lrc_u8g);
lixianyu 0:d8f4c441e032 2161 chess_low_edge--;
lixianyu 0:d8f4c441e032 2162
lixianyu 0:d8f4c441e032 2163
lixianyu 0:d8f4c441e032 2164 if ( U8G_MODE_GET_BITS_PER_PIXEL(u8g_GetMode(lrc_u8g)) == 1 )
lixianyu 0:d8f4c441e032 2165 {
lixianyu 0:d8f4c441e032 2166
lixianyu 0:d8f4c441e032 2167 chess_boxsize = 8;
lixianyu 0:d8f4c441e032 2168 chess_boxoffset = 1;
lixianyu 0:d8f4c441e032 2169 }
lixianyu 0:d8f4c441e032 2170 else
lixianyu 0:d8f4c441e032 2171 {
lixianyu 0:d8f4c441e032 2172
lixianyu 0:d8f4c441e032 2173 /*
lixianyu 0:d8f4c441e032 2174 if ( u8g_GetHeight(lrc_u8g) >= 12*8 )
lixianyu 0:d8f4c441e032 2175 {
lixianyu 0:d8f4c441e032 2176 chess_boxsize = 12;
lixianyu 0:d8f4c441e032 2177 chess_boxoffset = 3;
lixianyu 0:d8f4c441e032 2178 }
lixianyu 0:d8f4c441e032 2179 else */ if ( u8g_GetHeight(lrc_u8g) >= 11*8 )
lixianyu 0:d8f4c441e032 2180 {
lixianyu 0:d8f4c441e032 2181 chess_boxsize = 10;
lixianyu 0:d8f4c441e032 2182 chess_boxoffset = 2;
lixianyu 0:d8f4c441e032 2183 }
lixianyu 0:d8f4c441e032 2184 else
lixianyu 0:d8f4c441e032 2185 {
lixianyu 0:d8f4c441e032 2186 chess_boxsize = 8;
lixianyu 0:d8f4c441e032 2187 chess_boxoffset = 1;
lixianyu 0:d8f4c441e032 2188 }
lixianyu 0:d8f4c441e032 2189
lixianyu 0:d8f4c441e032 2190 if ( u8g_GetHeight(lrc_u8g) > 64 )
lixianyu 0:d8f4c441e032 2191 chess_low_edge -= (u8g_GetHeight(lrc_u8g)-chess_boxsize*8) / 2;
lixianyu 0:d8f4c441e032 2192
lixianyu 0:d8f4c441e032 2193 }
lixianyu 0:d8f4c441e032 2194
lixianyu 0:d8f4c441e032 2195 lrc_obj.strike_out_color = body_color;
lixianyu 0:d8f4c441e032 2196 chess_SetupBoard();
lixianyu 0:d8f4c441e032 2197 }
lixianyu 0:d8f4c441e032 2198
lixianyu 0:d8f4c441e032 2199
lixianyu 0:d8f4c441e032 2200
lixianyu 0:d8f4c441e032 2201 void chess_Draw(void)
lixianyu 0:d8f4c441e032 2202 {
lixianyu 0:d8f4c441e032 2203 if ( chess_state == CHESS_STATE_MENU )
lixianyu 0:d8f4c441e032 2204 {
lixianyu 0:d8f4c441e032 2205 if ( lrc_obj.ply_count == 0)
lixianyu 0:d8f4c441e032 2206 mnu_max = 2;
lixianyu 0:d8f4c441e032 2207 else
lixianyu 0:d8f4c441e032 2208 mnu_max = 4;
lixianyu 0:d8f4c441e032 2209 mnu_Draw();
lixianyu 0:d8f4c441e032 2210 }
lixianyu 0:d8f4c441e032 2211 else
lixianyu 0:d8f4c441e032 2212 {
lixianyu 0:d8f4c441e032 2213 chess_DrawBoard();
lixianyu 0:d8f4c441e032 2214
lixianyu 0:d8f4c441e032 2215 {
lixianyu 0:d8f4c441e032 2216 uint8_t i;
lixianyu 0:d8f4c441e032 2217 uint8_t entries = lrc_obj.chm_pos;
lixianyu 0:d8f4c441e032 2218 if ( entries > 4 )
lixianyu 0:d8f4c441e032 2219 entries = 4;
lixianyu 0:d8f4c441e032 2220
lixianyu 0:d8f4c441e032 2221 u8g_SetFont(lrc_u8g, u8g_font_5x7);
lixianyu 0:d8f4c441e032 2222 u8g_SetDefaultForegroundColor(lrc_u8g);
lixianyu 0:d8f4c441e032 2223 for( i = 0; i < entries; i++ )
lixianyu 0:d8f4c441e032 2224 {
lixianyu 0:d8f4c441e032 2225
lixianyu 0:d8f4c441e032 2226 #if defined(DOGXL160_HW_GR) || defined(DOGXL160_HW_BW)
lixianyu 0:d8f4c441e032 2227 dog_DrawStr(u8g_GetWidth(lrc_u8g)-35, u8g_GetHeight(lrc_u8g)-8*(i+1), font_5x7, cu_GetHalfMoveStr(lrc_obj.chm_pos-entries+i));
lixianyu 0:d8f4c441e032 2228 #else
lixianyu 0:d8f4c441e032 2229 u8g_DrawStr(lrc_u8g, u8g_GetWidth(lrc_u8g)-35, 8*(i+1), cu_GetHalfMoveStr(lrc_obj.chm_pos-entries+i));
lixianyu 0:d8f4c441e032 2230 #endif
lixianyu 0:d8f4c441e032 2231
lixianyu 0:d8f4c441e032 2232 }
lixianyu 0:d8f4c441e032 2233
lixianyu 0:d8f4c441e032 2234 }
lixianyu 0:d8f4c441e032 2235
lixianyu 0:d8f4c441e032 2236 if ( chess_state == CHESS_STATE_SELECT_PIECE )
lixianyu 0:d8f4c441e032 2237 mnu_DrawHome(chess_source_pos == 255);
lixianyu 0:d8f4c441e032 2238 else if ( chess_state == CHESS_STATE_SELECT_TARGET_POS )
lixianyu 0:d8f4c441e032 2239 mnu_DrawHome(chess_target_pos == 255);
lixianyu 0:d8f4c441e032 2240 else
lixianyu 0:d8f4c441e032 2241 mnu_DrawHome(0);
lixianyu 0:d8f4c441e032 2242
lixianyu 0:d8f4c441e032 2243 if ( chess_state == CHESS_STATE_GAME_END )
lixianyu 0:d8f4c441e032 2244 {
lixianyu 0:d8f4c441e032 2245 switch( lrc_obj.lost_side_color )
lixianyu 0:d8f4c441e032 2246 {
lixianyu 0:d8f4c441e032 2247 case COLOR_WHITE:
lixianyu 0:d8f4c441e032 2248 mnu_DrawEntry(u8g_GetHeight(lrc_u8g) / 2-2, "Black wins", 1, 1);
lixianyu 0:d8f4c441e032 2249 break;
lixianyu 0:d8f4c441e032 2250 case COLOR_BLACK:
lixianyu 0:d8f4c441e032 2251 mnu_DrawEntry(u8g_GetHeight(lrc_u8g) / 2-2, "White wins", 1, 1);
lixianyu 0:d8f4c441e032 2252 break;
lixianyu 0:d8f4c441e032 2253 default:
lixianyu 0:d8f4c441e032 2254 mnu_DrawEntry(u8g_GetHeight(lrc_u8g) / 2-2, "Stalemate", 1, 1);
lixianyu 0:d8f4c441e032 2255 break;
lixianyu 0:d8f4c441e032 2256 }
lixianyu 0:d8f4c441e032 2257 }
lixianyu 0:d8f4c441e032 2258 }
lixianyu 0:d8f4c441e032 2259 }
lixianyu 0:d8f4c441e032 2260
lixianyu 0:d8f4c441e032 2261
lixianyu 0:d8f4c441e032 2262 void chess_Step(uint8_t keycode)
lixianyu 0:d8f4c441e032 2263 {
lixianyu 0:d8f4c441e032 2264 if ( keycode == CHESS_KEY_NONE )
lixianyu 0:d8f4c441e032 2265 {
lixianyu 0:d8f4c441e032 2266 chess_key_cmd = chess_key_code;
lixianyu 0:d8f4c441e032 2267 chess_key_code = CHESS_KEY_NONE;
lixianyu 0:d8f4c441e032 2268 }
lixianyu 0:d8f4c441e032 2269 else
lixianyu 0:d8f4c441e032 2270 {
lixianyu 0:d8f4c441e032 2271 chess_key_cmd = CHESS_KEY_NONE;
lixianyu 0:d8f4c441e032 2272 chess_key_code = keycode;
lixianyu 0:d8f4c441e032 2273 }
lixianyu 0:d8f4c441e032 2274 //chess_ComputerMove(2);
lixianyu 0:d8f4c441e032 2275 switch(chess_state)
lixianyu 0:d8f4c441e032 2276 {
lixianyu 0:d8f4c441e032 2277 case CHESS_STATE_MENU:
lixianyu 0:d8f4c441e032 2278 mnu_Step(chess_key_cmd);
lixianyu 0:d8f4c441e032 2279 if ( chess_key_cmd == CHESS_KEY_SELECT )
lixianyu 0:d8f4c441e032 2280 {
lixianyu 0:d8f4c441e032 2281 if ( mnu_pos == 0 )
lixianyu 0:d8f4c441e032 2282 {
lixianyu 0:d8f4c441e032 2283 chess_SetupBoard();
lixianyu 0:d8f4c441e032 2284 lrc_obj.orientation = 0;
lixianyu 0:d8f4c441e032 2285 chess_state = CHESS_STATE_SELECT_START;
lixianyu 0:d8f4c441e032 2286 }
lixianyu 0:d8f4c441e032 2287 else if ( mnu_pos == 1 )
lixianyu 0:d8f4c441e032 2288 {
lixianyu 0:d8f4c441e032 2289 chess_SetupBoard();
lixianyu 0:d8f4c441e032 2290 lrc_obj.orientation = 1;
lixianyu 0:d8f4c441e032 2291 chess_state = CHESS_STATE_THINKING;
lixianyu 0:d8f4c441e032 2292 }
lixianyu 0:d8f4c441e032 2293 else if ( mnu_pos == 2 )
lixianyu 0:d8f4c441e032 2294 {
lixianyu 0:d8f4c441e032 2295 if ( lrc_obj.ply_count >= 2 )
lixianyu 0:d8f4c441e032 2296 {
lixianyu 0:d8f4c441e032 2297 cu_UndoHalfMove();
lixianyu 0:d8f4c441e032 2298 cu_UndoHalfMove();
lixianyu 0:d8f4c441e032 2299 lrc_obj.ply_count-=2;
lixianyu 0:d8f4c441e032 2300 if ( lrc_obj.ply_count == 0 )
lixianyu 0:d8f4c441e032 2301 mnu_pos = 0;
lixianyu 0:d8f4c441e032 2302 }
lixianyu 0:d8f4c441e032 2303 chess_state = CHESS_STATE_SELECT_START;
lixianyu 0:d8f4c441e032 2304 }
lixianyu 0:d8f4c441e032 2305 else if ( mnu_pos == 3 )
lixianyu 0:d8f4c441e032 2306 {
lixianyu 0:d8f4c441e032 2307 chess_state = CHESS_STATE_SELECT_START;
lixianyu 0:d8f4c441e032 2308 }
lixianyu 0:d8f4c441e032 2309 }
lixianyu 0:d8f4c441e032 2310 break;
lixianyu 0:d8f4c441e032 2311 case CHESS_STATE_SELECT_START:
lixianyu 0:d8f4c441e032 2312 chess_ClearMarks();
lixianyu 0:d8f4c441e032 2313 chess_MarkMovable();
lixianyu 0:d8f4c441e032 2314 chess_source_pos = chess_GetNextMarked(255, 0);
lixianyu 0:d8f4c441e032 2315 chess_target_pos = ILLEGAL_POSITION;
lixianyu 0:d8f4c441e032 2316 chess_state = CHESS_STATE_SELECT_PIECE;
lixianyu 0:d8f4c441e032 2317 break;
lixianyu 0:d8f4c441e032 2318
lixianyu 0:d8f4c441e032 2319 case CHESS_STATE_SELECT_PIECE:
lixianyu 0:d8f4c441e032 2320 if ( chess_key_cmd == CHESS_KEY_NEXT )
lixianyu 0:d8f4c441e032 2321 {
lixianyu 0:d8f4c441e032 2322 chess_source_pos = chess_GetNextMarked(chess_source_pos, 0);
lixianyu 0:d8f4c441e032 2323 }
lixianyu 0:d8f4c441e032 2324 else if ( chess_key_cmd == CHESS_KEY_PREV )
lixianyu 0:d8f4c441e032 2325 {
lixianyu 0:d8f4c441e032 2326 chess_source_pos = chess_GetNextMarked(chess_source_pos, 1);
lixianyu 0:d8f4c441e032 2327 }
lixianyu 0:d8f4c441e032 2328 else if ( chess_key_cmd == CHESS_KEY_SELECT )
lixianyu 0:d8f4c441e032 2329 {
lixianyu 0:d8f4c441e032 2330 if ( chess_source_pos == 255 )
lixianyu 0:d8f4c441e032 2331 {
lixianyu 0:d8f4c441e032 2332 chess_state = CHESS_STATE_MENU;
lixianyu 0:d8f4c441e032 2333 }
lixianyu 0:d8f4c441e032 2334 else
lixianyu 0:d8f4c441e032 2335 {
lixianyu 0:d8f4c441e032 2336 chess_ClearMarks();
lixianyu 0:d8f4c441e032 2337 chess_MarkTargetMoves(chess_source_pos);
lixianyu 0:d8f4c441e032 2338 chess_target_pos = chess_GetNextMarked(255, 0);
lixianyu 0:d8f4c441e032 2339 chess_state = CHESS_STATE_SELECT_TARGET_POS;
lixianyu 0:d8f4c441e032 2340 }
lixianyu 0:d8f4c441e032 2341 }
lixianyu 0:d8f4c441e032 2342 break;
lixianyu 0:d8f4c441e032 2343 case CHESS_STATE_SELECT_TARGET_POS:
lixianyu 0:d8f4c441e032 2344 if ( chess_key_cmd == CHESS_KEY_NEXT )
lixianyu 0:d8f4c441e032 2345 {
lixianyu 0:d8f4c441e032 2346 chess_target_pos = chess_GetNextMarked(chess_target_pos, 0);
lixianyu 0:d8f4c441e032 2347 }
lixianyu 0:d8f4c441e032 2348 else if ( chess_key_cmd == CHESS_KEY_PREV )
lixianyu 0:d8f4c441e032 2349 {
lixianyu 0:d8f4c441e032 2350 chess_target_pos = chess_GetNextMarked(chess_target_pos, 1);
lixianyu 0:d8f4c441e032 2351 }
lixianyu 0:d8f4c441e032 2352 else if ( chess_key_cmd == CHESS_KEY_BACK )
lixianyu 0:d8f4c441e032 2353 {
lixianyu 0:d8f4c441e032 2354 chess_ClearMarks();
lixianyu 0:d8f4c441e032 2355 chess_MarkMovable();
lixianyu 0:d8f4c441e032 2356 chess_target_pos = ILLEGAL_POSITION;
lixianyu 0:d8f4c441e032 2357 chess_state = CHESS_STATE_SELECT_PIECE;
lixianyu 0:d8f4c441e032 2358 }
lixianyu 0:d8f4c441e032 2359 else if ( chess_key_cmd == CHESS_KEY_SELECT )
lixianyu 0:d8f4c441e032 2360 {
lixianyu 0:d8f4c441e032 2361 chess_ManualMove(chess_source_pos, chess_target_pos);
lixianyu 0:d8f4c441e032 2362 if ( lrc_obj.is_game_end != 0 )
lixianyu 0:d8f4c441e032 2363 chess_state = CHESS_STATE_GAME_END;
lixianyu 0:d8f4c441e032 2364 else
lixianyu 0:d8f4c441e032 2365 chess_state = CHESS_STATE_THINKING;
lixianyu 0:d8f4c441e032 2366 /* clear marks as some kind of feedback to the user... it simply looks better */
lixianyu 0:d8f4c441e032 2367 chess_source_pos = ILLEGAL_POSITION;
lixianyu 0:d8f4c441e032 2368 chess_target_pos = ILLEGAL_POSITION;
lixianyu 0:d8f4c441e032 2369 chess_ClearMarks();
lixianyu 0:d8f4c441e032 2370 }
lixianyu 0:d8f4c441e032 2371 break;
lixianyu 0:d8f4c441e032 2372 case CHESS_STATE_THINKING:
lixianyu 0:d8f4c441e032 2373 chess_ComputerMove(2);
lixianyu 0:d8f4c441e032 2374 if ( lrc_obj.is_game_end != 0 )
lixianyu 0:d8f4c441e032 2375 chess_state = CHESS_STATE_GAME_END;
lixianyu 0:d8f4c441e032 2376 else
lixianyu 0:d8f4c441e032 2377 chess_state = CHESS_STATE_SELECT_START;
lixianyu 0:d8f4c441e032 2378 break;
lixianyu 0:d8f4c441e032 2379 case CHESS_STATE_GAME_END:
lixianyu 0:d8f4c441e032 2380 if ( chess_key_cmd != CHESS_KEY_NONE )
lixianyu 0:d8f4c441e032 2381 {
lixianyu 0:d8f4c441e032 2382 chess_state = CHESS_STATE_MENU;
lixianyu 0:d8f4c441e032 2383 chess_SetupBoard();
lixianyu 0:d8f4c441e032 2384 }
lixianyu 0:d8f4c441e032 2385 break;
lixianyu 0:d8f4c441e032 2386 }
lixianyu 0:d8f4c441e032 2387
lixianyu 0:d8f4c441e032 2388 }
lixianyu 0:d8f4c441e032 2389
lixianyu 0:d8f4c441e032 2390 #endif
lixianyu 0:d8f4c441e032 2391
lixianyu 0:d8f4c441e032 2392
lixianyu 0:d8f4c441e032 2393