Ejemplo n.º 1
0
int game_load(int slot) {
	int retval;
	char temp[80];
	board_t *board;

	if (ch_userdir()) {
		DBG_ERROR("Failed to enter user directory");
		return 1;
	}

	comm_send("force\n");

	snprintf(temp, sizeof(temp), "save%i.pgn", slot);
	retval = pgn_parse_file(temp);

	if (retval) {
		DBG_ERROR("Failed to parse PGN file '%s'", temp);
		return 1;
	}

	board = history->last->board;

	ui->update(board, NULL);

	if (config->player[board->turn] == PLAYER_ENGINE)
		comm_send("go\n");
	else if (config->player[OPPONENT(board->turn)] == PLAYER_ENGINE) {
		if (board->turn == WHITE)
			comm_send("white\n");
		else
			comm_send("black\n");
	}

	return retval;
}
Ejemplo n.º 2
0
bitboard getRawMoves(const position * const pos, const int player, const int piece, const int type, const int sq)
{
    bitboard rawMoves = 0;
    bitboard attackRange = 0;
    bitboard allPieces = 0;
    bitboard opponentSquares = 0;
    assert(sq >= 0 && sq <= 63);
    allPieces = pos->pieces[BLACK] | pos->pieces[WHITE];
    if(CAPTURE == type) {
        attackRange = getAttackRange(piece, type, sq, allPieces, pos->epSquare);
        opponentSquares = pos->pieces[OPPONENT(player)];
        if(pos->epSquare != -1) {
            opponentSquares |= _mask[pos->epSquare];
        }
        /* captures */
        rawMoves = attackRange & opponentSquares;
    }
    else if(NORMAL == type) {
        attackRange = getAttackRange(piece, type, sq, allPieces, pos->epSquare);
        /* normal moves, no violence ;) */
        rawMoves = attackRange & ~allPieces;
    }
    else {
        assert(0); /* don't know type of move */
    }
    return rawMoves;
}
Ejemplo n.º 3
0
XOBoard negaMaxThink(XOBoard::Player player, XOBoard board)
{
    /* TODO: Fa o miscare si returneaza tabla dupa aceasta miscare. Aceasta
     * functie de AI trebuie sa respecte acest format pentru ca este data in
     * constructorul jocului, dar puteti apela aici o functie scrisa de voi. */

    int sol = -10, x, y, alpha = -10, beta =10;
    for (int i = 0; i < 3; ++ i)
        for (int j = 0; j < 3; ++ j)
            if (board.is_empty(i,j))
            {
                board.put(player,i,j);
                int k = -negaMaxMin(OPPONENT(player), board, -beta, -alpha);
                std::cerr<<i<<" "<<j<<" "<<k<<std::endl;
                board.erase(i,j);
                if (k > alpha)
                {
                    alpha = k;
                    x = i;
                    y = j;
                }
            }
    /* TODO: Stergeti linia de mai jos dupa ce rezolvati. */
    board.put(player, x,y);
    return board;
}
Ejemplo n.º 4
0
static int square_attacked(board_t *b, int square, int side)
{
    board_t board = *b;
    move_t move;
    int i;

    board.turn = side;

    /* We add a piece because we only want to take capture moves into consideration. */
    board.square[square] = KING + OPPONENT(side);

    move.destination = square;

    for (i = 0; i < 64; i++)
    {
        if (COLOUR(board.square[i]) == side)
        {
            move.source = i;
            if ((PIECE(board.square[i]) == PAWN) && ((square < 8) || (square >= 56)))
                move.promotion_piece = QUEEN + side;
            else
                move.promotion_piece = NONE;
            if (move_is_semi_valid(&board, &move))
                return 1;
        }
    }
    return 0;
}
Ejemplo n.º 5
0
int getMoves(const position * const pos, const int player, const int piece, const int type, move store[])
{
    bitboard rawMoves = 0;
    int sq;
    int numMoves = 0;
    int opponent;
    bitboard pieces;
    opponent = OPPONENT(player);
    /* opponent in check = player won. should be checked somewhere before this */
    assert(!inCheck(pos, opponent, pos->kingSquare[opponent]));
    pieces = getPieceBitboard(pos, piece);
    sq = 0;
    if(IS_KING(piece)) {
        /* we already know the location of the king */
        sq = pos->kingSquare[player];
        pieces = pieces >> sq;
        assert(pieces != 0); /* we should not move the king off the board */
    }
    while(pieces != 0) {
        if(LSB_SET(pieces)) {
            rawMoves = getRawMoves(pos, player, piece, type, sq);
            numMoves += getPieceMoves(pos, player, type, rawMoves, sq, &store[numMoves]);
        }
        pieces = pieces >> 1;
        sq++;
    }
    return numMoves;
}
Ejemplo n.º 6
0
int		Eval::megaval(char **map, Pos& pos, PLAYER player)
{
  // 1 : win -> 5 aligné ou 10 de score
  // 2 : bloquer alignement 5 de l'adversaire ou empecher de manger si score adverse == 8
  // 3 : faire un 4 libre
  // 4 : empecher 4 libre
  // 4 : bloquer un 3 libre
  // 5 : manger deux pièces
  // 6 : empêcher l'autre de manger
  // 7 : poids des aligements
  return (_eval__alignment(map, pos, player, false)
	  + (1.5 * _eval__alignment(map, pos, static_cast<PLAYER>(OPPONENT(player)), true))
	  + _eval__eat(map, pos, player)
	  + (1.5 * _eval__eat(map, pos, static_cast<PLAYER>(OPPONENT(player))))
	  + _eval__block(map, pos, player)
	  + _eval__win(map, pos, player));
}
Ejemplo n.º 7
0
void OXGame::undo()
{
  _player = OPPONENT(_player);
  _moveCount--;
  int x, y;
  x = _move[_moveCount].x;
  y = _move[_moveCount].y;
  _cell[ x ][ y ] = EMPTY;
}
Ejemplo n.º 8
0
/** Un exemplu de functie de gandire care foloseste rezultatele furnizate de
 * o abordare negaMax exhaustiva. */
