Ejemplo n.º 1
0
static void
decide_move(void)
{
    mtx_lock(&game_mutex);

    if (game_started && !is_end() && !is_force_mode) {
        if (game_started && has_single_response()) {
            move m = get_single_response();

            print_computer_move(m);
            add_move(m);
            engine_move_count_inc();
        }
        else {
            move m = book_get_move(book, current_position());
            if (m != none_move) {
                print_computer_move(m);
                add_move(m);
                engine_move_count_inc();
            }
            else {
                set_thinking_done_cb(computer_move,
                                     ++callback_key);
                start_thinking();
            }
        }
    }
    else {
        game_started = false;
    }

    mtx_unlock(&game_mutex);
}
/*
 * Add all pseudo-legal non-capturing moves that the given piece (N/B/Q/K)
 * can make, with the exception of castles.
 */
static void generate_piece_noncaptures(const position_t* pos,
        square_t from,
        piece_t piece,
        move_t** moves_head)
{
    move_t* moves = *moves_head;
    square_t to;
    if (piece_slide_type(piece) == NONE) {
        // not a sliding piece, just iterate over dest. squares
        for (const direction_t* delta = piece_deltas[piece]; *delta; ++delta) {
            to = from + *delta;
            if (pos->board[to] != EMPTY) continue;
            moves = add_move(pos,
                    create_move(from, to, piece, NONE),
                    moves);
        }
    } else {
        // a sliding piece, keep going until we hit something
        for (const direction_t* delta = piece_deltas[piece]; *delta; ++delta) {
            to = from + *delta;
            while (pos->board[to] == EMPTY) {
                moves = add_move(pos,
                        create_move(from, to, piece, NONE),
                        moves);
                to += *delta;
            }
        }
    }
    *moves_head = moves;
}
Ejemplo n.º 3
0
void get_king_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	Move* res = NULL;
	Move* res_head = res;
	Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } };
	Pos curr;
	int found_ahead;

	for (int p = 0; p < 4; p++){
		curr = pos[p];
		while (is_valid_pos(curr) && board[curr.col][curr.row] == EMPTY){
			add_move(piece, &curr, 1);
			curr = get_next_diag(piece, curr);
			// BUG - once dests_num == 1 and |dest-start| != 1 add_moves thinks its 1 capture and not a simple move..
		}
		if (is_valid_pos(curr) && is_opposite(player, board[curr.col][curr.row])){
			char tmp = board[curr.row][curr.col];
			board[curr.row][curr.col] = EMPTY;
			Pos new_piece = get_next_diag(piece, curr);
			if (is_valid_pos(new_piece) && board[new_piece.row][new_piece.col] == EMPTY){
				found_ahead = get_capture_moves(piece, new_piece, board, player, 1, &new_piece);
				if (found_ahead == 0) add_move(piece, &new_piece, 1);
			}
			board[curr.row][curr.col] = tmp;
		}
	}
}
Ejemplo n.º 4
0
// finds all moves of a single king piece
void get_king_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } };
	Pos curr, new_piece;
	int found_ahead = -1;

	for (int p = 0; p < 4; p++){
		curr = pos[p];
		while (is_valid_pos(curr) && board[curr.col][curr.row] == EMPTY){
			add_move(piece, &curr, 0);
			curr = get_next_diag(piece, curr);
		}
		if (is_valid_pos(curr) && is_opposite(player, board[curr.col][curr.row])){
			char tmp = board[curr.col][curr.row];
			board[curr.col][curr.row] = EMPTY;
			board[piece.col][piece.row] = EMPTY;
			new_piece = get_next_diag(piece, curr);
			if (is_valid_pos(new_piece) && board[new_piece.col][new_piece.row] == EMPTY){
				found_ahead = get_capture_moves(piece, new_piece, board, player, 1, &new_piece);
				if (found_ahead == 0) add_move(piece, &new_piece, 1);
			}
			board[curr.col][curr.row] = tmp;
			board[piece.col][piece.row] = curr_piece;
		}
	}
}
Ejemplo n.º 5
0
int get_capture_moves(Pos start, Pos piece, char board[BOARD_SIZE][BOARD_SIZE], COLOR player, int count, Pos* dests){
	Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } };
	int found_now = 0, found_ahead;
	for (int p = 0; p < 4; p++)
		if (is_valid_pos(pos[p]) && is_opposite(player, board[pos[p].col][pos[p].row])){
			Pos new_piece = get_next_diag(piece, pos[p]);
			if (is_valid_pos(new_piece) && board[new_piece.col][new_piece.row] == EMPTY){
				found_now++;
				char tmp = board[pos[p].col][pos[p].row];
				board[pos[p].col][pos[p].row] = EMPTY;
				Pos* new_dests = malloc(sizeof(Pos) * (count + 1));
				for (int i = 0; i < count; i++){
					new_dests[i].row = dests[i].row;
					new_dests[i].col = dests[i].col;
				}
				new_dests[count].row = new_piece.row;
				new_dests[count].col = new_piece.col;
				found_ahead = get_capture_moves(start, new_piece, board, player, count + 1, new_dests);
				if (found_ahead == 0){
					add_move(start, new_dests, count + 1);
					free(new_dests);
				}
				board[pos[p].row][pos[p].col] = tmp;
			}
		}
	return found_now;
}
Ejemplo n.º 6
0
static int
computer_move(uintmax_t key)
{
    if (key != callback_key)
        return -1;

    move m;

    mtx_lock(&game_mutex);

    if (engine_get_best_move(&m) != 0) {
        puts("-");
    }
    else {
        print_computer_move(m);
        if (exit_on_done)
            exit(EXIT_SUCCESS);
        add_move(m);
        engine_move_count_inc();
    }

    mtx_unlock(&game_mutex);

    return 0;
}
Ejemplo n.º 7
0
inline void bishop_move(struct position *pos, struct move_array *m,
            unsigned char bishops)
{
    uint64_t bishop_pos = pos->pieces[bishops];
    uint64_t moves;
    unsigned char index_from, index_to;
    for (int i = 0; i < 10; i++) {  // up to 10 bishops of same color on the board, (for loop for compiler loop unrolling)
        if ((index_from = ffsll(bishop_pos)) != 0) {
            index_from--;
            moves = BishopMoves[index_from][magictransform((pos->allpieces & BishopMasks[index_from]), BishopMagic[index_from], BishopMagicSize [index_from])] & ~pos-> sumpieces[bishops & COLOR];
            for (int i = 0; i < 14; i++) {
                if ((index_to = ffsll(moves)) != 0) {
                    index_to--;
                    add_move(m, index_from, index_to, bishops, find_piece(pos, index_to));
                    moves &= notlinboard[index_to];
                } else {
                    break;
                }
            }
            bishop_pos &= notlinboard[index_from];
        } else {
            break;
        }
    }
}
Ejemplo n.º 8
0
void	move_rotate_both(t_env *e)
{
	int	c;

	c = 0;
	c += move_rotate_a(e, BOTH);
	c += move_rotate_b(e, BOTH);
	c != 0 ? add_move(e, "rr") : 0;
}
/*
 * Generate all non-capturing, non-promoting pawn moves.
 */
