int IsPathClear(enum ChessPiece board[8][8], int oldx, int oldy, int newx, int newy) { int dx = (newx == oldx) ? 0 : ((newx > oldx) ? 1 : -1); int dy = (newy == oldy) ? 0 : ((newy > oldy) ? 1 : -1); int x = oldx; int y = oldy; /* straight lines and diagonals only */ if ((abs(oldx - newx) != abs(oldy - newy)) && (oldx != newx) && (oldy != newy)) { return 0; } while ((x != newx) || (y != newy)) { x += dx; y += dy; if (board[x][y] != CP_EMPTY && !((x == newx) && (y == newy) && (IsPieceWhite(board[newx][newy]) != IsPieceWhite(board[oldx][oldy])))) { return 0; } } return 1; }
int getCenterControlScore(ChessBoard * board, bool white) { int whiteCenterScore = 0; int blackCenterScore = 0; BITBOARD iterateCenterSquares = centerSquares; while(iterateCenterSquares != 0) { short centerSquare = FirstOne(iterateCenterSquares); iterateCenterSquares ^= offset_to_mask(centerSquare); BITBOARD attackBitboard = get_attacksto_bitboard(board, centerSquare); short whiteAttacks = NumOnes(attackBitboard & board->whitePieces); short blackAttacks = NumOnes(attackBitboard & board->blackPieces); short contents = board->boardContents[centerSquare]; if (contents != EMPTY) { if (IsPieceWhite(contents)) whiteAttacks += 2; else blackAttacks += 2; } whiteCenterScore += whiteAttacks * EvalParameters::whiteCenterControlScale[centerSquare]; blackCenterScore += blackAttacks * EvalParameters::blackCenterControlScale[centerSquare]; } if (white) return whiteCenterScore - blackCenterScore; else return blackCenterScore - whiteCenterScore; }
int IsMoveLegal(enum ChessPiece board[8][8], int oldx, int oldy, int newx, int newy, enum ChessCastling *castling, char **enpassanttarget) { enum ChessPiece tempboard[8][8]; char *letters = "abcdefgh"; char *numbers = "87654321"; char move[5]; int iswhitemove = IsPieceWhite(board[oldx][oldy]); if (CanPieceMoveHere(board, oldx, oldy, newx, newy, castling, enpassanttarget)) { /* is this a castling move? Then check the intermediate square */ if (oldx == 4 && oldy == 7 && newy == 7 && (newx == 6 || newx == 2) && board[oldx][oldy] == CP_WKING) { CopyBoard(board, tempboard); if (newx == 6) { strcpy(move, "e8f8"); ExecuteMove(tempboard, move, 0, NULL, NULL); if (!IsPositionLegal(tempboard, !iswhitemove)) { return 0; } } if (newx == 2) { strcpy(move, "e8d8"); ExecuteMove(tempboard, move, 0, NULL, NULL); if (!IsPositionLegal(tempboard, !iswhitemove)) { return 0; } } } if (oldx == 4 && oldy == 7 && newy == 0 && (newx == 6 || newx == 2) && board[oldx][oldy] == CP_BKING) { CopyBoard(board, tempboard); if (newx == 6) { strcpy(move, "e1f1"); ExecuteMove(tempboard, move, 0, NULL, NULL); if (!IsPositionLegal(tempboard, !iswhitemove)) { return 0; } } if (newx == 2) { strcpy(move, "e1d1"); ExecuteMove(tempboard, move, 0, NULL, NULL); if (!IsPositionLegal(tempboard, !iswhitemove)) { return 0; } } } CopyBoard(board, tempboard); move[0] = letters[oldx]; move[1] = numbers[oldy]; move[2] = letters[newx]; move[3] = numbers[newy]; move[4] = '\0'; ExecuteMove(tempboard, move, 0, NULL, NULL); return IsPositionLegal(tempboard, !iswhitemove); } return 0; }
int CanPieceMoveHere(enum ChessPiece board[8][8], int oldx, int oldy, int newx, int newy, enum ChessCastling *castling, char **enpassanttarget) { enum ChessPiece moving = board[oldx][oldy]; enum ChessPiece captured = board[newx][newy]; char *letters = "abcdefgh"; char *numbers = "87654321"; int epx, epy; if (oldx == newx && oldy == newy) { return 0; } if (enpassanttarget && *enpassanttarget) { epx = strchr(letters, (*enpassanttarget)[0]) - letters; epy = strchr(numbers, (*enpassanttarget)[1]) - numbers; } else { epx = -1; epy = -1; } switch(moving) { case CP_WPAWN: { if (!IsPathClear(board, oldx, oldy, newx, newy)) { return 0; } if (oldx == newx) { if (!captured && (newy == oldy - 1 || (newy == 4 && oldy == 6))) { return 1; } } else if ((abs(oldx - newx) == 1) && (newy == oldy - 1)) { if (captured != CP_EMPTY && !IsPieceWhite(captured)) { return 1; } else if (captured == CP_EMPTY && newx == epx && newy == epy) { return 1; } } return 0; } break; case CP_BPAWN: { if (!IsPathClear(board, oldx, oldy, newx, newy)) { return 0; } if (oldx == newx) { if (!captured && (newy == oldy + 1 || (newy == 3 && oldy == 1))) { return 1; } } else if ((abs(oldx - newx) == 1) && (newy == oldy + 1)) { if (captured != CP_EMPTY && IsPieceWhite(captured)) { return 1; } else if (captured == CP_EMPTY && newx == epx && newy == epy) { return 1; } } return 0; } case CP_WKNIGHT: case CP_BKNIGHT: { if (!((abs(oldx - newx) == 2 && abs(oldy - newy) == 1) || (abs(oldx - newx) == 1 && abs(oldy - newy) == 2))) { return 0; } if (captured && IsPieceWhite(captured) == IsPieceWhite(moving)) { return 0; } return 1; } break; case CP_WBISHOP: case CP_BBISHOP: { if (!IsPathClear(board, oldx, oldy, newx, newy)) { return 0; } if (abs(oldx - newx) != abs(oldy - newy)) { return 0; } return 1; } break; case CP_WROOK: case CP_BROOK: { if (!IsPathClear(board, oldx, oldy, newx, newy)) { return 0; } if ((oldx - newx != 0) && (oldy - newy != 0)) { return 0; } return 1; } case CP_WQUEEN: case CP_BQUEEN: { if (!IsPathClear(board, oldx, oldy, newx, newy)) { return 0; } if (((oldx - newx != 0) && (oldy - newy != 0)) && (abs(oldx - newx) != abs(oldy - newy))) { return 0; } return 1; } case CP_WKING: case CP_BKING: { if (!IsPathClear(board, oldx, oldy, newx, newy)) { return 0; } if (abs(oldx - newx) > 1 || abs(oldy - newy) > 1) { /* check for castling */ if (castling) { if (moving == CP_WKING && oldx == 4 && oldy == 7 && newy == 7) { if (newx == 6 && (*castling & CC_WK) != 0) { return 1; } if (newx == 2 && (*castling & CC_WQ) != 0) { return 1; } } if (moving == CP_BKING && oldx == 4 && oldy == 0 && newy == 0) { if (newx == 6 && (*castling & CC_BK) != 0) { return 1; } if (newx == 2 && (*castling & CC_BQ) != 0) { return 1; } } } return 0; } return 1; } break; default: break; } return 0; }