int negaMaxMin(XOBoard::Player player, XOBoard& board, int alpha, int beta)
{
    int sol = -10;
    if( board.is_full())
    {
        return board.get_score(player)-board.get_score(OPPONENT(player));
    }
    for (int i = 0; i < 3; ++ i)
        for (int j = 0; j < 3; ++ j)
            if (board.is_empty(i,j))
            {
                board.put(player,i,j);
                int k = -negaMaxMin(OPPONENT(player), board, -beta, -alpha);
                board.erase(i,j);
                if (k >= beta)
                    return beta;
                if (k > alpha)
                    alpha = k;
            }
    return alpha;
}
BOOL tsumego_setup_if_closed(ThreadInfo *info, const Board *board, TreeBlock *bl) {
  const TreeHandle *s = info->s;

  Stone win_state = S_EMPTY;

  // Check if the newly created node b is an end state, if so, no need to call dcnn.
  Stone curr_player = OPPONENT(board->_next_player);

  if (curr_player == s->params.defender) {
    // Check if in the given region, whether a player has two eyes.
    // Check at least one group of player lives.
    BOOL curr_lives = OneGroupLives(board, curr_player, &s->params.ld_region);
    if (curr_lives) win_state = curr_player;
  }

  if (s->params.defender == S_BLACK && board->_w_cap >= 4) win_state = S_WHITE;
  else if (s->params.defender == S_WHITE && board->_b_cap >= 4) win_state = S_BLACK;

  // If it is a terminal state, then we can proceed.
  // Change the prove/dis_prove number, if one side lives.
  if (win_state != S_EMPTY) {
    /*
    if (win_state == S_WHITE) {
      char buf[100];
      Coord last_move = bl->parent->data.moves[bl->parent_offset];
      printf("%s Lives! Final move: %s\n", curr_player == S_BLACK ? "B" : "W", get_move_str(last_move, curr_player, buf));
      ShowBoard(board, SHOW_ALL);
      printf("\n");
    }
    */

    int b, w;
    if (win_state == S_BLACK) {
      b = 0;
      w = INIT_PROVE_NUM;
    } else {
      w = 0;
      b = INIT_PROVE_NUM;
    }
    // Update the statistics in the parent node.
    ProveNumber *pn = &bl->parent->cnn_data.ps[bl->parent_offset];
    __atomic_store_n(&pn->w, w, __ATOMIC_RELAXED);
    __atomic_store_n(&pn->b, b, __ATOMIC_RELAXED);

    bl->n = 0;
    bl->terminal_status = win_state;
    // bl->player = mmove.player;
    return TRUE;
  }
  return FALSE;
}
void threaded_run_tsumego_bp(ThreadInfo *info, float black_moku, Stone next_player, int end_ply, BOOL board_on_child, BlockOffset child_offset, TreeBlock *b) {
  // In tsumego, there is no playout policy, and we just evaluate the curent board situation and backprop.
  TreeHandle *s = info->s;
  TreePool *p = &s->p;

  TreeBlock *curr = b;
  Stone player = next_player;
  // If the board is pointing to the child, we need to switch the current player.
  if (board_on_child) player = OPPONENT(player);

  // Backpropagation.
  while (curr->parent != NULL) {
    update_pn(info, board_on_child, player, curr);
    curr = curr->parent;
    player = OPPONENT(player);
  }

  if (s->params.use_online_model) {
    // Update the online model.
    player = board_on_child ? OPPONENT(next_player) : next_player;
    update_online_model(info, player, b);
  }
}
Ejemplo n.º 11
0
static int in_check(board_t *board, int turn)
{
    int i;
    for (i = 0; i < 64; i++)
        if (board->square[i] ==  KING + turn)
            break;

    if (i == 64)
    {
        DBG_ERROR("board is missing a king");
        exit(1);
    }

    return square_attacked(board, i, OPPONENT(turn));
}
Ejemplo n.º 12
0
bool OXGame::move(int x, int y)
{
  if (_finished) return 1;
  _cell[x][y] = _player;
  _move[_moveCount].x = x;
  _move[_moveCount].y = y;
  _moveCount++;
  if (is5inRow(x, y))
    {
      _winner = _player;
      _finished = true;
    }
  if (_moveCount == _boardSize * _boardSize) _finished = true;
  _player = OPPONENT(_player);
  return _finished;
}
Ejemplo n.º 13
0
static void storeMoveIfLegal(const position* const pos, move* m, const int player, move store[], int *numMoves)
{
    position newPosition;
    int status;
    int opponent;
    status = playMove(pos, &newPosition, m, player);

    if(status != ILLEGAL) { /* move is legal */
        /* check that the move does not put players king in check, which would be illegal */
        if(!inCheck(&newPosition, player, newPosition.kingSquare[player])) {
            /* calculate evaluation */
            opponent = OPPONENT(player);
            if(inCheck(&newPosition, opponent, newPosition.kingSquare[opponent])) {
                m->flags |= CHECK;
                m->eval += EVAL_CHECK;
            }
            store[(*numMoves)++] = *m;
        }
    }
}
Ejemplo n.º 14
0
int make_move(board_t *board, move_t *move)
{
    /* Assume that move is valid. */

    if ((PIECE(board->square[move->source]) == PAWN) && ((PIECE(board->square[move->destination]) == NONE)) && ((move->source % 8) != (move->destination % 8)))
    {
        /* En-passant move. */
        int ep = move->destination - 8 * (move->destination > move->source ? 1 : -1);
        board->captured[board->square[ep]]++;
        board->square[ep] = NONE;
    }

    /* Update captured pieces. */
    if (board->square[move->destination] != NONE)
        board->captured[board->square[move->destination]]++;

    if ((PIECE(board->square[move->source]) == KING) && (move->destination - move->source == 2))
    {
        /* Kingside castle. */
        board->square[move->destination - 1] = board->square[move->destination + 1];
        board->square[move->destination + 1] = NONE;
    }

    if ((PIECE(board->square[move->source]) == KING) && (move->source - move->destination == 2))
    {
        /* Queenside castle. */
        board->square[move->destination + 1] = board->square[move->destination - 2];
        board->square[move->destination - 2] = NONE;
    }

    if ((PIECE(board->square[move->source]) == PAWN) && (move->destination < 8 || move->destination >= 56))
        /* Promotion. */
        board->square[move->destination] = move->promotion_piece;
    else
        board->square[move->destination] = board->square[move->source];

    board->square[move->source] = NONE;
    board->turn = OPPONENT(board->turn);

    return 0;
}
Ejemplo n.º 15
0
/*
    Types of moves:
    1) King normal move
    2) King captures
    3) King castles
    4)
*/
int playMove(const position * const pos, position *newPosition, const move * const m, const int player)
{
    int opponent;
    opponent = OPPONENT(player);
    /* assert consistency of position */
    assertPosition(pos);
    /* opponent cannot be check, this should be handled elsewhere */
    assert(!inCheck(pos, opponent, pos->kingSquare[opponent]));
    /* init new position to old position */
    *newPosition = *pos;
    /* opponent has to play in the new position */
    newPosition->toPlay = opponent;
    movePiece(newPosition, m, player);
    if(IS_CAPTURE(m)) {
        /* clear bitmask for captured piece */
        clearCapturedPiece(newPosition, m);
    }
    /* ep is disabled after any move played */
    DISABLE_EP(newPosition);
    /* assert consistency of new position */
    assertPosition(newPosition);
    return 0;
}
// =============================================== Back propagation.
void threaded_run_bp(ThreadInfo *info, float black_moku, Stone next_player, int end_ply, BOOL board_on_child, BlockOffset child_offset, TreeBlock *b) {
  TreeHandle *s = info->s;
  TreePool *p = &s->p;

  // Dynkomi is adjusted if the win rate is too high.
  float komi = s->common_params->komi + s->common_variants->dynkomi;
  float black_count_playout = sigmoid(black_moku - komi);
  float black_count;

  // If there is network that predicts moku, then we should combine the results.
  if (b->has_score && s->params.use_cnn_final_score && end_ply >= s->params.min_ply_to_use_cnn_final_score) {
    // Final score = final_mixture_ratio * win_rate_prediction + (1.0 - final_mixture_ratio) * playout_result.
    float cnn_final_playout = sigmoid(b->score - komi);
    black_count = s->params.final_mixture_ratio * cnn_final_playout + (1 - s->params.final_mixture_ratio) * black_count_playout;
  } else {
    black_count = black_count_playout;
  }

  // Rave moves encoded in the board.
  int rave_moves[BOUND_COORD];
  if (s->params.use_rave) memset(rave_moves, 0, sizeof(rave_moves));

  TreeBlock *curr;
  BlockOffset curr_offset;

  if (board_on_child) {
    curr = b;
    curr_offset = child_offset;
  } else {
    curr = b->parent;
    curr_offset = b->parent_offset;
  }

  // Backprop from b.
  while (curr != NULL) {
    Stat* stat = &curr->data.stats[curr_offset];

    // Add total first, otherwise the winning rate might go over 1.
    __sync_add_and_fetch(&stat->total, 1);
    inc_atomic_float(&stat->black_win, black_count);
    // stat->total += 1;
    // stat->black_win += black_count;
    // __sync_add_and_fetch(&stat->black_win, black_count);

    // Then update rave, if rave mode is open
    if (s->params.use_rave) {
      // Update rave moves.
      rave_moves[curr->data.moves[curr_offset]] = 1;

      // Loop over existing moves.
      for (int i = 0; i < curr->n; ++i) {
        Coord m = curr->data.moves[i];
        if (rave_moves[m]) {
          Stat *rave_stat = &curr->data.rave_stats[i];
          __sync_add_and_fetch(&rave_stat->total, 1);
          inc_atomic_float(&rave_stat->black_win, black_count);
          // __sync_add_and_fetch(&rave_stat->black_win, black_count);
        }
      }
    }

    curr_offset = curr->parent_offset;
    curr = curr->parent;
  }

  if (s->params.use_online_model) {
    // Update the online model.
    Stone player = (board_on_child ? OPPONENT(next_player) : next_player);
    update_online_model(info, player, b);
  }
}
Ejemplo n.º 17
0
inline void calc_piece_value(struct t_board *board, struct t_chess_eval *eval) {

    t_chess_color color, opponent;
    t_chess_square square;
    t_chess_piece piece;
    t_chess_piece piece_type;
    t_bitboard b;
    t_bitboard attack_squares;
    t_bitboard moves;
    int move_count;
    struct t_pawn_hash_record *pawn_record = eval->pawn_evaluation;

    for (color = WHITE; color <= BLACK; color++) {

        t_chess_value middlegame = 0;
        t_chess_value endgame = 0;

        opponent = OPPONENT(color);

        //=========================================================
        //-- Rooks first
        //=========================================================
        piece = PIECEINDEX(color, ROOK);
        eval->attacklist[piece] = 0;
        b = board->piecelist[piece];

        //-- Remove Rook and Queens (so we can easily evaluate rams)
        t_bitboard _all_pieces = board->all_pieces ^ board->pieces[color][QUEEN] ^ b;
        t_bitboard _not_occupied = ~(board->occupied[color] & _all_pieces);

        //-- Rooks on the 7th
        if ((b & rank_mask[color][6]) && (board->pieces[opponent][KING] & rank_mask[color][7])) {
            middlegame += MG_ROOK_ON_7TH;
            endgame += MG_ROOK_ON_7TH;
        }

        //-- Rooks on Open file
        if (b & pawn_record->open_file) {
			middlegame += popcount(b & pawn_record->open_file) * pawn_record->pawn_count[color] * MG_ROOK_ON_OPEN_FILE;
        }

        //-- Rooks on Semi-Open file
        if (b & pawn_record->semi_open_file[color]) {
			middlegame += popcount(b & pawn_record->semi_open_file[color]) * pawn_record->pawn_count[color] * MG_ROOK_ON_SEMI_OPEN_FILE;
        }

        //-- Loop around for all pieces
        while (b) {

            //-- Find the square it resides
            square = bitscan_reset(&b);

            //-- Generate moves
            moves = rook_magic_moves[square][((rook_magic[square].mask & _all_pieces) * rook_magic[square].magic) >> 52];
            eval->attacks[color][ROOK] |= moves;
            moves &= _not_occupied;

            //-- Mobility (along ranks)
            move_count = popcount(moves & square_rank_mask[square]);
            middlegame += horizontal_rook_mobility[MIDDLEGAME][move_count];
            endgame += horizontal_rook_mobility[ENDGAME][move_count];

            //-- Mobility (along files)
            move_count = popcount(moves & square_column_mask[square]);
            middlegame += vertical_rook_mobility[MIDDLEGAME][move_count];
            endgame += vertical_rook_mobility[ENDGAME][move_count];

            //-- King safety
            if (attack_squares = (moves & eval->king_zone[opponent])) {
                eval->king_attack_count[opponent]++;
                eval->king_attack_pressure[opponent] += popcount(attack_squares) * 40;
            }
			assert(eval->king_zone[opponent] != 0);

            // piece-square tables
            middlegame += piece_square_table[piece][MIDDLEGAME][square];
            endgame += piece_square_table[piece][ENDGAME][square];

        }

        //=========================================================
        //-- Queens
        //=========================================================
        piece = PIECEINDEX(color, QUEEN);
        eval->attacklist[piece] = 0;
        b = board->piecelist[piece];

        _all_pieces ^= board->pieces[color][BISHOP];
        _not_occupied = ~(board->occupied[color] & _all_pieces);

        while (b) {

            //-- Find the square it resides
            square = bitscan_reset(&b);

            //-- Rook-like Moves
            t_bitboard rook_moves = rook_magic_moves[square][((rook_magic[square].mask & _all_pieces) * rook_magic[square].magic) >> 52];
            eval->attacklist[piece] |= rook_moves;
			rook_moves &= _not_occupied;

            //-- Bishop-like moves
            t_bitboard bishop_moves = bishop_magic_moves[square][((bishop_magic[square].mask & _all_pieces) * bishop_magic[square].magic) >> 55];
            eval->attacklist[piece] |= bishop_moves;
			bishop_moves &= _not_occupied;

            //-- Mobility
            move_count = popcount((rook_moves & square_column_mask[square]) | bishop_moves);
			middlegame += move_count;

            //-- King safety
            if (attack_squares = ((rook_moves | bishop_moves) & eval->king_zone[opponent])) {
                eval->king_attack_count[opponent]++;
                eval->king_attack_pressure[opponent] += 80 * popcount(attack_squares);
            }

            //-- piece-square tables
            middlegame += piece_square_table[piece][MIDDLEGAME][square];
            endgame += piece_square_table[piece][ENDGAME][square];
        }

        //-- Interaction of double pawns & major pieces
        if (pawn_record->double_pawns[color]) {

            int double_pawn_count = popcount(pawn_record->double_pawns[color]);
            int major_piece_count = popcount(board->pieces[color][ROOK] | board->pieces[color][QUEEN]);

            switch (major_piece_count) {
            case 0:
                break;
            case 1:
                middlegame += (double_pawn_count * 12) - pawn_record->semi_open_double_pawns[color] * 30;
                endgame += (double_pawn_count * 12) - pawn_record->semi_open_double_pawns[color] * 25;
                break;
            case 2:
                middlegame += (double_pawn_count * 24) - pawn_record->semi_open_double_pawns[color] * 35;
                endgame += (double_pawn_count * 24) - pawn_record->semi_open_double_pawns[color] * 30;
                break;
            case 3:
                middlegame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 40;
                endgame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 35;
                break;
            case 4:
                middlegame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 40;
                endgame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 35;
                break;
            case 5:
                middlegame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 40;
                endgame += (double_pawn_count * 30) - pawn_record->semi_open_double_pawns[color] * 35;
                break;
            }
        }

        //=========================================================
        //-- Bishops
        //=========================================================
        piece = PIECEINDEX(color, BISHOP);
        eval->attacklist[piece] = 0;
        b = board->piecelist[piece];

        //-- Bishop pair bonus
        if (b & (b - 1)) {
            middlegame += MG_BISHOP_PAIR;
            endgame += EG_BISHOP_PAIR;
        }

        //-- Remove Own Pieces (leave pawns)
		_all_pieces = board->all_pieces ^ board->pieces[color][KNIGHT] ^ board->pieces[color][QUEEN];
		_not_occupied = ~(board->occupied[color] & _all_pieces);

        while (b) {
            //-- Find the square it resides
            square = bitscan_reset(&b);

            //-- Generate moves
            moves = bishop_magic_moves[square][((bishop_magic[square].mask & _all_pieces) * bishop_magic[square].magic) >> 55];
            eval->attacklist[piece] |= moves;

			moves &= _not_occupied;

            //-- Mobility
            move_count = popcount(moves);
            middlegame += bishop_mobility[MIDDLEGAME][move_count];
            endgame += bishop_mobility[ENDGAME][move_count];

            //-- Trapped
            //middlegame -= trapped_bishop[MIDDLEGAME][move_count];
            //endgame -= trapped_bishop[ENDGAME][move_count];

            //-- King safety
            if (attack_squares = (moves & eval->king_zone[opponent])) {
                eval->king_attack_count[opponent]++;
                eval->king_attack_pressure[opponent] += 20 * popcount(attack_squares);
            }

            // piece-square tables
            middlegame += piece_square_table[piece][MIDDLEGAME][square];
            endgame += piece_square_table[piece][ENDGAME][square];
        }

        //=========================================================
        //-- Knights
        //=========================================================
        piece = PIECEINDEX(color, KNIGHT);
        eval->attacklist[piece] = 0;
        b = board->piecelist[piece];

        _not_occupied = ~board->occupied[color] & ~eval->attacks[opponent][PAWN];

        //-- Outposts
        t_bitboard knight_outpost = b & pawn_record->potential_outpost[color];
        while (knight_outpost) {

            square = bitscan_reset(&knight_outpost);
            t_chess_color square_color = SQUARECOLOR(square);

            //-- Can it be taken by a minor piece?
            if ((board->pieces[opponent][KNIGHT] == 0) && ((board->pieces[opponent][BISHOP] & color_square_mask[square_color]) == 0)) {
                middlegame += 25 - square_distance(square, board->king_square[opponent]);
                endgame += 10;
            }
            else {
                middlegame += 15 - square_distance(square, board->king_square[opponent]);
                endgame += 8;
            }
        }

        while (b) {
            //-- Find the square it resides
            square = bitscan_reset(&b);

            //-- Opponents King Tropism
            middlegame -= square_distance(square, board->king_square[opponent]) * 2;

            //-- Generate moves
            moves = knight_mask[square];
            eval->attacklist[piece] |= moves;

            //-- Connected to another knight
            if (moves & board->piecelist[piece]) {
                middlegame += MG_CONNECTED_KNIGHTS;
                endgame += EG_CONNECTED_KNIGHTS;
            }

            //-- King safety
            if (attack_squares = (moves & eval->king_zone[opponent])) {
                eval->king_attack_count[opponent]++;
                eval->king_attack_pressure[opponent] += 20 * popcount(attack_squares);
            }

            //-- Mobility (not including any squares attacked by enemy pawns)
            moves &= _not_occupied;
            move_count = popcount(moves);
            middlegame += knight_mobility[MIDDLEGAME][move_count];
            endgame += knight_mobility[ENDGAME][move_count];

            // piece-square tables
            middlegame += piece_square_table[piece][MIDDLEGAME][square];
            endgame += piece_square_table[piece][ENDGAME][square];
        }

        //=========================================================
        //-- King Attacks
        //=========================================================
        piece = PIECEINDEX(color, KING);
        eval->attacklist[piece] = king_mask[board->king_square[color]];

		//=========================================================
		//-- Blocked Central Pawns
		//=========================================================
		if (b = (central_kq_pawns[color] & board->pieces[color][PAWN])){
			b = ((b << 8) >> (color * 16)) & board->all_pieces;
			middlegame += -10 * popcount(b);
		}

        //-- Add to board scores
        eval->middlegame += middlegame * (1 - color * 2);
        eval->endgame += endgame * (1 - color * 2);

        //-- Create combined attacks
        eval->attacks[color][BLANK] = eval->attacks[color][PAWN] | eval->attacks[color][ROOK] | eval->attacks[color][BISHOP] | eval->attacks[color][KNIGHT] | eval->attacks[color][QUEEN] | eval->attacks[color][KING];

    }
Ejemplo n.º 18
0
t_chess_value alphabeta(struct t_board *board, int ply, int depth, t_chess_value alpha, t_chess_value beta, BOOL early_cutoff, struct t_move_record *exclude_move) {

    //-- Should we call qsearch?
    if (depth <= 0 && !board->in_check)
        return qsearch_plus(board, ply, depth, alpha, beta);

    //-- Increment the nodes
    nodes++;

    //-- see if we need to update stats */
    if ((nodes & message_update_mask) == 0)
        uci_check_status(board, ply);

    //-- Local Principle Variation variable
    struct t_pv_data *pv = &(board->pv_data[ply]);

    //-- Has the maximum depth been reached
    if (ply >= MAXPLY || uci.stop) {
        pv->best_line_length = ply;
        assert(pv->eval->static_score >= -CHECKMATE && pv->eval->static_score <= CHECKMATE);
        return pv->eval->static_score;
    }

    /* check to see if this is a repeated position or draw by 50 moves */
    if (repetition_draw(board)) {
        pv->best_line_length = ply;
        return 0;
    }

    //-- Mate Distance Pruning
    if (CHECKMATE - ply <= alpha) {
        return alpha;
    }
    else if (-CHECKMATE + ply >= beta) {
        return beta;
    }
    else if ((!board->in_check) && (-CHECKMATE + ply + 2 >= beta)) {
        return beta;
    }

    //-- Declare local variables
    struct t_pv_data *next_pv = pv->next_pv;
    struct t_pv_data *previous_pv = pv->previous_pv;

    t_chess_value					best_score = -CHECKMATE;
    t_chess_value					a = alpha;
    t_chess_value					b = beta;

    //-- Determine what type of node it is
    if (beta > alpha + 1)
        pv->node_type = node_pv;
    else if (previous_pv->node_type == node_pv)
        pv->node_type = node_lite_all;
    else if (previous_pv->node_type == node_cut)
        pv->node_type = node_all;
    else
        pv->node_type = node_cut;

    //-- Probe Hash
    struct t_move_record *hash_move = NULL;
    struct t_hash_record *hash_record = probe(board->hash);

    //-- Has there been a match?
    if (hash_record != NULL) {

		//-- Get the score from the hash table
		t_chess_value hash_score = get_hash_score(hash_record, ply);
		
		//-- Could it make a cut-off?
		if (early_cutoff && hash_record->depth >= depth) {

            //-- Score in hash table is at least as good as beta
            if (hash_record->bound != HASH_UPPER && hash_score >= beta) {
                hash_record->age = hash_age;
                assert(hash_score >= -CHECKMATE && hash_score <= CHECKMATE);
                return hash_score;
            }

            //-- Score is worse than alpha
            if (hash_record->bound != HASH_LOWER && hash_score <= alpha) {
                hash_record->age = hash_age;
                assert(hash_score >= -CHECKMATE && hash_score <= CHECKMATE);
                return hash_score;
            }

            //-- Score is more accurate
            if (hash_record->bound == HASH_EXACT) {
                hash_record->age = hash_age;
                pv->best_line_length = ply;
                update_best_line_from_hash(board, ply);
                assert(hash_score >= -CHECKMATE && hash_score <= CHECKMATE);
                return hash_score;
            }
        }

        //-- Store the hash move for further use!
        hash_move = hash_record->move;

        //-- Use the hash score to refine the node type
        if (hash_record->bound != HASH_UPPER && hash_score >= beta)
            pv->node_type = node_super_cut;

        else if (hash_record->bound != HASH_LOWER && hash_score <= alpha)
            pv->node_type = node_super_all;

        else if (hash_record->bound == HASH_EXACT && pv->node_type == node_all)
            pv->node_type = node_lite_all;
    }

    //-- Beta pruning
    if (early_cutoff && depth <= 4 && pv->node_type != node_pv && beta < MAX_CHECKMATE && beta > -MAX_CHECKMATE && !board->in_check) {

        int pessimistic_score = pv->eval->static_score - depth * 50 - 100;

        if (pessimistic_score >= beta)
            return pessimistic_score;
    }

	//-- Razoring.
	t_chess_value e;	
	if (early_cutoff && (depth <= 4) && pv->node_type != node_pv  && !board->in_check){

		t_chess_value razor_margin = depth * 50 + 50;
		if (pv->eval->static_score + razor_margin <= alpha){

			t_chess_value razor_alpha = alpha - razor_margin;
			e = qsearch_plus(board, ply, depth, razor_alpha, razor_alpha + 1);
			
			if (e <= razor_alpha)
				return e;
		}
	}
		
    //-- Null Move
    t_undo undo[1];

	pv->mate_threat = 0;
	pv->null_refutation = NULL;
	pv->extension = FALSE;
	if (early_cutoff && can_do_null_move(board, pv, ply, alpha, beta)) {

		//-- Calculate Reduction
		//int r = (800 + 70 * depth) / 256 + min(3, (pv->eval->static_score - beta) / 128);
		int r = min(4, 2 + (25 * depth) / 128 + (pv->eval->static_score - beta) / 128);
		//int r = 3;

		//-- Make the changes on the board
		make_null_move(board, undo);

		//-- Store the move in the PV data
		pv->current_move = NULL;

		//-- Clear the Killer +2
		if (ply + 2 <= MAXPLY){
			board->pv_data[ply + 2].killer1 = NULL;
			board->pv_data[ply + 2].killer2 = NULL;
		}

		//-- Evaluate the new board position
		evaluate(board, next_pv->eval);

		//-- Find the new score
		e = -alphabeta(board, ply + 1, depth - r - 1 , -beta, -beta + 1, TRUE, NULL);

		//-- undo the null move
		unmake_null_move(board, undo);

		//-- is it good enough for a cut-off?
		if (e >= beta) {
			if (e > MAX_CHECKMATE)
				e = beta;
			poke(board->hash, e, ply, depth, HASH_LOWER, NULL);
			return e;
		}

		//-- Is there a Mate Threat after a super-reduced move - if so then exit?
		if (e < -MAX_CHECKMATE){
			if (pv->previous_pv->reduction > 1)
				return alpha;
			pv->mate_threat = e;
		}

		//-- Record the move which refuted the NULL move
		if (ply < MAXPLY)
			pv->null_refutation = board->pv_data[ply + 1].current_move;
    }

    //-- Internal Iterative Deepening!
	if (hash_move == NULL && !uci.stop){

		//-- PV Nodes - we *really* need a good move
		if (pv->node_type == node_pv && depth > 2) {

			//-- Search with reduced depth
			e = alphabeta(board, ply, depth - 2, alpha, beta, FALSE, NULL);

			//-- If still no move then search with -INFINITY bound
			if (e <= alpha)
				e = alphabeta(board, ply, depth - 2, -CHESS_INFINITY, beta, FALSE, NULL);

			//-- Probe the hash
			hash_record = probe(board->hash);

			//-- Set the hash move
			if (hash_record != NULL)
				hash_move = hash_record->move;
		}

		//-- Fail high nodes
		//else if ((pv->node_type == node_cut || pv->node_type == node_super_cut) && (depth >= 7) && alpha > -MAX_CHECKMATE && beta < MAX_CHECKMATE){

		//	//-- Search with reduced depth
		//	e = alphabeta(board, ply, depth / 2, alpha, beta);

		//	//-- If still no move then search with -INFINITY bound
		//	if (e <= alpha)
		//		e = alphabeta(board, ply, depth / 2, -CHESS_INFINITY, beta);

		//	//-- Probe the hash
		//	hash_record = probe(board->hash);

		//	//-- Set the hash move
		//	if (hash_record != NULL)
		//		hash_move = hash_record->move;

		//}
    }

    //-- Generate All Moves
    struct t_move_list moves[1];
    moves->hash_move = hash_move;

    if (board->in_check) {
        generate_evade_check(board, moves);

        // Are we in checkmate?
        if (moves->count == 0) {
            pv->best_line_length = ply;
			e = -CHECKMATE + ply;
            return e;
        }
        order_evade_check(board, moves, ply);
    }
    else {
        generate_moves(board, moves);
        order_moves(board, moves, ply);
    }

    //-- Enhanced Transposition Cutoff?
	t_chess_color to_move = board->to_move;
	if (early_cutoff && (depth > 4) && pv->node_type != node_pv && beta < MAX_CHECKMATE && alpha > -MAX_CHECKMATE && !uci.stop) {
        BOOL fail_low;
        while (simple_make_next_move(board, moves, undo)) {

            //-- Calculate Reduction Conservatively i.e. assume minimum reduction
			if (board->in_check)
				pv->reduction = 0;
			else if (PIECETYPE(moves->current_move->piece) == PAWN && COLOR_RANK(to_move, moves->current_move->to_square) >= 6)
				pv->reduction = 0;
			else
				pv->reduction = 1;

            //-- Simple version of alpha_beta for tips of search
            e = -alphabeta_tip(board, ply + 1, depth - pv->reduction, -beta, &fail_low);

            //-- Take the move back
            unmake_move(board, undo);

            //-- Is it good enough for a cutoff?
            if (e >= beta) {
                poke(board->hash, e, ply, depth, HASH_LOWER, moves->current_move);
                assert(e >= -CHECKMATE && e <= CHECKMATE);
                return e;
            }

            //-- Is it going to enhance the move ordering?
            if (fail_low) {
                moves->value[moves->imove] += MOVE_ORDER_ETC;
                assert(moves->move[moves->imove] == moves->current_move);
            }

        }
        //-- Reset the real move count for the "proper" search
        moves->imove = moves->count;
    }

	////-- No Hash Move for Cut Nodes with score below beta and no good capture and no ETC
	//if (hash_move == NULL && (any_fail_low == FALSE) && ((pv->node_type == node_cut) || (pv->node_type == node_super_all)) && (depth >= 3) && (beta > pv->eval->static_score) && no_good_captures(board, moves)){

	//	//-- Search with reduced depth
	//	e = alphabeta(board, ply, depth - 3, alpha, beta);

	//	//-- If still no move then search with -INFINITY bound
	//	if (e <= alpha)
	//		e = alphabeta(board, ply, depth - 3, -CHESS_INFINITY, beta);

	//	//-- Probe the hash
	//	hash_record = probe(board->hash);

	//	//-- Set the hash move
	//	if (hash_record != NULL)
	//		hash_move = hash_record->move;
	//}

    //-- Create the list of "bad" captures
    struct t_move_list bad_moves[1];
    bad_moves->count = 0;
    bad_moves->imove = 0;

    //-- Reset the move count (must be after IID)
    pv->legal_moves_played = 0;

    //-- Variables used to calculate the reduction
	t_chess_color opponent = OPPONENT(to_move);
    BOOL in_check = board->in_check;
    struct t_move_record *last_move = NULL;
	if (ply > 1)
        last_move = board->pv_data[ply - 2].current_move;


    //-- Play moves
    while (!uci.stop && make_next_move(board, moves, bad_moves, undo)) {

        //-- Increment the "legal_moves_played" counter
        pv->legal_moves_played++;
        pv->current_move = moves->current_move;

		//========================================//
		// Futility Pruning
		//========================================//
		if (uci.options.futility_pruning && is_futile(pv, next_pv, depth, a, b)){
			unmake_move(board, undo);
			continue;
		}		
		
		//-- Clear the Killer +2
		if (ply + 2 <= MAXPLY){
			board->pv_data[ply + 2].killer1 = NULL;
			board->pv_data[ply + 2].killer2 = NULL;
		}

		//-- Evaluate the new board position
        evaluate(board, next_pv->eval);

		////========================================//
		//// See if Extension is Necessary
		////========================================//
		//pv->extension = FALSE;
		//if (pv->mate_threat){

		//	e = -alphabeta(board, ply + 1, depth - 1, -CHECKMATE, pv->mate_threat + 2);

		//	pv->extension = (e > pv->mate_threat);

		//	if (e <= pv->mate_threat && e <= a)
		//	{
		//		unmake_move(board, undo);
		//		continue;
		//	}
		//}
			
		//========================================//
		// Calculate reduction
		//========================================//

		struct t_move_record *current_move = pv->current_move;

		//-- In Check?
		if (board->in_check){
			if (see_safe(board, current_move->to_square, 0))
				pv->reduction = 0;
			else if (ply > 3 && board->pv_data[ply - 1].in_check && board->pv_data[ply - 3].in_check)
				pv->reduction = 0;
			else
				pv->reduction = 1;
		}

		//-- Pawn push to 7th
		else if (PIECETYPE(current_move->piece) == PAWN && COLOR_RANK(to_move, current_move->to_square) >= 6){
			
			//-- Pawn Promotion
			if (current_move->promote_to){
				
				if (pv->legal_moves_played == 1 || PIECETYPE(current_move->promote_to) == QUEEN){

					//--Extend if it's a safe pawn promotion or first move
					if ((pv->current_move->captured && moves->current_move_see_positive) || see_safe(board, current_move->to_square, 0))
						pv->reduction = 0;
					else
						pv->reduction = 1;
				}

				// Reduce Heavily if not a queen promotion
				else
					pv->reduction = 5;
			}

			//-- Push to the 7th
			else if (pv->legal_moves_played == 1 || (pv->current_move->captured && moves->current_move_see_positive) || see_safe(board, current_move->to_square, 0))
				pv->reduction = 0;
			else
				pv->reduction = 1;

		}

		//-- First Move?
		else if (pv->legal_moves_played == 1)
			pv->reduction = 1;

		////-- Under Threat of Mate
		//else if (pv->mate_threat)
		//	pv->reduction = 1;

		//-- Good Capture?
		else if (pv->current_move->captured && moves->current_move_see_positive){
			pv->reduction = 1;
		}

		//-- Is this getting out of check?
		else if (in_check){
			if (pv->current_move == pv->check_killer1)
				pv->reduction = 1;
			else if (PIECETYPE(current_move->piece) == KING){
				if (CAN_CASTLE(to_move, board->castling))
					pv->reduction = 4;
				else
					pv->reduction = 1;
			}
			else if (current_move->captured) /* must be a bad capture */
				pv->reduction = 2;
			else if (see_safe(board, current_move->to_square, 0))
				pv->reduction = 1;
			else
				pv->reduction = 2;
		}

		//-- Don't reduce Killers!
		else if (pv->current_move == pv->killer1){
			pv->reduction = 1;
		}

		//-- Does it move a threatened piece?
		else if (pv->null_refutation != NULL && pv->null_refutation->to_square == pv->current_move->from_square){

			if (see_safe(board, current_move->to_square, 0))
				pv->reduction = 1;
			else
				pv->reduction = 3;
		}

		//-- Candidate for serious reductions
		else{

			switch (pv->node_type)
			{
			case node_cut:
				pv->reduction = 3;
				if (pv->current_move->captured)
					pv->reduction += 1; 
				break;

			case node_super_cut:
				pv->reduction = 4;
				if (pv->current_move->captured)
					pv->reduction += 1; 
				break;

			case node_pv:
				if (pv->legal_moves_played > 2)
					pv->reduction = 2;
				else
					pv->reduction = 1;
				break;

			case node_lite_all:
				if (pv->legal_moves_played > 2)
					pv->reduction = 2;
				else
					pv->reduction = 1;
				
				if (pv->current_move->captured)
					pv->reduction += 1;				
				break;

			case node_super_all:
				if (current_move->captured){
					if (pv->legal_moves_played < 4)
						pv->reduction = 3;
					else
						pv->reduction = 4;
				}
				else if (!see_safe(board, current_move->to_square, 0)){
					if (pv->legal_moves_played < 4)
						pv->reduction = 4;
					else if (pv->legal_moves_played < 12)
						pv->reduction = 5;
					else 
						pv->reduction = 6;
				}
				else if (pv->legal_moves_played < 4)
					pv->reduction = 2;
				else if (pv->legal_moves_played < 12)
					pv->reduction = 3;
				else
					pv->reduction = 4;
				break;

			case node_all:
				if (current_move->captured){
					if (pv->legal_moves_played < 4)
						pv->reduction = 3;
					else 
						pv->reduction = 4;
				}
				else if (!see_safe(board, current_move->to_square, 0)){
					if (pv->legal_moves_played < 4)
						pv->reduction = 4;
					else 
						pv->reduction = 5;
				}
				else if (pv->legal_moves_played < 4)
					pv->reduction = 2;
				else if (pv->legal_moves_played < 18)
					pv->reduction = 3;
				else
					pv->reduction = 4;
				break;

			}

		}

        //-- Search the next ply at reduced depth
        e = -alphabeta(board, ply + 1, depth - pv->reduction, -b, -a, TRUE, NULL);

        //-- Fail high on a super-reduced move?
        if (e > a && pv->reduction > 1) {
            pv->reduction = 1;

            //-- Search again using the full width
            e = -alphabeta(board, ply + 1, depth - 1, -beta, -a, TRUE, NULL);
        }

        //-- Is a research required?
        else if (alpha + 1 != beta && e > a && a + 1 == b)
            e = -alphabeta(board, ply + 1, depth - pv->reduction, -beta, -a, TRUE, NULL);

        unmake_move(board, undo);

        //-- Is it good enough to cut-off?
        if (e >= beta) {
            if (board->in_check)
                update_check_killers(pv, depth);
            else
                update_killers(pv, depth);

            //-- Record the cutoff
            cutoffs++;
            if (pv->legal_moves_played == 1)
                first_move_cutoffs++;

            //-- Store in the hash table
            poke(board->hash, e, ply, depth, HASH_LOWER, pv->current_move);
            return e;
        }

        //-- Is it the best so far?
        if (e > best_score) {
            best_score = e;

            //-- Does it improve upon alpha (i.e. is it part of the PV)?
            if (e > a) {
                a = e;

                //-- Update the Principle Variation
                update_best_line(board, ply);
            }
        }

        // Reset the zero width window
        b = a + 1;

		//-- Was this a fail low at a node which should have failed high?
		//if (pv->node_type == )
    }

    //-- Is it a draw
    if (pv->legal_moves_played == 0) {
        pv->best_line_length = ply;
        return 0;
    }

    //-- Update Hash
    if (best_score > alpha)
        poke(board->hash, best_score, ply, depth, HASH_EXACT, pv->best_line[ply]);
	else
        poke(board->hash, best_score, ply, depth, HASH_UPPER, NULL);

    // Return Best Score found
    assert(best_score >= -CHECKMATE && best_score <= CHECKMATE);
    return best_score;

}
Ejemplo n.º 19
0
bool
is_middle_ladder(Board *b, Coord coord, group_t laddered, Stone lcolor)
{
	/* TODO: Remove the redundant parameters. */
	assert(group_at(b, laddered)->liberties == 1);

  Coord last_lib = get_nlibs_of_group(b, laddered, 1, NULL);
	assert(last_lib == coord);
	assert(group_at(b, laddered)->color == lcolor);

	/* If we can move into empty space or do not have enough space
	 * to escape, this is obviously not a ladder. */
	if (immediate_liberty_count(b, coord) != 2) {
    /*
		if (DEBUGL(5))
			fprintf(stderr, "no ladder, wrong free space\n");
    */
		return false;
	}

	/* A fair chance for a ladder. Group in atari, with some but limited
	 * space to escape. Time for the expensive stuff - set up a temporary
	 * board and start selective 2-liberty search. */

	Board *bset = (Board *)malloc(BOARD_MAX_SIZE * 2 * sizeof(Board));

	struct move_queue ccq = { .moves = 0 };
	if (can_countercapture(b, lcolor, laddered, lcolor, &ccq, 0)) {
		/* We could escape by countercapturing a group.
		 * Investigate. */
		assert(ccq.moves > 0);
		for (unsigned int i = 0; i < ccq.moves; i++) {
			Board b2;
			CopyBoard(&b2, b);
			bool is_ladder = middle_ladder_walk(&b2, bset, laddered, ccq.move[i], lcolor);
			// board_done_noalloc(&b2);
			if (!is_ladder) {
				free(bset);
				return false;
			}
		}
	}

	Board b2;
  CopyBoard(&b2, b);
  Coord last_lib2 = get_nlibs_of_group(&b2, laddered, 1, NULL);

	bool is_ladder = middle_ladder_walk(&b2, bset, laddered, last_lib2, lcolor);
	// board_done_noalloc(&b2);
	free(bset);
	return is_ladder;
}

bool
wouldbe_ladder(Board *b, group_t group, Coord escapelib, Coord chaselib, Stone lcolor)
{
	assert(b->_groups[group].liberties == 2);
	assert(b->_groups[group].color == lcolor);

  /*
	if (DEBUGL(6))
		fprintf(stderr, "would-be ladder check - does %s %s play out chasing move %s?\n",
			stone2str(lcolor), coord2sstr(escapelib, b), coord2sstr(chaselib, b));
  */

	if (!NEIGHBOR8(escapelib, chaselib)) {
    /*
		if (DEBUGL(5))
			fprintf(stderr, "cannot determine ladder for remote simulated stone\n");
    */
		return false;
	}

	if (neighbor_count_at(b, chaselib, lcolor) != 1 || immediate_liberty_count(b, chaselib) != 2) {
    /*
		if (DEBUGL(5))
			fprintf(stderr, "overly trivial for a ladder\n");
    */
		return false;
	}

	bool is_ladder = false;
	Board *bset = (Board *)malloc(BOARD_MAX_SIZE * 2 * sizeof(Board));
	Board b2;
	CopyBoard(&b2, b);

  GroupId4 ids;
  if (TryPlay(&b2, X(chaselib), Y(chaselib), OPPONENT(lcolor), &ids)) {
    Play(&b2, &ids);
    Coord last_lib2 = get_nlibs_of_group(&b2, group, 1, NULL);
		is_ladder = middle_ladder_walk(&b2, bset, group, last_lib2, lcolor);
  }

	// board_done_noalloc(&b2);
	free(bset);
	return is_ladder;
}
Ejemplo n.º 20
0
// ----------------------------------------------------------------------------
void AICarbon::undo()
{
  int x, y, k;
  UCHAR p;
  int xp, yp;

  assert(check());

  moveCount--;
  xp = remMove[moveCount].x;
  yp = remMove[moveCount].y;
  upperLeftCand = remULCand[moveCount];
  lowerRightCand = remLRCand[moveCount];

  OXCell* c = remCell[moveCount];
  c->update1(0);
  c->update1(1);
  c->update1(2);
  c->update1(3);
  c->update4();

  nSt[0][c->status4[0]]++;
  nSt[1][c->status4[1]]++;
  
  c->piece = EMPTY;
  
  // zamiana graczy    
  who = OPPONENT(who);
  opp = OPPONENT(opp);

  // aktualizowanie mieszania
  table.undo(xp, yp, who);

  // modyfikowanie <pat>
  for (k = 0; k < 4; k++)
    {
      x = xp; y = yp;
      for (p = 16; p != 0; p <<= 1)
        {
          x -= DX[k]; y -= DY[k];
          cell[x][y].pattern[k][who] ^= p;
          if (cell[x][y].piece == EMPTY)// && (cell[x][y].adj1 || cell[x][y].adj2))
            {
              cell[x][y].update1(k);
              nSt[0][cell[x][y].status4[0]]--; nSt[1][cell[x][y].status4[1]]--;
              cell[x][y].update4();
              nSt[0][cell[x][y].status4[0]]++; nSt[1][cell[x][y].status4[1]]++;
            }
        }
      x = xp; y = yp;
      for (p = 8; p != 0; p >>= 1)
        {
          x += DX[k]; y += DY[k];
          cell[x][y].pattern[k][who] ^= p;
          if (cell[x][y].piece == EMPTY)// && (cell[x][y].adj1 || cell[x][y].adj2))
            {
              cell[x][y].update1(k);
              nSt[0][cell[x][y].status4[0]]--; nSt[1][cell[x][y].status4[1]]--;
              cell[x][y].update4();
              nSt[0][cell[x][y].status4[0]]++; nSt[1][cell[x][y].status4[1]]++;
            }
        }
    }
  
  // usuwanie kandydatow
  cell[xp - 1][yp - 1].adj1--; cell[xp    ][yp - 1].adj1--; cell[xp + 1][yp - 1].adj1--;
  cell[xp - 1][yp    ].adj1--;                              cell[xp + 1][yp    ].adj1--;
  cell[xp - 1][yp + 1].adj1--; cell[xp    ][yp + 1].adj1--; cell[xp + 1][yp + 1].adj1--;
  cell[xp - 2][yp - 2].adj2--; cell[xp    ][yp - 2].adj2--; cell[xp + 2][yp - 2].adj2--;
  cell[xp - 2][yp    ].adj2--;                              cell[xp + 2][yp    ].adj2--;
  cell[xp - 2][yp + 2].adj2--; cell[xp    ][yp + 2].adj2--; cell[xp + 2][yp + 2].adj2--;

  assert(check());
}
Ejemplo n.º 21
0
/** Puteti folosi functia negaMax pentru a implementa un AI pe baza de negaMAX.
 *
 * Functia primeste ca parametri:
 * 
 * player = Jucatorul care trebuie sa mute in continuare (identitatea
 *          calculatorului care gandeste cu aceasta functie).
 *           Valorile posibile sunt { XOBoard::PlayerX, XOBoard::PlayerO }
 *
 * board = Tabla pe care o vede jucatorul care trebuie sa mute in continuare.
 *
 * alpha = Inseamna ca player a gasit deja o cale prin care pot sa termin
 *         jocul cu un scor cel putin egal cu alpha.
 *
 * beta = Inseamna ca OPPONENT(player) a gasit o cale prin care sa-l forteze pe
 *        player sa termine jocul cu un scor cel mult egal cu beta (cu alte
 *        cuvinte daca player gaseste o modalitate sa castige mai mult de beta,
 *        cel mai probabil analizeaza un scenariu nerealist in care a presupus
 *        ca OPPONENT(player) a fost prost la un moment dat si a facut o
 *        greseala.
 */
std::pair<int, XOBoard> negaMax(XOBoard::Player player,
                                XOBoard board,
                                int alpha,
                                int beta)
{
  /* Daca s-a terminat jocul, scorul este cel raportat. */
  if (board.game_over()) {
    int myScore = board.get_score(player) - board.get_score(OPPONENT(player));
    return std::pair<int, XOBoard>(myScore, board);
  }

  /* Generam lista de expansiuni ale tablei (toate mutarile viitoare). */
  std::vector<XOBoard> expansions;
  for (unsigned int i = 0; i < 3; ++i) {
    for (unsigned int j = 0; j < 3; ++j) {
      if (board.get(i, j) == '_') {
        board.put(player, i, j);
        expansions.push_back(board);
        board.erase(i, j);
      }
    }
  }

  /* Verificam care este mutarea cea mai inteleapta. */
  XOBoard nextMove;
  for (unsigned int i = 0; i < expansions.size(); ++i) {
    /* Fiindca urmatorul nivel de negaMax este privit din partea oponentului,
     * cand apelez functia trebuie sa neg pe alfa si sa i-l servesc drept
     * beta pentru ca asta inseamna ca il "avertizez" ca nu sunt fraier si ca
     * deja stiu un mod prin care el nu poate sa faca mai mult decat -alpha.
     *
     * Pe de alta parte, desi eu il limitez pe el superior, din punct de vedere
     * inferior nu am nici un motiv sa-l limitez, asa ca ii voi servi un alpha
     * egal cu -INF (nu stiu cat de prost poate el sa joace, n-am cum sa-mi dau
     * seama).
     */

    /* Acum ne gandim cum s-ar descurca el in situatia asta. */
    std::pair<int, XOBoard> outcome = negaMax(
        OPPONENT(player), expansions[i], -INF, -alpha);

    /* Vedem ce miscare a reusit sa scoata el in conditiile date. */
    int myScore = -outcome.first;

    /* Analizam jocul din perspectiva taierii alfa-beta. */
    if (myScore > beta) {
      /* Inseamna ca asta e un scenariu in care el ar fi facut o greseala. Noi
       * stim ca el nu e prost, asa ca din moment ce a gasit deja mai sus in
       * arbore o modalitate prin care sa ma faca sa termin jocul cu cel mult
       * beta, n-o sa joace in asa fel incat sa ma puna pe mine in situatia
       * asta de acum. Aplicam deci, taierea beta. */
      return std::pair<int, XOBoard>(beta, nextMove);
    } else if (myScore > alpha) {
      /* Inseamna ca tocmai am gasit o miscare prin care eu sa castig la sigur
       * mai mult decat stiam inainte ca pot sa castig (daca vreti, un fel de
       * plan "la sigur" mai bun).
       */
      alpha = myScore;
      nextMove = expansions[i];
    }
  }

  /* Raportam mutarea aleasa ca fiind cea mai buna. */
  return std::pair<int, XOBoard>(alpha, nextMove);
}
Ejemplo n.º 22
0
int inCheck(const position * const pos, const int player, const int targetSquare)
{
    bitboard attacks = 0;
    int opponent = OPPONENT(player);
    int sq = 0;
    bitboard knights = 0;
    bitboard allPieces = 0;
    bitboard rooks = 0;
    bitboard bishops = 0;
    bitboard pawns = 0;
    int rankState;
    int fileState;
    int rank;
    int file;
    bitboard rot_a1h8;
    bitboard rot_h1a8;
    int state;
    bitboard target;
    /* should be used only for kings or empty squares */
    assert(((targetSquare == pos->kingSquare[player])) ||
        ((_mask[targetSquare] & (pos->pieces[WHITE] | pos->pieces[BLACK])) == 0));
    if(targetSquare == pos->kingSquare[player]) {
        target = pos->king[player];
    }
    else {
        target = _mask[targetSquare];
    }
    /* opponent king attacks */
    attacks |= _king[pos->kingSquare[opponent]];
    /* incremental checking... */
    if(attacks & target) {
        return 1;
    }
    /* opponent knight attacks */
    knights = pos->knights[opponent];
    sq = 0;
    while(knights != 0) {
        if(LSB_SET(knights)) {
            attacks |= _knight[sq];
            /* incremental checking... */
            if(attacks & target) {
                return 1;
            }
        }
        knights = knights >> 1;
        sq++;
    }
    allPieces = pos->pieces[WHITE] | pos->pieces[BLACK];

    /* rook and queen attacks */
    rooks = pos->rooks[opponent] | pos->queens[opponent];

    sq = 0;
    while(rooks != 0) {
        if(LSB_SET(rooks)) {
            rank = sq / 8;
            rankState = RANK_STATE(allPieces, rank);
            attacks |= _horz[sq][rankState];
            file = sq % 8;
            fileState = FILE_STATE(rotate(allPieces), file);
            attacks |= _vert[sq][fileState];


            /* incremental checking... */
            if(attacks & target) {
                return 1;
            }
        }
        rooks = rooks >> 1;
        sq++;
    }
    /* bishop and queen attacks */
    bishops = pos->bishops[opponent] | pos->queens[opponent];
    sq = 0;

    attacks = 0; // remove
    while(bishops != 0) {
        if(LSB_SET(bishops)) {

            rot_a1h8 = rotate_a1h8(allPieces);
            state = A1H8_STATE(rot_a1h8, sq);
            attacks |= _a1h8[sq][state];
            rot_h1a8 = rotate_h1a8(allPieces);
            state = H1A8_STATE(rot_h1a8, sq);
            attacks |= _h1a8[sq][state];

            /* incremental checking... */
            if(attacks & target) {
                return 1;
            }
        }
        bishops = bishops >> 1;
        sq++;
    }
    /* pawn attacks */
    pawns = pos->pawns[opponent];
    sq = 0;
    while(pawns != 0) {
        if(LSB_SET(pawns)) {
            if(WHITE == opponent) {
                attacks |= _wpawn_attack[sq];
            }
            else {
                attacks |= _bpawn_attack[sq];
            }
            /* incremental checking... */
            if(attacks & target) {
                return 1;
            }
        }
        pawns = pawns >> 1;
        sq++;
    }
    return 0;
}
static void update_online_model(ThreadInfo *info, Stone player, TreeBlock *b) {
  TreeHandle *s = info->s;
  TreePool *p = &s->p;
  if (b == NULL) error("update_online_model: input b cannot be NULL!");

  pthread_mutex_lock(&s->mutex_online_model);

  // Backprop from b.
  // Note that for any new tree block, its first opp_preds will be update here. (So a policy will never
  // avoid a nonleaf child just because its opp_preds is "empty").
  for (;b != p->root; b = b->parent, player = OPPONENT(player)) {
    TreeBlock * parent = b->parent;
    BlockOffset parent_offset = b->parent_offset;
    const Stat* stat = &b->parent->data.stats[parent_offset];

    if (b->extra == NULL) continue;

    // Compute online prediction.
    PRINT_DEBUG("In update_online_model, compute online prediction..\n");
    float pred = s->model_bias;
    for (int i = 0; i < BOARD_SIZE * BOARD_SIZE; i ++) {
      pred += s->model_weights[i] * b->extra[i];
    }
    pred = sigmoid(pred);
    // For the parent, it is the win rate from opponent point of view.
    b->parent->data.opp_preds[parent_offset] = pred;

    PRINT_DEBUG("In update_online_model, finish computing online prediction..\n");

    BOOL update_model = FALSE;
    float weight = 0.0;
    float target = -1.0;
    if (s->params.life_and_death_mode) {
      // if the current b/w number has zero, then it is an end state and we should update the model, otherwise pass.
      const ProveNumber *pn = &b->parent->cnn_data.ps[parent_offset];
      if (pn == NULL) error("update_online_model: pn cannot be NULL!");
      PRINT_DEBUG("In update_online_model with life_and_death_mode is on. Before we set target..\n");
      if ((pn->b == 0 && player == S_BLACK) || (pn->w == 0 && player == S_WHITE)) target = 1.0;
      if ((pn->b == 0 && player == S_WHITE) || (pn->w == 0 && player == S_BLACK)) target = 0.0;
      if (target > 0) update_model = TRUE;
      weight = 10.0;
    } else {
      // Normal mode.
      // Get actual win rate.
      float win_rate = ((float)stat->black_win) / stat->total;
      if (player == S_WHITE) win_rate = 1 - win_rate;

      update_model = stat->total > 30;
      target = win_rate;
      weight = min(stat->total, 1000);
    }

    // One must make sure that if update_model is TRUE, target must be meaningful.
    PRINT_DEBUG("In update_online_model, accumulate the error ...\n");
    float err = target - pred;
    if (target >= 0) {
      // Mean average.
      s->model_acc_err += fabs(err);
      s->model_count_err ++;
    }

    // Gradient update.
    if (target >= 0 && update_model) {
      PRINT_DEBUG("In update_online_model, update the model ...");
      // Update the weights as well.
      // y = f(w . x + b)
      // objective:  min ||y - f(w.x+b)||^2,
      //   Note that: err = y - f(w.x+b), f' = f * (1 - f)
      // grad w_i = - err * f(1-f) * x_i
      // grad b = - err * f(1-f)
      float alpha = err * pred * (1 - pred) * weight * s->params.online_model_alpha;

      for (int i = 0; i < BOARD_SIZE * BOARD_SIZE;  ++i) {
        // Add negative gradient.
        s->model_weights[i] += alpha * b->extra[i];
      }
      s->model_bias += alpha;
    }
  }

  pthread_mutex_unlock(&s->mutex_online_model);
}
Ejemplo n.º 24
0
// ----------------------------------------------------------------------------
// xp, yp in <4, boardSize + 4)
void AICarbon::_move(int xp, int yp)
{
  nSearched++;

  int x, y, k;
  UCHAR p;

  assert(check());
  nSt[0][cell[xp][yp].status4[0]]--;
  nSt[1][cell[xp][yp].status4[1]]--;
  
  cell[xp][yp].piece = who;
  remCell[moveCount] = &cell[xp][yp];
  remMove[moveCount] = OXPoint(xp, yp);
  remULCand[moveCount] = upperLeftCand;
  remLRCand[moveCount] = lowerRightCand;
  moveCount++;

  if(xp - 2 < upperLeftCand.x) upperLeftCand.x = __max(xp - 2, 4);
  if(yp - 2 < upperLeftCand.y) upperLeftCand.y = __max(yp - 2, 4);
  if(xp + 2 > lowerRightCand.x) lowerRightCand.x = __min(xp + 2, boardWidth + 3);
  if(yp + 2 > lowerRightCand.y) lowerRightCand.y = __min(yp + 2, boardHeight + 3);
  
  // modyfikowanie <pat> i <points>         
  for (k = 0; k < 4; k++)
    {
      x = xp; y = yp;
      for (p = 16; p != 0; p <<= 1)
        {
          x -= DX[k]; y -= DY[k];
          cell[x][y].pattern[k][who] |= p;
          if (cell[x][y].piece == EMPTY)// && (cell[x][y].adj1 || cell[x][y].adj2))
            {
              cell[x][y].update1(k);
              nSt[0][cell[x][y].status4[0]]--; nSt[1][cell[x][y].status4[1]]--;
              cell[x][y].update4();
              nSt[0][cell[x][y].status4[0]]++; nSt[1][cell[x][y].status4[1]]++;
            }
        }
      x = xp; y = yp;
      for (p = 8; p != 0; p >>= 1)
        {
          x += DX[k]; y += DY[k];
          cell[x][y].pattern[k][who] |= p;
          if (cell[x][y].piece == EMPTY)// && (cell[x][y].adj1 || cell[x][y].adj2))
            {
              cell[x][y].update1(k);
              nSt[0][cell[x][y].status4[0]]--; nSt[1][cell[x][y].status4[1]]--;
              cell[x][y].update4();
              nSt[0][cell[x][y].status4[0]]++; nSt[1][cell[x][y].status4[1]]++;
            }
        }
    }
    
  // dodawanie kandydatow
  cell[xp - 1][yp - 1].adj1++; cell[xp    ][yp - 1].adj1++; cell[xp + 1][yp - 1].adj1++;
  cell[xp - 1][yp    ].adj1++;                              cell[xp + 1][yp    ].adj1++;
  cell[xp - 1][yp + 1].adj1++; cell[xp    ][yp + 1].adj1++; cell[xp + 1][yp + 1].adj1++;
  cell[xp - 2][yp - 2].adj2++; cell[xp    ][yp - 2].adj2++; cell[xp + 2][yp - 2].adj2++;
  cell[xp - 2][yp    ].adj2++;                              cell[xp + 2][yp    ].adj2++;
  cell[xp - 2][yp + 2].adj2++; cell[xp    ][yp + 2].adj2++; cell[xp + 2][yp + 2].adj2++;

  // aktualizowanie mieszania
  table.move(xp, yp, who);

  // zamiana graczy    
  who = OPPONENT(who);
  opp = OPPONENT(opp);

  assert(check());
}
Ejemplo n.º 25
0
/* Checks whether a move is valid, except for whether this puts own king in check. */
static int move_is_semi_valid(board_t *board, move_t *move)
{
    /* Bounds check. */
    if ((move->source > 63) || (move->source < 0))
        return 0;

    if ((move->destination > 63) || (move->destination < 0))
        return 0;

    /* Test for moving to same square. */
    if (move->source == move->destination)
        return 0;

    /* Test for empty source square. */
    if (board->square[move->source] == NONE)
        return 0;

    /* Test for moving opponent's piece. */
    if (COLOUR(board->square[move->source]) != board->turn)
        return 0;

    /* Check that a promotion piece is specified for promotion moves. */
    if ((PIECE(board->square[move->source]) == PAWN) && ((move->destination < 8) || (move->destination >= 56)))
    {
        switch (PIECE(move->promotion_piece))
        {
        case KNIGHT:
        case ROOK:
        case BISHOP:
        case QUEEN:
            break;
        default:
            return 0;
        }

        if (COLOUR(move->promotion_piece) != board->turn)
            return 0;
    }
    else if (move->promotion_piece != NONE)
        /* Promotion piece specified for non-promotion move. */
        return 0;

    switch (PIECE(board->square[move->source]))
    {
    case KNIGHT:
        if ((HOR != 1) && (HOR != 2))
            return 0;
        if ((HOR == 1) && (VERT != 2))
            return 0;
        if ((HOR == 2) && (VERT != 1))
            return 0;
        if (board->square[move->destination] == NONE)
            break;
        if (COLOUR(board->square[move->destination]) == COLOUR(board->square[move->source]))
            return 0;
        break;
    case BISHOP:
        if (HOR != VERT)
            return 0;
        if (!ray_ok(board, move))
            return 0;
        break;
    case ROOK:
        if ((HOR != 0) && (VERT != 0))
            return 0;
        if (!ray_ok(board, move))
            return 0;
        break;
    case QUEEN:
        if ((HOR != 0) && (VERT != 0) && (HOR != VERT))
            return 0;
        if (!ray_ok(board, move))
            return 0;
        break;
    case PAWN:
        /* Catch moves in wrong direction. */
        if ((move->destination > move->source) && (COLOUR(board->square[move->source]) == BLACK))
            return 0;
        if ((move->destination < move->source) && (COLOUR(board->square[move->source]) == WHITE))
            return 0;

        if (HOR > 1)
            return 0;

        if (HOR == 0)
        {
            /* Regular or double push. */

            if (VERT > 2)
                return 0;
            if (VERT == 2)
                if (!(((move->source >= 8) && (move->source <= 15)) || ((move->source >= 48) && (move->source <= 55))))
                    return 0;
            /* Use ray checking code with added requirement that destination square is empty. */
            if (!ray_ok(board, move) || (board->square[move->destination] != NONE))
                return 0;
        }
        else
        {
            if (VERT != 1)
                return 0;
            if (!ray_ok(board, move))
                return 0;
            /* En-passant move. */
            if (board->square[move->destination] == NONE)
            {
                if ((COLOUR(board->square[move->source]) == WHITE) && !((move->source >= 32) && (move->source < 40)))
                    return 0;
                if ((COLOUR(board->square[move->source]) == BLACK) && !((move->source >= 24) && (move->source < 32)))
                    return 0;

                if (board->square[move->destination + (COLOUR(board->square[move->source]) == WHITE ? -8 : 8)] !=
                        PAWN + OPPONENT(COLOUR(board->square[move->source])))
                    return 0;
            }

        }
        break;
    case KING:
        if (HOR > 2)
            return 0;
        else if (HOR == 2)
        {
            int white = COLOUR(board->square[move->source]) == WHITE;

            int i, step = (move->destination > move->source ? 1 : -1);
            int rook = (step == 1 ? (white ? 7 : 63) : (white ? 0 : 56));

            /* Castling. */
            if (VERT != 0)
                return 0;

            if (move->source != (white ? 4 : 60))
                return 0;

            if (board->square[rook] != ROOK + COLOUR(board->square[move->source]))
                return 0;

            i = move->source + step;

            while (i != rook)
            {
                if (board->square[i] != NONE)
                    return 0;
                i += step;
            }

            /* Check whether any of the squares the king moves over is under
            ** attack. Note that destination square is checked later.
            */
            if (square_attacked(board, move->source, (white ? BLACK : WHITE)))
                return 0;
            if (square_attacked(board, move->source + step, (white ? BLACK : WHITE)))
                return 0;
        }
        else
        {
            if (VERT > 1)
                return 0;
            if (!ray_ok(board, move))
                return 0;
        }
    }
    return 1;
}
Ejemplo n.º 26
0
int main(int argc, char *argv[])
{
	if (argc < 5) {
		printf("Usage: %s server_hostname server_port opponent_level"
		    "(1=dumb, 5, 7, 8)own_level(1=dumb, 5, 7, 8)\n", argv[0]);
		exit(0);
	}

	//Datele pentru conexiune
	int sockfd, portno;
	struct sockaddr_in serv_addr;
	struct hostent *server;

	//Initializari & creare socket
	portno = atoi(argv[2]);
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0){
		error("ERROR opening socket");
	}
	server = gethostbyname(argv[1]);
	if (server == NULL) {
		fprintf(stderr,"ERROR, no such host\n");
		exit(0);
	}
	bzero((char *) &serv_addr, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	bcopy((char *)server->h_addr,
			(char *)&serv_addr.sin_addr.s_addr,
			server->h_length);
	serv_addr.sin_port = htons(portno);

	//Conectare la server
	if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
		error("ERROR connecting");
	}

	//Trimitem primul mesaj - dificultatea adversarului
	char buffer[256];
	bzero(buffer,256);
	buffer[0] = atoi(argv[3]);
	char message_size = 1; // Trimitem 1 octet
	sendMessage(sockfd, &message_size, 1);
	sendMessage(sockfd, buffer, 1);


	// primesc raspuns cu culoarea
	Player player;
	bzero(buffer,256);
	char read_message_size;
	readMessage(sockfd, &read_message_size, 1);
	readMessage(sockfd, buffer, read_message_size);
	if (buffer[0] == 0) {
		/* sunt jucatorul alb */
		player = White;
		printf("Sunt alb!\n");
	} else if (buffer[0] == 1) {
		/* sunt jucatorul negru */
		player = Black;
		printf("Sunt negru!\n");
	}else{
		// mesaj invalid; eroare!
	}
	
	BGBoard board; 
	Moves next_move;
	int dice1, dice2, n;

	while (true) 
	{
		bzero(buffer,256);
		
		readMessage(sockfd, &read_message_size, 1); 
		readMessage(sockfd, buffer, read_message_size); 

		if (read_message_size == 1) {
     	 	// Jocul s-a terminat;
      		if (buffer[0] == 'W') {
        		printf("WE WON\n");
      		} else {
        		printf("WE LOST\n");
      		}
      		break;
    	}

    	/* se efectueaza mutarea adversarului */
    	for (int i = 0; i < read_message_size-2; i+=2) {
    		board.move(OPPONENT(player),buffer[i],buffer[i+1]);
		}
		
		/* se extrage zarul din mesajul primit */
		dice1 = buffer[read_message_size-2];
    	dice2 = buffer[read_message_size-1];

    	/* se calculeaza mutarea optima pentru mine */
    	next_move = think(board,player,dice1,dice2);

		n = (int)next_move.size();

		/* daca nu am gasit nicio mutare valida, trimit mesaj de '0' bytes */
    	if (!n) {
    		sendMessage(sockfd, (char*) &n, 1); 
    		continue;
    	}

    	/* altfel se efectueaza mutarea */
    	bzero(buffer,256);
    	for (int i = 0; i < n; i+=2) {	
    		buffer[i] = (char)next_move[i];
    		buffer[i+1] = (char)next_move[i+1];
    		board.move(player,next_move[i],next_move[i+1]);
    	}
    	
    	/* se trimite la server un mesaj cu mutarea pe care vreau sa o fac */
		sendMessage(sockfd, (char*) &n, 1); 
    	sendMessage(sockfd, buffer, n); 
    	printf("Message sent!\n");
    }
	
	close(sockfd);
	return 0;
}
Ejemplo n.º 27
0
void configure_piece_moves(int *i)
{
    int delta, d;
    t_chess_square s, target;
    t_chess_color color, opponent;
    t_chess_piece p, move_piece, capture;
    struct t_move_record *move = &xmove_list[*i];

    for (color = WHITE; color <= BLACK; color++) {
        opponent = OPPONENT(color);
        for (s = A1; s <= H8; s++) {
            for (p = KNIGHT; p <= KING; p++) {
                if (PIECETYPE(p) != PAWN) {
                    move_piece = p + (color * 8);
                    if (slider[p]) {
                        d = 0;
                        for (delta = direction[p][d]; (delta = direction[p][d]) != 0; d++) {
                            target = x88_SQUARE(s) + delta;
                            while (x88_ONBOARD(target)) {
                                move->captured = BLANK;
                                move->from_square = s;
                                move->to_square = x88_TO_64(target);
                                move->move_type = MOVE_PIECE_MOVE;
                                move->piece = move_piece;
                                move->promote_to = BLANK;
                                move_directory[move->from_square][move->to_square][move->piece] = move;
                                (*i)++;
                                move++;
                                for (capture = KNIGHT; capture <= QUEEN; capture++) {
                                    move->captured = capture + (opponent * 8);
                                    move->from_square = s;
                                    move->to_square = x88_TO_64(target);
                                    move->move_type = MOVE_PIECExPIECE;
                                    move->piece = move_piece;
                                    move->promote_to = BLANK;
                                    (*i)++;
                                    move++;
                                }
                                if ((x88_TO_64(target) >= A2) && (x88_TO_64(target) <= H7)) {
                                    move->captured = PAWN + (opponent * 8);
                                    move->from_square = s;
                                    move->to_square = x88_TO_64(target);
                                    move->move_type = MOVE_PIECExPAWN;
                                    move->piece = move_piece;
                                    move->promote_to = BLANK;
                                    (*i)++;
                                    move++;
                                }
                                target += delta;
                            }
                        }
                    }
                    else
                    {
                        d = 0;
                        for (delta = direction[p][d]; (delta = direction[p][d]) != 0; d++) {
                            target = x88_SQUARE(s) + delta;
                            if (x88_ONBOARD(target)) {
                                move->captured = BLANK;
                                move->from_square = s;
                                move->to_square = x88_TO_64(target);
                                if (PIECETYPE(move_piece) == KING)
                                    move->move_type = MOVE_KING_MOVE;
                                else
                                    move->move_type = MOVE_PIECE_MOVE;
                                move->piece = move_piece;
                                move->promote_to = BLANK;
                                move_directory[move->from_square][move->to_square][move->piece] = move;
                                (*i)++;
                                move++;
                                for (capture = KNIGHT; capture <= QUEEN; capture++) {
                                    move->captured = capture + (opponent * 8);
                                    move->from_square = s;
                                    move->to_square = x88_TO_64(target);
                                    if (PIECETYPE(move_piece) == KING)
                                        move->move_type = MOVE_KINGxPIECE;
                                    else
                                        move->move_type = MOVE_PIECExPIECE;
                                    move->piece = move_piece;
                                    move->promote_to = BLANK;
                                    (*i)++;
                                    move++;
                                }
                                if ((x88_TO_64(target) >= A2) && (x88_TO_64(target) <= H7)) {
                                    move->captured = PAWN + (opponent * 8);
                                    move->from_square = s;
                                    move->to_square = x88_TO_64(target);
                                    if (PIECETYPE(move_piece) == KING)
                                        move->move_type = MOVE_KINGxPAWN;
                                    else
                                        move->move_type = MOVE_PIECExPAWN;
                                    move->piece = move_piece;
                                    move->promote_to = BLANK;
                                    (*i)++;
                                    move++;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Ejemplo n.º 28
0
static bool
middle_ladder_walk(Board *b, Board *bset, group_t laddered, Coord nextmove, Stone lcolor)
{
	assert(group_at(b, laddered)->liberties == 1);

	/* First, escape. */
  /*
	if (DEBUGL(6))
		fprintf(stderr, "  ladder escape %s\n", coord2sstr(nextmove, b));
  */
  GroupId4 ids;
  if (!TryPlay2(b, nextmove, &ids)) error("The play should never be wrong!");
  Play(b, &ids);

	// laddered = group_at(b, laddered);
  /*
	if (DEBUGL(8)) {
		board_print(b, stderr);
		fprintf(stderr, "%s c %d\n", coord2sstr(laddered, b), board_group_info(b, laddered).libs);
	}
  */

  int laddered_libs = b->_groups[laddered].liberties;

	if (laddered_libs == 1) {
    /*
		if (DEBUGL(6))
			fprintf(stderr, "* we can capture now\n");
    */
		return true;
	}
	if (laddered_libs > 2) {
    /*
		if (DEBUGL(6))
			fprintf(stderr, "* we are free now\n");
    */
		return false;
	}

  FOR4(nextmove, _, c) {
		if (board_at(b, c) == OPPONENT(lcolor) && group_at(b, c)->liberties == 1) {
			/* We can capture one of the ladder stones
			 * anytime later. */
			/* XXX: If we were very lucky, capturing
			 * this stone will not help us escape.
			 * That should be pretty rate. */
      /*
			if (DEBUGL(6))
				fprintf(stderr, "* can capture chaser\n");
      */
			return false;
		}
	} ENDFOR4

	/* Now, consider alternatives. */
	int liblist[2], libs = 0;
  Coord tmp_libs[2];
  get_nlibs_of_group(b, laddered, 2, tmp_libs);
	for (int i = 0; i < 2; i++) {
		Coord ataristone = tmp_libs[i];
		Coord escape = tmp_libs[1 - i];
		if (immediate_liberty_count(b, escape) > 2 + NEIGHBOR4(ataristone, escape)) {
			/* Too much free space, ignore. */
			continue;
		}
		liblist[libs++] = i;
	}

	/* Try out the alternatives. */
	bool is_ladder = false;
	for (int i = 0; !is_ladder && i < libs; i++) {
		Board *b2 = b;
		if (i != libs - 1) {
			b2 = bset++;
      CopyBoard(b2, b);
		}

    Coord libs_b2[2];
    get_nlibs_of_group(b2, laddered, 2, libs_b2);

		Coord ataristone = libs_b2[liblist[i]];
		// Coord escape = board_group_info(b2, laddered).lib[1 - liblist[i]];
		struct move m = { ataristone, OPPONENT(lcolor) };
    bool play_successful = TryPlay2(b2, ataristone, &ids);
    if (play_successful) Play(b2, &ids);
		/* If we just played self-atari, abandon ship. */
		/* XXX: If we were very lucky, capturing this stone will
		 * not help us escape. That should be pretty rate. */
    /*
		if (DEBUGL(6))
			fprintf(stderr, "(%d=%d) ladder atari %s (%d libs)\n", i, res, coord2sstr(ataristone, b2), board_group_info(b2, group_at(b2, ataristone)).libs);
    */
		if (play_successful && group_at(b2, ataristone)->liberties > 1) {
      Coord last_lib = get_nlibs_of_group(b2, laddered, 1, NULL);
			is_ladder = middle_ladder_walk(b2, bset, laddered, last_lib, lcolor);
    }

    /* Why we need to do deallocation?
		if (i != libs - 1) {
			board_done_noalloc(b2);
		}
    */
	}
  /*
	if (DEBUGL(6))
		fprintf(stderr, "propagating %d\n", is_ladder);
  */
	return is_ladder;
}
Ejemplo n.º 29
0
const sMinMaxResult		MinMax<T>::eval(IBoard &board, const Rules &rules, const sMinMaxState &minMaxState, const IEval &evalFunction)
{

	if (minMaxState.depth == 0
		|| rules.gameEnded(board, minMaxState.lastStroke, minMaxState.captures[0], minMaxState.captures[1]) != common::eCell::E_CELL)
		return (((sMinMaxResult)
			{
				minMaxState.lastStroke
				, evalFunction.eval(board, rules, minMaxState)
			}));

	uint8_t					nCaptures(0);
	uint16_t				captures(0);
	sMinMaxResult			result;

	result.value = T::initialValue;

	uint8_t		alpha(minMaxState.alphaBeta[0]);
	uint8_t		beta(minMaxState.alphaBeta[1]);

	// Use iterator instead
	uint8_t		size = board.getSize();
	for (uint8_t i = 0; i < size; ++i)
	{
		for (uint8_t j = 0; j < size; ++j)
		{
			if (board.getHitBoard({i, j}) == false
				|| !rules.isValid(board, {i, j}, minMaxState.currentPlayer))
				continue ;

			board.setCell({i, j}, minMaxState.currentPlayer);
			nCaptures = rules.applyCapture(board, {i, j}, captures);

			const auto &next = T::search(
				board, rules
				, {
					(uint8_t)(minMaxState.depth - 1), !minMaxState.maximizing, OPPONENT(minMaxState.currentPlayer)
					, {i, j}
					, {
						(uint8_t)(minMaxState.currentPlayer == common::eCell::P1 ? minMaxState.captures[0] + nCaptures : minMaxState.captures[0])
						, (uint8_t)(minMaxState.currentPlayer == common::eCell::P1 ? minMaxState.captures[1] : minMaxState.captures[1] + nCaptures)
					}
					, {alpha, beta}
				}
				, evalFunction);

			rules.undoCapture(board, {i, j}, captures, OPPONENT(minMaxState.currentPlayer));
			board.setCell({i, j}, common::eCell::NONE);

			if (T::compareValues(next.value, result.value))
			{
				result.coord = {i, j};
				result.value = next.value;
			}

			if (T::alphaBetaComp(result.value, alpha, beta))
				return (result);
			T::setAlphaBeta(result.value, alpha, beta);
		}
	}
	return (result);
};
Ejemplo n.º 30
0
void init_move_directory()
{
    int i, j;
    t_chess_square f, t;
    t_chess_piece p;
    t_chess_color color, opponent;
    static char s[64];
    struct t_move_record *move;
    uchar not_mask;

    // initialize the global move lists
    for (f = A1; f <= H8; f++) {
        for (t = A1; t <= H8; t++) {
            for (p = BLANK; p <= BLACKKING; p++) {
                move_directory[f][t][p] = NULL;
            }
        }
    }

    configure_castling();
    i = 4;
    configure_pawn_push(&i);
    configure_pawn_capture(&i);
    configure_piece_moves(&i);

    init_directory_castling_delta();

    //-- Fill in the data
    for (i = 0, move = &xmove_list[0]; i < GLOBAL_MOVE_COUNT; i++, move++) {

        move->index = i;
        move->history = 0;
        move->refutation = NULL;
        move->from_to_bitboard = SQUARE64(move->from_square) | SQUARE64(move->to_square);
        move->capture_mask = 0;
        if (move->captured && (move->move_type != MOVE_PxP_EP))
            move->capture_mask = SQUARE64(move->to_square);

        color = COLOR(move->piece);
        opponent = OPPONENT(color);

        move->hash_delta = white_to_move_hash;
        move->pawn_hash_delta = white_to_move_hash;

        if (move->captured)
        {
            assert(move->piece >= 0 && move->piece < 15);
            move->mvvlva = see_piece_value[move->captured] * 100 + (see_piece_value[QUEEN] - see_piece_value[move->piece]);
        }
        else
            move->mvvlva = 0;

        assert(move->piece >= 0 && move->piece < 16);
        assert(move->from_square >= 0 && move->from_square < 64);
        assert(move->to_square >= 0 && move->to_square < 64);
        switch (move->move_type)
        {
        case MOVE_CASTLE:
            j = move->index;
            assert( move->index >= 0 &&  move->index < 4);
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            move->hash_delta ^= hash_value[castle[j].rook_piece][castle[j].rook_from] ^ hash_value[castle[j].rook_piece][castle[j].rook_to];
            move->pawn_hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            break;
        case MOVE_PAWN_PUSH1:
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            move->pawn_hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            break;
        case MOVE_PAWN_PUSH2:
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            move->pawn_hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            break;
        case MOVE_PxPAWN:
            assert(PIECEINDEX(opponent, PAWN) >= 0 && PIECEINDEX(opponent, PAWN) < 64);
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square] ^ hash_value[PIECEINDEX(opponent, PAWN)][move->to_square];
            move->pawn_hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square] ^ hash_value[PIECEINDEX(opponent, PAWN)][move->to_square];
            break;
        case MOVE_PxPIECE:
            assert(move->captured >= 0 && move->captured < 16);
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square] ^ hash_value[move->captured][move->to_square];
            move->pawn_hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            break;
        case MOVE_PxP_EP:
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square] ^ hash_value[PIECEINDEX(opponent, PAWN)][(move->to_square - 8) + 16 * color];
            move->pawn_hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square] ^ hash_value[PIECEINDEX(opponent, PAWN)][(move->to_square - 8) + 16 * color];
            break;
        case MOVE_PROMOTION:
            assert(move->promote_to >= 0 && move->promote_to < 16);
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->promote_to][move->to_square];
            move->pawn_hash_delta ^= hash_value[move->piece][move->from_square];
            break;
        case MOVE_CAPTUREPROMOTE:
            assert(move->captured >= 0 && move->captured < 16);
            assert(move->promote_to >= 0 && move->promote_to < 16);
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->promote_to][move->to_square] ^ hash_value[move->captured][move->to_square];
            move->pawn_hash_delta ^= hash_value[move->piece][move->from_square];
            break;
        case MOVE_PIECE_MOVE:
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            break;
        case MOVE_PIECExPIECE:
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square] ^ hash_value[move->captured][move->to_square];
            break;
        case MOVE_PIECExPAWN:
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square] ^ hash_value[move->captured][move->to_square];
            move->pawn_hash_delta ^= hash_value[move->captured][move->to_square];
            break;
        case MOVE_KING_MOVE:
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            move->pawn_hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            break;
        case MOVE_KINGxPIECE:
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square] ^ hash_value[move->captured][move->to_square];
            move->pawn_hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            break;
        case MOVE_KINGxPAWN:
            move->hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square] ^ hash_value[move->captured][move->to_square];
            move->pawn_hash_delta ^= hash_value[move->captured][move->to_square];
            move->pawn_hash_delta ^= hash_value[move->piece][move->from_square] ^ hash_value[move->piece][move->to_square];
            break;
        }
    }
}