static void generate_pawn_quiet_moves(const position_t* pos,
        square_t from,
        piece_t piece,
        move_t** moves_head)
{
    color_t side = pos->side_to_move;
    square_t to;
    rank_t r_rank = relative_rank[side][square_rank(from)];
    move_t* moves = *moves_head;
    to = from + pawn_push[side];
    if (r_rank == RANK_7 || pos->board[to] != EMPTY) return;
    moves = add_move(pos, create_move(from, to, piece, EMPTY), moves);
    to += pawn_push[side];
    if (r_rank == RANK_2 && pos->board[to] == EMPTY) {
        // initial two-square push
        moves = add_move(pos,
                create_move(from, to, piece, EMPTY),
                moves);
    }
    *moves_head = moves;
}
Ejemplo n.º 10
0
void	swap_b(t_e *env)
{
	int tmp;

	if (env->b_s != NULL && env->b_s->next != NULL)
	{
		tmp = env->b_s->nbr;
		env->b_s->nbr = env->b_s->next->nbr;
		env->b_s->next->nbr = tmp;
		env->nb_op++;
		add_move(env, "sb");
	}
}
Ejemplo n.º 11
0
static void
operator_move(move m)
{
    stop_thinking();

    mtx_lock(&game_mutex);

    if (!is_force_mode)
        game_started = true;
    add_move(m);
    decide_move();

    mtx_unlock(&game_mutex);
}
Ejemplo n.º 12
0
void	move_push_b(t_env *e)
{
	t_stack	*temp;

	if (e->stack_a != NULL)
	{
		temp = e->stack_a;
		e->stack_a = e->stack_a->next;
		temp->next = e->stack_b;
		e->stack_b = temp;
		e->stack_b->next == NULL ? e->stack_end_b = e->stack_b : 0;
		e->stack_a == NULL ? e->stack_end_a = NULL : 0;
		add_move(e, "pb");
	}
}
Ejemplo n.º 13
0
int		move_rotate_b(t_env *e, int move)
{
	t_stack	*tmp;

	if (e->stack_b != NULL && e->stack_a->next != NULL)
	{
		tmp = e->stack_b;
		e->stack_b = e->stack_b->next;
		tmp->next = NULL;
		e->stack_end_b->next = tmp;
		e->stack_end_b = tmp;
		move == ONE ? add_move(e, "rb") : 0;
		return (1);
	}
	return (0);
}
Ejemplo n.º 14
0
inline void king_move(struct position *pos, struct move_array *m, unsigned char king)
{
    unsigned char from = ffsll(pos->pieces[king]) - 1;
    uint64_t moves = kingmoves[from] & ~pos->sumpieces[king & COLOR];

    unsigned char index;
    for (int i = 0; i < 8; i++) {
        if ((index = ffsll(moves)) != 0) {
            index--;
            add_move(m, from, index, king, find_piece(pos, index));
            moves &= notlinboard[index];
        } else {
            break;
        }
    }
}
Ejemplo n.º 15
0
int		move_rotate_a(t_env *e, int move)
{
	t_stack	*tmp;

	if (e->stack_a != NULL && e->stack_a->next != NULL)
	{
		tmp = e->stack_a;
		e->stack_a = e->stack_a->next;
		tmp->next = NULL;
		e->stack_end_a->next = tmp;
		e->stack_end_a = tmp;
		move == ONE ? add_move(e, "ra") : 0;
		return (1);
	}
	return (0);
}
Ejemplo n.º 16
0
/* Choose a digit for the given square.
 * The starting digit is passed as a parameter.
 * Returns -1 if no choice possible.
 */
static
int
choose( int idx, int digit )
{
    rb->yield();

    for( ; digit <= 9 ; ++digit )
        if( !DISALLOWED( idx, digit ) )
        {
            board[ idx ] = SET_DIGIT( digit );
            update( idx );
            add_move( idx, digit, CHOICE );
            return digit;
        }

    return -1;
}
Ejemplo n.º 17
0
/* Fill square with given digit, and update state.
 * Returns 0 on success, else -1 on error (i.e. invalid fill)
 */
static
int
fill( int idx, int digit )
{
    assert( 0 != digit );

    if( !IS_EMPTY( idx ) )
        return ( DIGIT( idx ) == digit ) ? 0 : -1;

    if( DISALLOWED( idx, digit ) )
        return -1;

    board[ idx ] = SET_DIGIT( digit );
    update( idx );
    add_move( idx, digit, 0 );

    return 0;
}
/*
 * Add all pseudo-legal non-capturing promotions.
 */
static int generate_promotions(const position_t* pos, move_t* moves)
{
    move_t* moves_head = moves;
    color_t side = pos->side_to_move;
    piece_t piece = create_piece(side, PAWN);
    for (int i = 0; i < pos->num_pawns[side]; ++i) {
        square_t from = pos->pawns[side][i];
        rank_t r_rank = relative_rank[side][square_rank(from)];
        if (r_rank < RANK_7) continue;
        square_t to = from + pawn_push[side];
        if (pos->board[to]) continue;
        for (piece_type_t type=KNIGHT; type<=QUEEN; ++type) {
            moves = add_move(pos,
                    create_move_promote(from, to, piece, EMPTY, type),
                    moves);
        }
    }
    *moves = 0;
    return (moves-moves_head);
}
/*
 * Add all pseudo-legal captures that the given pawn can make.
 */
