//returns if player with val has some valid move in this configuration bool Alex_Ayerdi::has_valid_move(int val) { for(int i=0; i<8;i++) for(int j=0; j<8; j++) if(move_is_valid(i+1, j+1, val)) return true; return false; }
move_t *fullalg_to_move(board_t *board, char *move_s) { move_t *move; if ((strlen(move_s) < 4) || (strlen(move_s) > 5)) return NULL; if ((move_s[0] < 'a') || (move_s[0] > 'h')) return NULL; if ((move_s[1] < '1') || (move_s[1] > '8')) return NULL; if ((move_s[2] < 'a') || (move_s[2] > 'h')) return NULL; if ((move_s[3] < '1') || (move_s[3] > '8')) return NULL; if ((strlen(move_s) == 5) && (move_s[4] != 'n') && (move_s[4] != 'b') && (move_s[4] != 'r') && (move_s[4] != 'q')) return NULL; move = (move_t *) malloc(sizeof(move_t)); move->source = move_s[0] - 'a' + (move_s[1] - '1') * 8; move->destination = move_s[2] - 'a' + (move_s[3] - '1') * 8; if (strlen(move_s) == 5) { switch (move_s[4]) { case 'n': move->promotion_piece = KNIGHT; break; case 'b': move->promotion_piece = BISHOP; break; case 'r': move->promotion_piece = ROOK; break; case 'q': move->promotion_piece = QUEEN; } move->promotion_piece += board->turn; } else move->promotion_piece = NONE; if (!move_is_valid(board, move)) { free(move); return NULL; } move_set_attr(board, move); return move; }
//executes move if it is valid. Returns false and does not update Alex_Ayerdi otherwise bool Alex_Ayerdi::play_square(int row, int col, int val) { if(!move_is_valid(row, col, val)) return false; squares[row-1][col-1] = val; for(int rinc = -1; rinc <= 1; rinc++) for(int cinc = -1; cinc <= 1; cinc++) { check_or_flip_path(row-1, col-1, rinc, cinc, val, true); } return true; }
/* This function ask a moves, save it, apply it and return 0 if the game is finish (won or tie) */ int next_move(struct game *myGame){ struct move currMove; /* this is need for game_state_transtiction */ // struct state s1; printf("Player: %c\n", myGame->players[myGame->current_player]); /* continue to ask until the move is correct */ while(!move_is_valid(myGame, &currMove)); game_update(myGame, &currMove); // game_state_transition(&myGame->state, &currMove, &s1, myGame); /* update the moves history */ // TODO this can be used as history replay mode // if(update_moves(&currMove) !=0) // return 1; /* print the table */ game_print(myGame); /* check if there is a winner or it is tie */ return is_finish(myGame, &currMove); }
static int is_mated(board_t *board, int side) { int src, dest; move_t move; for (src = 0; src < 64; src++) if (COLOUR(board->square[src]) == side) for (dest = 0; dest < 64; dest++) { move.source = src; move.destination = dest; if ((PIECE(board->square[src]) == PAWN) && ((dest < 8) || (dest >= 56))) move.promotion_piece = QUEEN + side; else move.promotion_piece = NONE; if (move_is_valid(board, &move)) return 0; } return 1; }
static move_t *find_unique_move(board_t *board, san_move_t *san_move) { int square; int piece; int found = 0; move_t move, *retval; if (san_move->type == SAN_QUEENSIDE_CASTLE) { san_move->source_file = 4; san_move->source_rank = (board->turn == WHITE ? 0 : 7); san_move->destination = (board->turn == WHITE ? 2 : 58); piece = KING; } else if (san_move->type == SAN_KINGSIDE_CASTLE) { san_move->source_file = 4; san_move->source_rank = (board->turn == WHITE ? 0 : 7); san_move->destination = (board->turn == WHITE ? 6 : 62); piece = KING; } else piece = ui_piece(san_move->piece); piece += board->turn; for (square = 0; square < 64; square++) { move_t m; if (board->square[square] != piece) continue; /* We found a piece. */ if (san_move->source_file != SAN_NOT_SPECIFIED) if (san_move->source_file != square % 8) continue; if (san_move->source_rank != SAN_NOT_SPECIFIED) if (san_move->source_rank != square / 8) continue; m.source = square; m.destination = san_move->destination; m.promotion_piece = ui_piece(san_move->promotion_piece); if (m.promotion_piece != NONE) m.promotion_piece += board->turn; if (move_is_valid(board, &m)) { move = m; found++; if (found > 1) return NULL; } } if (!found) { DBG_ERROR("failed to find a legal move corresponding to SAN move"); return NULL; } retval = (move_t *) malloc(sizeof(move_t)); *retval = move; return retval; }
int Alex_Ayerdi::eval(int cpuval) { // originally used score, but it led to bad ai // instead we evaluate based maximizing the // difference between computer's available move count // and the player's. Additionally, corners will be // considered as specially beneficial since they cannot ever be // flipped. int score = 0; // evaluation score // count available moves for computer and player int mc = 0; int mp = 0; for (int i=1; i<9;i++) { for (int j=1; j<9; j++) { if (move_is_valid(i, j, cpuval)) mc++; if (move_is_valid(i, j, -1*cpuval)) mp++; } } // add the difference to score (scaled) score += 20*(mc - mp); // the number is just some scale determined through playing //score += 7*mc; /* // additionally, if mp is 0 this is real good so add some more points, // and if mc is 0 this is real bad so subtract more points // because of skipped turns if (mp == 0) score += 50; if (mc == 0) score -= 50; */ // count corners for computer and player int cc = 0; int cp = 0; if (get_square(1, 1) == cpuval) cc++; else if (get_square(1, 1) == -1*cpuval) cp++; if (get_square(1, 8) == cpuval) cc++; else if (get_square(1, 8) == -1*cpuval) cp++; if (get_square(8, 1) == cpuval) cc++; else if (get_square(8, 1) == -1*cpuval) cp++; if (get_square(8, 8) == cpuval) cc++; else if (get_square(8, 8) == -1*cpuval) cp++; // add the difference to score (scaled) score += 200*(cc - cp); /* // squares adjacent to corners on edges also useful, but not as much since it could lead to a corner int ac = 0; int ap = 0; if (get_square(1, 2) == cpuval) ac++; else if (get_square(1, 2) == -1*cpuval) ap++; if (get_square(2, 1) == cpuval) ac++; else if (get_square(2, 1) == -1*cpuval) ap++; if (get_square(1, 7) == cpuval) ac++; else if (get_square(1, 7) == -1*cpuval) ap++; if (get_square(2, 8) == cpuval) ac++; else if (get_square(2, 8) == -1*cpuval) ap++; if (get_square(7, 1) == cpuval) ac++; else if (get_square(7, 1) == -1*cpuval) ap++; if (get_square(8, 2) == cpuval) ac++; else if (get_square(8, 2) == -1*cpuval) ap++; if (get_square(7, 8) == cpuval) ac++; else if (get_square(7, 8) == -1*cpuval) ap++; if (get_square(8, 7) == cpuval) ac++; else if (get_square(8, 7) == -1*cpuval) ap++; score += 30*(ac - ap); // scale so bigger depths are worth more score += 10*depth; */ // limit the amount of space around our pieces so we don't surround as much (which leads to big gains endgame for opponent) int sc = 0; int sp = 0; // counts for open spaces neighboring a player/comp's pieces for (int i=1; i<9;i++) { for (int j=1; j<9; j++) { if (get_square(i, j) == cpuval) { //add count to sc sc += free_neighbors(i, j); } if (get_square(i, j) == -1*cpuval) { //add count to sp sp += free_neighbors(i, j); } } } score -= 10*(sc - sp); // subtract because we are trying to minimize it return score; }
static int do_move(move_t *move, int ui_update) { char *move_s, *move_f, *move_san; board_t new_board; if (!move_is_valid(history->last->board, move)) { DBG_WARN("Move is illegal"); return 0; } move_set_attr(history->last->board, move); new_board = *history->last->board; move_s = move_to_fullalg(&new_board, move); move_list_play(&fullalg_list, move_s); move_san = move_to_san(&new_board, move); move_f = san_to_fan(&new_board, move_san); DBG_LOG("Processing move %s (%s)", move_s, move_san); move_list_play(&san_list, move_san); move_list_play(&fan_list, move_f); free(move_san); free(move_f); free(move_s); make_move(&new_board, move); if (move->state == MOVE_CHECK) new_board.state = BOARD_CHECK; else if (move->state == MOVE_CHECKMATE) new_board.state = BOARD_CHECKMATE; else new_board.state = BOARD_NORMAL; history_play(history, move, &new_board); if (ui_update) ui->update(history->view->board, move); if (new_board.state == MOVE_CHECKMATE) { history->result = malloc(sizeof(result_t)); if (new_board.turn == WHITE) { history->result->code = RESULT_BLACK_WINS; history->result->reason = strdup("Black mates"); } else { history->result->code = RESULT_WHITE_WINS; history->result->reason = strdup("White mates"); } if (ui_update) ui->show_result(history->result); } else if (new_board.state == MOVE_STALEMATE) { history->result = malloc(sizeof(result_t)); history->result->code = RESULT_DRAW; history->result->reason = strdup("Stalemate"); if (ui_update) ui->show_result(history->result); } return 1; }