static void generate_pawn_captures(const position_t* pos,
        square_t from,
        piece_t piece,
        move_t** moves_head)
{
    color_t side = pos->side_to_move;
    int cap_left = side == WHITE ? 15 : -15;
    int cap_right = side == WHITE ? 17 : -17;
    square_t to;
    rank_t r_rank = relative_rank[side][square_rank(from)];
    move_t* moves = *moves_head;
    if (r_rank < RANK_7) {
        // non-promote captures
        to = from + cap_left;
        if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
            moves = add_move(pos, create_move(from, to, piece,
                    pos->board[to]), moves);
        } else if (to == pos->ep_square && pos->board[to] == EMPTY) {
            moves = add_move(pos, create_move_enpassant(from, to, piece,
                    pos->board[to + pawn_push[side^1]]), moves);
        }
        to = from + cap_right;
        if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
            moves = add_move(pos, create_move(from, to, piece,
                    pos->board[to]), moves);
        } else if (to == pos->ep_square && pos->board[to] == EMPTY) {
            moves = add_move(pos, create_move_enpassant(from, to, piece,
                    pos->board[to + pawn_push[side^1]]), moves);
        }
    } else {
        // capture/promotes
        to = from + cap_left;
        if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
            for (piece_t promoted=QUEEN; promoted > PAWN; --promoted) {
                moves = add_move(pos, create_move_promote(from, to, piece,
                        pos->board[to], promoted), moves);
            }
        }
        to = from + cap_right;
        if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
            for (piece_t promoted=QUEEN; promoted > PAWN; --promoted) {
                moves = add_move(pos, create_move_promote(from, to, piece,
                        pos->board[to], promoted), moves);
            }
        }
    }
    *moves_head = moves;
}
Ejemplo n.º 20
0
void get_man_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	Move* res = NULL;
	Move* res_head = res;
	Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } };
	int direction = 1, found_ahead;
	if (player == BLACK) direction = -1;

	for (int p = 0; p < 4; p++){
		if (is_valid_pos(pos[p]) && pos[p].row == piece.row + direction && board[pos[p].col][pos[p].row] == EMPTY) add_move(piece, &pos[p], 1);
		else if (is_valid_pos(pos[p]) && is_opposite(player, board[pos[p].col][pos[p].row])){
			char tmp = board[pos[p].row][pos[p].col];
			board[pos[p].row][pos[p].col] = EMPTY;
			Pos new_piece = get_next_diag(piece, pos[p]);
			if (is_valid_pos(new_piece) && board[new_piece.row][new_piece.col] == EMPTY){
				found_ahead = get_capture_moves(piece, new_piece, board, player, 1, &new_piece);
				if (found_ahead == 0) add_move(piece, &new_piece, 1);
			}
			board[pos[p].row][pos[p].col] = tmp;
		}
	}
}
Ejemplo n.º 21
0
void get_moves_by_piece(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	Pos* tmp_dests;
	switch (board[piece.col][piece.row]){
	case WHITE_B: case BLACK_B:
		get_bishop_moves(board, player, piece);
		return;
	case WHITE_R: case BLACK_R:
		get_rook_moves(board, player, piece);
		return;
	case WHITE_Q: case BLACK_Q:
		get_bishop_moves(board, player, piece);
		get_rook_moves(board, player, piece);
		return;
	case BLACK_P: case WHITE_P:
		get_pawn_moves(board, player, piece);
		return;
	case WHITE_K: case BLACK_K:
		tmp_dests = (Pos[8]) { { piece.col - 1, piece.row - 1 }, { piece.col - 1, piece.row }, { piece.col - 1, piece.row + 1 },
		{ piece.col + 1, piece.row - 1 }, { piece.col + 1, piece.row }, { piece.col + 1, piece.row + 1 },
		{ piece.col, piece.row - 1 }, { piece.col, piece.row + 1 }
		};
		break;
	case WHITE_N: case BLACK_N:
		tmp_dests = (Pos[8]) { { piece.col - 2, piece.row - 1 }, { piece.col - 2, piece.row + 1 },
		{ piece.col + 2, piece.row - 1 }, { piece.col + 2, piece.row + 1 },
		{ piece.col - 1, piece.row - 2 }, { piece.col + 1, piece.row - 2 },
		{ piece.col - 1, piece.row + 2 }, { piece.col + 1, piece.row + 2 }};
		break;
	default: return;
	}
	for (int i = 0; i < 8; i++){
		if (is_valid_pos(tmp_dests[i])){
			if (board[tmp_dests[i].col][tmp_dests[i].row] == EMPTY || is_opposite(player, board[tmp_dests[i].col][tmp_dests[i].row])){
				add_move(piece, tmp_dests[i], 0);
			}
		}
	}
	return;
}
Ejemplo n.º 22
0
inline void knight_move(struct position *pos, struct move_array *m, unsigned char knights)
{
    uint64_t knight_pos = pos->pieces[knights];
    uint64_t moves;
    unsigned char index_from, index_to;
    for (int i = 0; i < 10; i++) {  // can have up to 10 knights of same color on the board, (for loop for compiler loop unrolling)
        if ((index_from = ffsll(knight_pos)) != 0) {
            index_from--;
            moves = knightmoves[index_from] & ~pos->sumpieces[knights & COLOR];
            for (int i = 0; i < 8; i++) {
                if ((index_to = ffsll(moves)) != 0) {
                    index_to--;
                    add_move(m, index_from, index_to, knights, find_piece(pos, index_to));
                    moves &= notlinboard[index_to];
                } else {
                    break;
                }
            }
            knight_pos &= notlinboard[index_from];
        } else {
            break;
        }
    }
}
Ejemplo n.º 23
0
void get_pawn_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	int direction = board[piece.col][piece.row] == BLACK_P ? -1 : 1;
	int pawn_row = board[piece.col][piece.row] == BLACK_P ? 6 : 1;

	Pos dest;
	dest.col = piece.col;
	dest.row = piece.row + direction;

	if (is_valid_pos(dest)){
		if (board[dest.col][dest.row] == EMPTY){
			add_move(piece, dest, 0);
			if (is_EOB(dest, player)) for (int i = 1; i < 5; i++) add_move(piece, dest, get_piece_by_type(i, player));
		}
	}
	if (piece.row == pawn_row){
		dest.row = piece.row + (2 * direction);
		if (is_valid_pos(dest)){
			if (board[dest.col][dest.row] == EMPTY && board[piece.col][piece.row + direction] == EMPTY) add_move(piece, dest, 0);
		}
	}
	dest.col = piece.col + 1;
	dest.row = piece.row + direction;
	if (is_valid_pos(dest)){
		if (is_opposite(player, board[dest.col][dest.row])){
			add_move(piece, dest, 0);
			if (is_EOB(dest, player)) for (int i = 1; i < 5; i++) add_move(piece, dest, get_piece_by_type(i, player));
		}
	}
	dest.col = piece.col - 1;
	if (is_valid_pos(dest)){
		if (is_opposite(player, board[dest.col][dest.row])){
			add_move(piece, dest, 0);
			if (is_EOB(dest, player)) for (int i = 1; i < 5; i++) add_move(piece, dest, get_piece_by_type(i, player));
		}
	}
}
Ejemplo n.º 24
0
inline void pawn_move(struct position *pos, struct move_array *m, unsigned char pawns)
{
    uint64_t pawn_pos = pos->pieces[pawns];
    uint64_t moves;
    unsigned char index_to;
    switch (pawns & COLOR) {
    case WHITE:
        // nonpromotion forward moves 
        moves = moveN(pawn_pos) & ~pos->allpieces & ~rank[7];
        for (int i = 0; i < 8; i++) {
            if ((index_to = ffsll(moves)) != 0) {
                index_to--;
                add_move(m, index_to + S, index_to, pawns, nopiece_n);
                moves &= notlinboard[index_to];
            } else {
                break;
            }
        }

        // forward 2 moves 
        pawn_pos = pos->pieces[pawns];
        moves = moveN(moveN(pawn_pos) & ~pos->allpieces) & ~pos->allpieces & rank[3];
        for (int i = 0; i < 8; i++) {
            if ((index_to = ffsll(moves)) != 0) {
                index_to--;
                add_move_forward2(m, index_to + S + S, index_to, pawns, nopiece_n);
                moves &= notlinboard[index_to];
            } else {
                break;
            }
        }

        // nonpromotion attack west moves
        pawn_pos = pos->pieces[pawns];
        moves = moveNW(pawn_pos) & (pos->bpieces | ep_squares[1][pos->ep]) & ~file[7] & ~rank[7];
        for (int i = 0; i < 8; i++) {
            if ((index_to = ffsll(moves)) != 0) {
                index_to--;
                add_move(m, index_to + SE, index_to, pawns, find_piece_ep(pos, index_to));
                moves &= notlinboard[index_to];
            } else {
                break;
            }
        }

        // nonpromotion attack east moves
        pawn_pos = pos->pieces[pawns];
        moves = moveNE(pawn_pos) & (pos->bpieces | ep_squares[1][pos->ep]) & ~file[0] & ~rank[7];
        for (int i = 0; i < 8; i++) {
            if ((index_to = ffsll(moves)) != 0) {
                index_to--;
                add_move(m, index_to + SW, index_to, pawns, find_piece_ep(pos, index_to));
                moves &= notlinboard[index_to];
            } else {
                break;
            }
        }

        pawn_pos = pos->pieces[pawns];
        if ((pawn_pos & rank[6]) == 0) {    // no promotion possibilities
            return;
        } else {
            // promotion forward moves
            moves = moveN(pawn_pos) & ~pos->allpieces & rank[7];
            for (int i = 0; i < 8; i++) {
                if ((index_to = ffsll(moves)) != 0) {
                    index_to--;
                    add_promotion_move(m, index_to + S, index_to, pawns, nopiece_n);
                    moves &= notlinboard[index_to];
                } else {
                    break;
                }
            }

            // promotion attack west moves
            pawn_pos = pos->pieces[pawns];
            moves = moveNW(pawn_pos) & pos->bpieces & ~file[7] & rank[7];
            for (int i = 0; i < 8; i++) {
                if ((index_to = ffsll(moves)) != 0) {
                    index_to--;
                    add_promotion_move(m, index_to + SE, index_to, pawns, find_piece(pos, index_to));
                    moves &= notlinboard[index_to];
                } else {
                    break;
                }
            }

            // promotion attack east moves
            pawn_pos = pos->pieces[pawns];
            moves = moveNE(pawn_pos) & pos->bpieces & ~file[0] & rank[7];
            for (int i = 0; i < 8; i++) {
                if ((index_to = ffsll(moves)) != 0) {
                    index_to--;
                    add_promotion_move(m, index_to + SW, index_to, pawns, find_piece(pos, index_to));
                    moves &= notlinboard[index_to];
                } else {
                    break;
                }
            }
        }
        break;
    default: // black
        // nonpromotion forward moves 
        moves = moveS(pawn_pos) & ~pos->allpieces & ~rank[0];
        for (int i = 0; i < 8; i++) {
            if ((index_to = ffsll(moves)) != 0) {
                index_to--;
                add_move(m, index_to + N, index_to, pawns, nopiece_n);
                moves &= notlinboard[index_to];
            } else {
                break;
            }
        }

        // forward 2 moves 
        pawn_pos = pos->pieces[pawns];
        moves = moveS(moveS(pawn_pos) & ~pos->allpieces) & ~pos->allpieces & rank[4];
        for (int i = 0; i < 8; i++) {
            if ((index_to = ffsll(moves)) != 0) {
                index_to--;
                add_move_forward2(m, index_to + N + N, index_to, pawns, nopiece_n);
                moves &= notlinboard[index_to];
            } else {
                break;
            }
        }

        // nonpromotion attack west moves
        pawn_pos = pos->pieces[pawns];
        moves = moveSW(pawn_pos) & (pos->wpieces | ep_squares[0][pos->ep]) & ~file[7] & ~rank[0];
        for (int i = 0; i < 8; i++) {
            if ((index_to = ffsll(moves)) != 0) {
                index_to--;
                add_move(m, index_to + NE, index_to, pawns, find_piece_ep(pos, index_to));
                moves &= notlinboard[index_to];
            } else {
                break;
            }
        }

        // nonpromotion attack east moves
        pawn_pos = pos->pieces[pawns];
        moves = moveSE(pawn_pos) & (pos->wpieces | ep_squares[0][pos->ep]) & ~file[0] & ~rank[0];
        for (int i = 0; i < 8; i++) {
            if ((index_to = ffsll(moves)) != 0) {
                index_to--;
                add_move(m, index_to + NW, index_to, pawns, find_piece_ep(pos, index_to));
                moves &= notlinboard[index_to];
            } else {
                break;
            }
        }

        pawn_pos = pos->pieces[pawns];
        if ((pawn_pos & rank[1]) == 0) {    // no promotion possibilities
            return;
        } else {
            // promotion forward moves
            moves = moveS(pawn_pos) & ~pos->allpieces & rank[0];
            for (int i = 0; i < 8; i++) {
                if ((index_to = ffsll(moves)) != 0) {
                    index_to--;
                    add_promotion_move(m, index_to + N, index_to, pawns, nopiece_n);
                    moves &= notlinboard[index_to];
                } else {
                    break;
                }
            }

            // promotion attack west moves
            pawn_pos = pos->pieces[pawns];
            moves = moveSW(pawn_pos) & pos->wpieces & ~file[7] & rank[0];
            for (int i = 0; i < 8; i++) {
                if ((index_to = ffsll(moves)) != 0) {
                    index_to--;
                    add_promotion_move(m, index_to + NE, index_to, pawns, find_piece(pos, index_to));
                    moves &= notlinboard[index_to];
                } else {
                    break;
                }
            }

            // promotion attack east moves
            pawn_pos = pos->pieces[pawns];
            moves = moveSE(pawn_pos) & pos->wpieces & ~file[0] & rank[0];
            for (int i = 0; i < 8; i++) {
                if ((index_to = ffsll(moves)) != 0) {
                    index_to--;
                    add_promotion_move(m, index_to + NW, index_to, pawns, find_piece(pos, index_to));
                    moves &= notlinboard[index_to];
                } else {
                    break;
                }
            }
        }
        break;
    }
}
Ejemplo n.º 25
0
Board::Board(int m):root_story(-1, -1, 0)
{
#ifdef CKM_STORED
//  pIgs = NULL;
#endif

	
	
  size = 19;
 // UI = new FlBoard();
 // time_color = UI->black_time->text_background();
 //time_color2 = UI->black_time->text_color();
  //UI->b = this;
  set_size(size);
  cur_player = BLACK;
  for (int i=0; i<19; i++)
    for (int j=0; j<19; j++) {
      b[i][j] = EMPTY;
      root_story.b[i][j] = EMPTY;
    }
  s = &root_story;

  pos = 0;
  root_story.score[0] = score[0] = 0; 
  root_story.score[1] = score[1] = 0.5;
  mode = 0;
  set_mode(m);
//  owner = 0; //< pointer on the possibly associated IGS game
  memset(inib, EMPTY, 19*19);
  memset(dead, EMPTY, 19*19);
  memset(territory, EMPTY, 19*19);
    memset(b, EMPTY, 19*19);
 // memset(old_c, 0, sizeof(old_c)); //time color
  next = first;
  first = this;
  if (!stn) {
    stn = new Stone();
    stn->set_size(20);
  //  stn->init_image();
  }
 // UI->black_box->image(stn->img[0]);
 // UI->white_box->image(stn->img[1]);
 // UI->black_name->hide();
//  UI->white_name->hide();
//  UI->black_time->hide();
  //UI->white_time->hide();
 // UI->moves_browser->board = this;
 // UI->observer_browser->callback(observer_cb, this);
  //  UI->moves_browser->type(Fl_Browser::VERTICAL | Fl_Browser::MULTI_BROWSER);
  strcpy(blackname, "");
  strcpy(blackrank, "");
  strcpy(whitename, "");
  strcpy(whiterank, "");
  filename = 0;
  title = 0;
 
  
  PA_ResetBgSys();
  PA_ResetSpriteSys();
	PA_Init3D(); 
	PA_Reset3DSprites();
	
	PA_LoadTiledBg(0, 3, board19); 
	PA_LoadTiledBg(1, 1, bgscoreigs); 
	PA_Init16cBg(1, 0);
	PA_16cText(1, 120, 10, 255, 192, "chris28ttttt [17k]", 1, 2, 100);	
	//	PA_LoadSpritePal(0, 1, (void*)pass_Pal); 
		
	
 
 	
 	
		PA_3DProcess();  // Update sprites

		PA_WaitForVBL();
		
		if (!ptn) {
    ptn = new Pointer();
    
  }
  u16 gfx[6];
 gfx[PASSBUTTON] = PA_3DCreateTex((void*)pass_Texture, 64, 32, TEX_256COL);
    PA_3DCreateSpriteFromTex(PASSBUTTON, gfx[PASSBUTTON], 64, 32,  2, 33, 164);
    	PA_3DProcess();  // Update sprites
	PA_WaitForVBL();

      
//	while (COND_PLAY_MOVE) {
	while(!(mode&BOARD_OBSERVE)) {
		ptn->move();
		
		//add_move(ptn->xpointer, ptn->ypointer);
		
		 if (mode&BOARD_SCORING) {
  		  //  if (s->nbvariants) return 1;
    	  if (mode&BOARD_PLAYING) {
				if (!dead[ptn->xpointer][ptn->ypointer]) {
	 				char c = 'a'+ptn->xpointer;
	  				if (c>='i') c++;
	  				char s[10];
	 				// sprintf(s, "%c%d", c, this->size-my);
	 				//	 owner->igs->send(s);
				}
     	 }
     	 else {
			if (0)//(mk == 1) event button 
	 		 remove(ptn->xpointer,ptn->ypointer, cur_board->b[ptn->xpointer][ptn->ypointer], !dead[ptn->xpointer][ptn->ypointer]);
			else {
	 		 	if (b[ptn->xpointer][ptn->ypointer] == EMPTY)
	   		 	dead[ptn->xpointer][ptn->ypointer] = dead[ptn->xpointer][ptn->ypointer] == 2? 0:2;
			}
			//	cur_board->dead[mx][my] = !cur_board->dead[mx][my];
			//	refresh();
			//	redraw();
			update_territory();
     	 }
    	}
    
    else if (b[ptn->xpointer][ptn->ypointer] == EMPTY) {
      if (mode&BOARD_PLAYING) { //IGS
		char s[10];
		char c = 'a'+ptn->xpointer;
		if (c>='i') c++;
		//sprintf(s, "%c%d", c, this->size-my);
		//owner->igs->send(s);
      }
      else { // edit mode
      
		add_move(ptn->xpointer, ptn->ypointer);
	//	refresh();
		update_pos();
      }
    }
		// sprintf(debug,"player : %d",cur_player);
		// PA_16cText(1, 10, 30, 255, 192, debug, 1, 2, 100);	
	//	refresh();
	//	update_pos();
	}
		
 //	PA_CreateSprite(0, 1, (void*)pass_Sprite, OBJ_SIZE_64X32, 1, 1, 1, 60);  
}
/*
 * Generate all non-capturing, non-promoting, pseudo-legal checks. Used for
 * quiescent move generation.
 */
int generate_pseudo_checks(const position_t* pos, move_t* moves)
{
    move_t* moves_head = moves;
    color_t side = pos->side_to_move, other_side = side^1;
    square_t king_sq = pos->pieces[other_side][0];
    for (int i = 0; i < pos->num_pawns[side]; ++i) {
        square_t from = pos->pawns[side][i];
        square_t to = INVALID_SQUARE;
        piece_t piece = pos->board[from];
        // Figure out whether or not we can discover check by moving.
        direction_t discover_check_dir = 0;
        bool will_discover_check;
        const attack_data_t* king_atk = &get_attack_data(from, king_sq);
        if ((king_atk->possible_attackers & Q_FLAG) == 0) {
            discover_check_dir = 0;
        } else {
            direction_t king_dir = king_atk->relative_direction;
            square_t sq;
            for (sq = from+king_dir; pos->board[sq] == EMPTY; sq+=king_dir) {}
            if (sq == king_sq) {
                // Nothing between us and the king. Is there anything
                // behind us to do the check when we move?
                for (sq = from-king_dir; pos->board[sq] == EMPTY;
                        sq -= king_dir) {}
                if (side == piece_color(pos->board[sq]) &&
                        (king_atk->possible_attackers &
                         get_piece_flag(pos->board[sq]))) {
                    discover_check_dir = king_dir;
                }
            }
        }
        // Generate checking moves.
        will_discover_check = discover_check_dir && abs(discover_check_dir)!=N;
        to = from + pawn_push[side];
        if (pos->board[to] != EMPTY) continue;
        rank_t r_rank =
            relative_rank[side][square_rank(from)];
        if (r_rank == RANK_7) continue; // non-promotes only
        for (const direction_t* delta = piece_deltas[piece]; *delta; ++delta) {
            if (will_discover_check || to + *delta == king_sq) {
                moves = add_move(pos,
                        create_move(from, to, piece, EMPTY),
                        moves);
                break;
            }
        }
        to += pawn_push[side];
        if (r_rank == RANK_2 && pos->board[to] == EMPTY) {
            for (const direction_t* delta = piece_deltas[piece];
                    *delta; ++delta) {
                if (will_discover_check || to + *delta == king_sq) {
                    moves = add_move(pos,
                            create_move(from, to, piece, EMPTY),
                            moves);
                    break;
                }
            }
        }
    }

    for (int i = 0; i < pos->num_pieces[side]; ++i) {
        square_t from = pos->pieces[side][i];
        square_t to = INVALID_SQUARE;
        piece_t piece = pos->board[from];
        // Figure out whether or not we can discover check by moving.
        direction_t discover_check_dir = 0;
        bool will_discover_check;
        const attack_data_t* king_atk = &get_attack_data(from, king_sq);
        if ((king_atk->possible_attackers & Q_FLAG) == 0) {
            discover_check_dir = 0;
        } else {
            direction_t king_dir = king_atk->relative_direction;
            square_t sq;
            for (sq = from+king_dir; pos->board[sq] == EMPTY; sq+=king_dir) {}
            if (sq == king_sq) {
                // Nothing between us and the king. Is there anything
                // behind us to do the check when we move?
                for (sq = from - king_dir; pos->board[sq] == EMPTY;
                        sq -= king_dir) {}
                if (side == piece_color(pos->board[sq]) &&
                        (king_atk->possible_attackers &
                         get_piece_flag(pos->board[sq]))) {
                    discover_check_dir = king_dir;
                }
            }
        }
        // Generate checking moves.
        if (piece_is_type(piece, KNIGHT)) {
            for (const direction_t* delta = piece_deltas[piece];
                    *delta; ++delta) {
                to = from + *delta;
                if (pos->board[to] != EMPTY) continue;
                if (discover_check_dir ||
                        possible_attack(to, king_sq, WN)) {
                    moves = add_move(pos,
                            create_move(from, to, piece, EMPTY),
                            moves);
                }
            }
        } else {
            for (const direction_t* delta = piece_deltas[piece];
                    *delta; ++delta) {
                for (to = from+*delta; pos->board[to] == EMPTY; to+=*delta) {
                    will_discover_check = discover_check_dir &&
                        abs(discover_check_dir) != abs(*delta);
                    if (will_discover_check) {
                        moves = add_move(pos,
                                create_move(from, to, piece, NONE),
                                moves);
                        continue;
                    }
                    if (possible_attack(to, king_sq, piece)) {
                        const direction_t to_king = direction(to, king_sq);
                        square_t x = to + to_king;
                        for (; pos->board[x] == EMPTY; x+=to_king) {}
                        if (x == king_sq) {
                            moves = add_move(pos,
                                    create_move(from, to, piece, NONE),
                                    moves);
                        }
                    }
                }
            }
        }
    }
    *moves = 0;
    return moves-moves_head;
}
Ejemplo n.º 27
0
void get_bishop_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){
	Pos curr;
	curr.col = piece.col + 1;
	curr.row = piece.row + 1;
	while (is_valid_pos(curr)){
		if (is_valid_dest(board, player, curr) == 1 || is_valid_dest(board, player, curr) == 2) add_move(piece, curr, 0);
		if (is_valid_dest(board, player, curr) == 0 || is_valid_dest(board, player, curr) == 2) break;
		curr.col++, curr.row++;
	}
	curr.col = piece.col - 1;
	curr.row = piece.row - 1;
	while (is_valid_pos(curr)){
		if (is_valid_dest(board, player, curr) == 1 || is_valid_dest(board, player, curr) == 2) add_move(piece, curr, 0);
		if (is_valid_dest(board, player, curr) == 0 || is_valid_dest(board, player, curr) == 2) break;
		curr.col--, curr.row--;
	}
	curr.col = piece.col - 1;
	curr.row = piece.row + 1;
	while (is_valid_pos(curr)){
		if (is_valid_dest(board, player, curr) == 1 || is_valid_dest(board, player, curr) == 2) add_move(piece, curr, 0);
		if (is_valid_dest(board, player, curr) == 0 || is_valid_dest(board, player, curr) == 2) break;
		curr.col--, curr.row++;
	}
	curr.col = piece.col + 1;
	curr.row = piece.row - 1;
	while (is_valid_pos(curr)){
		if (is_valid_dest(board, player, curr) == 1 || is_valid_dest(board, player, curr) == 2) add_move(piece, curr, 0);
		if (is_valid_dest(board, player, curr) == 0 || is_valid_dest(board, player, curr) == 2) break;
		curr.col++, curr.row--;
	}
}
/*
 * Add all pseudo-legal captures that the given piece (N/B/Q/K) can make.
 */
static void generate_piece_captures(const position_t* pos,
        square_t from,
        piece_t piece,
        move_t** moves_head)
{
    move_t* moves = *moves_head;
    square_t to;
    // Note: I unrolled all these loops to handle each direction explicitly.
    // The idea was to increase performance, but it's only about 1% faster
    // for much more code, so it's possible I'll change this back later.
    switch (piece_type(piece)) {
        case KING:
            to = from - 17;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 16;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 15;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 1;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 1;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 15;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 16;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 17;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            break;
        case KNIGHT:
            to = from - 33;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 31;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 18;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from - 14;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 14;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 18;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 31;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            to = from + 33;
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            break;
        case BISHOP:
            for (to=from-17; pos->board[to]==EMPTY; to-=17) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from-15; pos->board[to]==EMPTY; to-=15) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+15; pos->board[to]==EMPTY; to+=15) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+17; pos->board[to]==EMPTY; to+=17) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            break;
        case ROOK:
            for (to=from-16; pos->board[to]==EMPTY; to-=16) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from-1; pos->board[to]==EMPTY; to-=1) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+1; pos->board[to]==EMPTY; to+=1) {}
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+16; pos->board[to]==EMPTY; to+=16) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            break;
        case QUEEN:
            for (to=from-17; pos->board[to]==EMPTY; to-=17) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from-16; pos->board[to]==EMPTY; to-=16) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from-15; pos->board[to]==EMPTY; to-=15) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from-1; pos->board[to]==EMPTY; to-=1) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+1; pos->board[to]==EMPTY; to+=1) {}
            if (pos->board[to] != EMPTY && can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+15; pos->board[to]==EMPTY; to+=15) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+16; pos->board[to]==EMPTY; to+=16) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            for (to=from+17; pos->board[to]==EMPTY; to+=17) {}
            if (can_capture(piece, pos->board[to])) {
                moves = add_move(pos, create_move(from, to, piece,
                            pos->board[to]), moves);
            }
            break;
        default: assert(false);
    }
    *moves_head = moves;
}
T Hex<T>::getNextBestMove(player_t player)
{
	//First list out all the possible legal moves.
	//For each move:
	//			Simulate N times to calculate the wins if this move gets selected.
	std::vector<T> vec_legal_move;
	populate_legal_move_list(player,vec_legal_move);

	//dummy initializations
	T best_move = vec_legal_move[0];
	T best_win_count = 0;

	for (T best_move_i = 0; best_move_i != vec_legal_move.size(); ++best_move_i)
	{
		{
			T row = (vec_legal_move[best_move_i]/size_)+1; //Hex board row is 1-indexed
			col_t col = vec_legal_move[best_move_i]%size_ + 'A';
			MoveType moveType = add_move(row,col,player);
			assert((moveType == MoveType::Valid) && "move tagged as non valid. check");
		}
		//Now we will run Monte-Carlo assuming we have selected vec_legal_move[best_move_i] for the current player.
		std::vector<T> vecShuffledMove;
		vecShuffledMove.reserve(vec_legal_move.size()-1);
		for (T move_i = 0; move_i != vec_legal_move.size(); ++move_i)
		{
			if (move_i != best_move_i)
			{
				vecShuffledMove.push_back(vec_legal_move[move_i]);
			}
		}

		//After every simulation we also need to reset the board.
		//Also reset the vec_legal_move[best_move_i] after completion of monte-carlo simulation for this move.

		T winCount = 0;
		player_t otherPlayer = (player == 1) ? 2 : 1;
		for (T simulation_i = 0; simulation_i != NSimulation; ++simulation_i)
		{
			std::random_shuffle(vecShuffledMove.begin(),vecShuffledMove.end());
			//iterate over vecShuffledMove and keep assigning the position to the two players alternatively.
			for (std::vector<T>::iterator it = vecShuffledMove.begin(); it != vecShuffledMove.end(); ++it)
			{
				T pos = (*it);
				T row = (pos/size_)+1; //Hex board row is 1-indexed
				col_t col = pos%size_ + 'A';
				player_t curMovePlayer = (std::distance(vecShuffledMove.begin(),it)%2 == 0) ? otherPlayer : player;
				MoveType moveType = add_move(row,col,curMovePlayer);
				assert((moveType == MoveType::Valid) && "move tagged as non valid. check");
			}
			//Now board has been filled up.
			//check the winner of this simulation.
			bool flagSuccessCurPlayer = is_winning_move(player);
			if (flagSuccessCurPlayer)
			{
				++winCount;
			}
			//checking individually for both players is for debugging only
			bool flagSuccessOtherPlayer = is_winning_move(otherPlayer);
			assert((flagSuccessCurPlayer != flagSuccessOtherPlayer) && "One and only one must win");

			//Now empty all the positions of the hex board that were filled up in this simulation.
			for (std::vector<T>::iterator it = vecShuffledMove.begin(); it != vecShuffledMove.end(); ++it)
			{
				T pos = (*it);
				T row = (pos/size_)+1; //Hex board row is 1-indexed
				col_t col = pos%size_ + 'A';
				delete_move(row,col);
			}
		}

		if (best_win_count < winCount)
		{
			best_win_count = winCount;
			best_move = vec_legal_move[best_move_i];
		}

		//Now remove the move which we considered as possible best move in this iteration.
		{
			T row = vec_legal_move[best_move_i]/size_ + 1;
			col_t col = vec_legal_move[best_move_i]%size_ + 'A';
			delete_move(row,col);
		}
	}

	return best_move;
}
/*
 * Generate all moves that evade check in the given position. This is purely
 * legal move generation; no pseudo-legal moves.
 */
int generate_evasions(const position_t* pos, move_t* moves)
{
    assert(pos->is_check && pos->board[pos->check_square]);
    move_t* moves_head = moves;
    color_t side = pos->side_to_move, other_side = side^1;
    square_t king_sq = pos->pieces[side][0];
    square_t check_sq = pos->check_square;
    piece_t king = create_piece(side, KING);
    piece_t checker = pos->board[check_sq];

    // Generate king moves.
    // Don't let the king mask its possible destination squares in calls
    // to is_square_attacked.
    square_t from = king_sq, to = INVALID_SQUARE;
    ((position_t*)pos)->board[king_sq] = EMPTY;
    for (const direction_t* delta = piece_deltas[king]; *delta; ++delta) {
        to = from + *delta;
        piece_t capture = pos->board[to];
        if (capture != EMPTY && !can_capture(king, capture)) continue;
        if (is_square_attacked((position_t*)pos,to,other_side)) continue;
        ((position_t*)pos)->board[king_sq] = king;
        moves = add_move(pos, create_move(from, to, king, capture), moves);
        ((position_t*)pos)->board[king_sq] = EMPTY;
    }
    ((position_t*)pos)->board[king_sq] = king;
    // If there are multiple checkers, only king moves are possible.
    if (pos->is_check > 1) {
        *moves = 0;
        return moves-moves_head;
    }
    
    // First, the most common case: a check that can be evaded via an
    // en passant capture. Note that if we're in check and an en passant
    // capture is available, the only way the en passant capture would evade
    // the check is if it's the newly moved pawn that's checking us.
    direction_t pin_dir;
    if (pos->ep_square != EMPTY &&
            check_sq+pawn_push[side] == pos->ep_square &&
            pos->board[pos->ep_square] == EMPTY) {
        piece_t our_pawn = create_piece(side, PAWN);
        to = pos->ep_square;
        for (int i=0; i<2; ++i) {
            from = to-piece_deltas[our_pawn][i];
            if (pos->board[from] && pos->board[from] == our_pawn) {
                pin_dir = pin_direction(pos, from, king_sq);
                if (pin_dir) continue;
                moves = add_move(pos,
                        create_move_enpassant(from, to, our_pawn, checker),
                        moves);
            }
        }
    }
    // Generate captures of the checker.
    for (int i = 0; i < pos->num_pawns[side]; ++i) {
        from = pos->pawns[side][i];
        piece_t piece = create_piece(side, PAWN);
        pin_dir = pin_direction(pos, from, king_sq);
        if (pin_dir) continue;
        if (!possible_attack(from, check_sq, piece)) continue;
        if (relative_rank[side][square_rank(from)] == RANK_7) {
            // Capture and promote.
            for (piece_t promoted=QUEEN; promoted > PAWN; --promoted) {
                moves = add_move(pos,
                        create_move_promote(from, check_sq, piece,
                            checker, promoted),
                        moves);
            }
        } else {
            moves = add_move(pos,
                    create_move(from, check_sq, piece, checker),
                    moves);
        }
    }
    for (int i = 1; i < pos->num_pieces[side]; ++i) {
        from = pos->pieces[side][i];
        piece_t piece = pos->board[from];
        pin_dir = pin_direction(pos, from, king_sq);
        if (pin_dir) continue;
        if (!possible_attack(from, check_sq, piece)) continue;
        if (piece_slide_type(piece) == NONE) {
            moves = add_move(pos,
                    create_move(from, check_sq, piece, checker),
                    moves);
        } else {
            // A sliding piece, keep going until we hit something.
            direction_t check_dir = direction(from, check_sq);
            for (to=from+check_dir; pos->board[to] == EMPTY; to+=check_dir) {}
            if (to == check_sq) {
                moves = add_move(pos,
                        create_move(from, to, piece, checker),
                        moves);
                continue;
            }
        }
    }
    if (piece_slide_type(checker) == NONE) {
        *moves = 0;
        return moves-moves_head;
    }
    
    // A slider is doing the checking; generate blocking moves.
    direction_t block_dir = direction(check_sq, king_sq);
    for (int i = 0; i < pos->num_pawns[side]; ++i) {
        from = pos->pawns[side][i];
        piece_t piece = create_piece(side, PAWN);
        direction_t k_dir;
        pin_dir = pin_direction(pos, from, king_sq);
        if (pin_dir) continue;
        to = from + pawn_push[side];
        if (pos->board[to] != EMPTY) continue;
        rank_t rank = relative_rank[side][square_rank(from)];
        k_dir = direction(to, king_sq);
        if (k_dir == block_dir &&
                ((king_sq < to && check_sq > to) ||
                 (king_sq > to && check_sq < to))) {
            if (rank == RANK_7) {
                // Block and promote.
                for (piece_t promoted=QUEEN; promoted > PAWN; --promoted) {
                    moves = add_move(pos,
                        create_move_promote(from, to, piece, EMPTY, promoted),
                        moves);
                }
            } else {
                moves = add_move(pos,
                        create_move(from, to, piece, EMPTY),
                        moves);
            }
        }
        if (rank != RANK_2) continue;
        to += pawn_push[side];
        if (pos->board[to]) continue;
        k_dir = direction(to, king_sq);
        if (k_dir == block_dir &&
                ((king_sq < to && check_sq > to) ||
                 (king_sq > to && check_sq < to))) {
            moves = add_move(pos,
                    create_move(from, to, piece, EMPTY),
                    moves);
        }
    }

    for (int i=1; i<pos->num_pieces[side]; ++i) {
        from = pos->pieces[side][i];
        piece_t piece = pos->board[from];
        direction_t k_dir;
        pin_dir = pin_direction(pos, from, king_sq);
        if (pin_dir) continue;
        if (piece_is_type(piece, KNIGHT)) {
            for (const direction_t* delta=piece_deltas[piece];
                    *delta; ++delta) {
                to = from + *delta;
                if (pos->board[to] != EMPTY) continue;
                k_dir = direction(to, king_sq);
                if (k_dir == block_dir &&
                        ((king_sq < to && check_sq > to) ||
                         (king_sq > to && check_sq < to))) {
                    moves = add_move(pos,
                            create_move(from, to, piece, EMPTY),
                            moves);
                }
            }
        } else {
           for (const direction_t* delta=piece_deltas[piece];
                   *delta; ++delta) {
                for (to = from+*delta; pos->board[to] == EMPTY; to+=*delta) {
                    k_dir = direction(to, king_sq);
                    if (k_dir == block_dir &&
                            ((king_sq < to && check_sq > to) ||
                             (king_sq > to && check_sq < to))) {
                        moves = add_move(pos,
                                create_move(from, to, piece, EMPTY),
                                moves);
                        break;
                    }
                }
            }
        }
    }
    *moves = 0;
    return moves-moves_head;
}