Esempio n. 1
0
std::string to_usi_string(Move m)
{
  std::stringstream ss;
  if (!is_ok(m))
  {
    ss <<((m == MOVE_RESIGN) ? "resign" :
          (m == MOVE_WIN   ) ? "win"    :
          (m == MOVE_NULL  ) ? "null"   :
          (m == MOVE_NONE  ) ? "none"   :
          "");
  }
  else if (is_drop(m))
  {
    ss << Piece(move_from(m));
    ss << '*';
    ss << move_to(m);
  }
  else {
    ss << move_from(m);
    ss << move_to(m);
    if (is_promote(m))
      ss << '+';
  }
  return ss.str();
}
Esempio n. 2
0
std::string move_to_string(const Move m){
    Square to = move_to(m);
    int type = move_type(m);
    if(type >= MovePN && type <= MovePQ)
        return square_to_string(move_from(m)) + square_to_string(to) + piece_to_char(Piece(type+Black));
    return square_to_string(move_from(m)) + square_to_string(to);
}
Esempio n. 3
0
std::string pretty(Move m)
{
  if (is_drop(m))
    return (pretty(move_to(m)) + pretty2(Piece(move_from(m))) + (pretty_jp ? "打" : "*"));
  else
    return pretty(move_from(m)) + pretty(move_to(m)) + (is_promote(m) ? (pretty_jp ? "成" : "+") : "");
}
Esempio n. 4
0
void MovePicker::score_evasions() {
	// Try good captures ordered by MVV/LVA, then non-captures if
	// destination square is not under attack, ordered by history
	// value, and at the end bad-captures and non-captures with a
	// negative SEE. This last group is ordered by the SEE score.
	Move m;
	int seeScore;

	// Skip if we don't have at least two moves to order
	if (lastMove < moves + 2)
		return;

	for (MoveStack* cur = moves; cur != lastMove; cur++)
	{
		m = cur->move;
		if ((seeScore = pos.see_sign(m)) < 0)
			cur->score = seeScore - History::MaxValue; // Be sure we are at the bottom
		else if (pos.is_capture(m))
#if defined(NANOHA)
			cur->score =  piece_value_midgame(pos.piece_on(move_to(m)))
			            - type_of(move_piece(m)) + History::MaxValue;
#else
			cur->score =  piece_value_midgame(pos.piece_on(move_to(m)))
			            - type_of(pos.piece_on(move_from(m))) + History::MaxValue;
#endif
		else
#if defined(NANOHA)
		{
			Piece piece = is_promotion(m) ? Piece(move_piece(m) | PROMOTED) : move_piece(m);
			cur->score = H.value(piece, move_to(m));
		}
#else
		cur->score = H.value(pos.piece_on(move_from(m)), move_to(m));
#endif
	}
Esempio n. 5
0
File: san.cpp Progetto: ageneau/scid
static int ambiguity(int move, const board_t * board) {

   int from, to, piece;
   list_t list[1];
   int i, n, m;

   // init

   from = move_from(move);
   to = move_to(move);
   piece = move_piece(move,board);

   gen_legal_moves(list,board);

   // no ambiguity?

   n = 0;

   for (i = 0; i < list_size(list); i++) {
      m = list_move(list,i);
      if (move_piece(m,board) == piece && move_to(m) == to) {
         n++;
      }
   }

   if (n == 1) return AMBIGUITY_NONE;

   // file ambiguity?

   n = 0;

   for (i = 0; i < list_size(list); i++) {
      m = list_move(list,i);
      if (move_piece(m,board) == piece && move_to(m) == to) {
         if (square_file(move_from(m)) == square_file(from)) n++;
      }
   }

   if (n == 1) return AMBIGUITY_FILE;

   // rank ambiguity?

   n = 0;

   for (i = 0; i < list_size(list); i++) {
      m = list_move(list,i);
      if (move_piece(m,board) == piece && move_to(m) == to) {
         if (square_rank(move_from(m)) == square_rank(from)) n++;
      }
   }

   if (n == 1) return AMBIGUITY_RANK;

   // square ambiguity

   return AMBIGUITY_SQUARE;
}
Esempio n. 6
0
void MovePicker::score<CAPTURES>()
{
	// Position::see()を用いると遅い。単に取る駒の価値順に調べたほうがパフォーマンス的にもいい。
	// 歩が成る指し手もあるのでこれはある程度優先されないといけない。
	// CAPTURE系である以上、打つ指し手は除外されている。
	for (auto& m : *this)
	{
		// CAPTURES_PRO_PLUSで生成しているので歩の成る指し手が混じる。これは金と歩の価値の差の点数とする。

		// 移動させる駒の駒種。駒取りなので移動元は盤上であることは保証されている。
		auto pt = type_of(pos.piece_on(move_from(m)));
		// bool pawn_promo = is_promote(m) && pt == PAWN;

		// MVV-LVAに、歩の成りに加点する形にしておく。
		// → 歩の成りは加点しないほうがよさげ?
		m.value =// (pawn_promo ? (Value)(Eval::ProDiffPieceValue[PAWN]) : VALUE_ZERO) +
			(Value)Eval::CapturePieceValue[pos.piece_on(to_sq(m))]
			- LVA(pt);

		// 盤の上のほうの段にあるほど価値があるので下の方の段に対して小さなペナルティを課す。
		// (基本的には取る駒の価値が大きいほど優先であるから..)
		// m.value -= Value(1 * relative_rank(pos.side_to_move(), rank_of(move_to(m))));
		// → 将棋ではあまりよくないアイデア。
	}
}
void MovePicker::score_captures() {
  // Winning and equal captures in the main search are ordered by MVV/LVA.
  // Suprisingly, this appears to perform slightly better than SEE based
  // move ordering.  The reason is probably that in a position with a winning
  // capture, capturing a more valuable (but sufficiently defended) piece
  // first usually doesn't hurt.  The opponent will have to recapture, and
  // the hanging piece will still be hanging (except in the unusual cases
  // where it is possible to recapture with the hanging piece).  Exchanging
  // big pieces before capturing a hanging piece probably helps to reduce
  // the subtree size.
  for(int i = 0; i < numOfMoves; i++) {
    int seeValue = pos->see(moves[i].move);
    if(seeValue >= 0) {
      if(move_promotion(moves[i].move))
        moves[i].score = QueenValueMidgame;
      else 
        moves[i].score =
          int(pos->midgame_value_of_piece_on(move_to(moves[i].move))) -
          int(pos->type_of_piece_on(move_from(moves[i].move)));
    }
    else
      moves[i].score = seeValue;
        
  }
}
Esempio n. 8
0
void
calc_difference(const Position &pos, Move last_move, SearchStack *ss)
{
  const Square    from = move_from(last_move);
  const PieceType type = move_piece_type(last_move);

  if (type == kKing)
  {
    if (pos.side_to_move() == kBlack)
      calc_difference_king_move_no_capture<kWhite>(pos, ss);
    else
      calc_difference_king_move_no_capture<kBlack>(pos, ss);
  }
  else
  {
    if (from >= kBoardSquare)
    {
      calc_no_capture_difference(pos, ss);
    }
    else
    {
      const PieceType capture = move_capture(last_move);

      if (capture == kPieceNone)
        calc_no_capture_difference(pos, ss);
      else
        calc_difference_capture(pos, ss);
    }
  }
}
Esempio n. 9
0
void MovePicker::score_captures() {
	// Winning and equal captures in the main search are ordered by MVV/LVA.
	// Suprisingly, this appears to perform slightly better than SEE based
	// move ordering. The reason is probably that in a position with a winning
	// capture, capturing a more valuable (but sufficiently defended) piece
	// first usually doesn't hurt. The opponent will have to recapture, and
	// the hanging piece will still be hanging (except in the unusual cases
	// where it is possible to recapture with the hanging piece). Exchanging
	// big pieces before capturing a hanging piece probably helps to reduce
	// the subtree size.
	// In main search we want to push captures with negative SEE values to
	// badCaptures[] array, but instead of doing it now we delay till when
	// the move has been picked up in pick_move_from_list(), this way we save
	// some SEE calls in case we get a cutoff (idea from Pablo Vazquez).
	Move m;

	// Use MVV/LVA ordering
	for (MoveStack* cur = moves; cur != lastMove; cur++)
	{
		m = cur->move;
		cur->score =  piece_value_midgame(pos.piece_on(move_to(m)))
		            - type_of(pos.piece_on(move_from(m)));

		if (is_promotion(m))
#if defined(NANOHA)
			cur->score += piece_value_midgame(Piece(move_piece(m) | PROMOTED));
#else
			cur->score += piece_value_midgame(Piece(promotion_piece_type(m)));
#endif
	}
}
Esempio n. 10
0
void sorting_captures(Move *movelist, int n)
{
    int sorting_values[n];
    for(int i = 0; i < n; i += 1)
    {
        Move i_move = movelist[i];
        int figure = board[move_from(i_move)];
        int broken = move_broken(i_move);
        sorting_values[i] = mvv_lva[figure][broken];
    }
    for(int i = 1; i < n; i += 1)
    {
        int j = i;
        while(sorting_values[j] > sorting_values[j - 1] && j > 0)
        {
            int tmp = sorting_values[j];
            sorting_values[j] = sorting_values[j - 1];
            sorting_values[j - 1] = tmp;
            
            Move tmp2 = movelist[j];
            movelist[j] = movelist[j - 1];
            movelist[j - 1] = tmp2;
            j -= 1;
        }
    }
}
Esempio n. 11
0
int PVS(int alpha, int beta, int depth)
{
    if(is_draw_by_repetition_or_50_moves()) return DRAW;
    
    if(depth == 0) return quiescence(alpha, beta);
    
    Move movelist[256];
    int n = generate_moves(movelist);
    if(n == 0)
    {
        if(!in_check(turn_to_move))
            return DRAW;
        return LOSING + ply - begin_ply;
    }
    sorting_moves(movelist, n);
    
    int bool_search_pv = 1;
    Move bestmove = 0;

    for(int i = 0; i < n; i += 1)
    {
        Move i_move = movelist[i];
        make_move(i_move);
        int score;
        if(bool_search_pv)
        {
            score = -PVS(-beta, -alpha, depth - 1);
        }
        else
        {
            score = -ZWS(-alpha, depth - 1, 1);
            if(score > alpha)
                score = -PVS(-beta, -alpha, depth - 1);
        }
        unmake_move(i_move);
        
        if(score >= beta)
        {
            hash_save_entry(depth, beta, i_move, MORE_THAN_BETA);
            if(!move_broken(i_move))
            {
                history[board[move_from(i_move)]][move_to(i_move)] = depth * depth;
            }
            return beta;
        }
        if(score > alpha)
        {
            bestmove = i_move;
            alpha = score;
        }
        bool_search_pv = 0;
    }
    if(bestmove != 0)
        hash_save_entry(depth, alpha, bestmove, BETWEEN_ALPHA_AND_BETA);
    else
        hash_save_entry(depth, alpha, 0, LESS_THAN_ALPHA);
    return alpha;
}
Esempio n. 12
0
void MovePicker::score_noncaptures() {
  for(int i = 0; i < numOfMoves; i++) {
    Move m = moves[i].move;
    if(m == killer1)
      moves[i].score = HistoryMax + 2;
    else if(m == killer2)
      moves[i].score = HistoryMax + 1;
    else
      moves[i].score = H.move_ordering_score(pos->piece_on(move_from(m)), m);
  }
}
Esempio n. 13
0
void sorting_moves(Move *movelist, int n)
{
    int sorting_values[n];
    Entry *entry = hash_get_entry();
    Move hash_move = 0;
    if(entry != NULL)
        hash_move = entry->bestmove;
    for(int i = 0; i < n; i += 1)
    {
        Move i_move = movelist[i];
        if(i_move == hash_move)
        {
            sorting_values[i] = 10000000;
        }
        else if(move_broken(i_move))
        {
            int figure = board[move_from(i_move)];
            int broken = move_broken(i_move);
            sorting_values[i] = mvv_lva[figure][broken];
        }
        else
        {
            sorting_values[i] = history[board[move_from(i_move)]][move_to(i_move)];
        }
    }
    for(int i = 1; i < n; i += 1)
    {
        int j = i;
        while(sorting_values[j] > sorting_values[j - 1] && j > 0)
        {
            int tmp = sorting_values[j];
            sorting_values[j] = sorting_values[j - 1];
            sorting_values[j - 1] = tmp;
            
            Move tmp2 = movelist[j];
            movelist[j] = movelist[j - 1];
            movelist[j - 1] = tmp2;
            j -= 1;
        }
    }
}
Esempio n. 14
0
void MovePicker::score_evasions() {
  for(int i = 0; i < numOfMoves; i++) {
    Move m = moves[i].move;
    if(m == ttMove)
      moves[i].score = 2*HistoryMax;
    else if(!pos->square_is_empty(move_to(m))) {
      int seeScore = pos->see(m);
      moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
    }
    else
      moves[i].score = H.move_ordering_score(pos->piece_on(move_from(m)), m);
  }
}
Esempio n. 15
0
void unmake_move(Move move)
{
    turn_to_move = not_turn_to_move;
    ply -= 1;
    int direction_of_pawns = turn_to_move == WHITE? -10: 10;
    int from = move_from(move);
    int to = move_to(move);
    int figure = board[move_to(move)];
    int broken = move_broken(move);
    int turn = move_turn(move);

    if(turn)
        board[from] = create_figure(turn_to_move, PAWN);
    else
        board[from] = figure;
    
    if(get_value(figure) == PAWN && to == ply->en_passant)
    {
        board[to] = EMPTY;
        board[to - direction_of_pawns] = create_figure(not_turn_to_move, PAWN);
    }
    else
        board[to] = broken;
    
    if(get_value(figure) == KING)
    {
        int horizontal;
        if(turn_to_move == WHITE)
        {
            place_of_white_king = from;
            horizontal = 90;
        }
        else
        {
            place_of_black_king = from;
            horizontal = 20;
        }
        if(from - to == 2)
        {
            board[horizontal + 1] = board[horizontal + 4];
            board[horizontal + 4] = EMPTY;
        }
        else if(to - from == 2)
        {
            board[horizontal + 8] = board[horizontal + 6];
            board[horizontal + 6] = EMPTY;
        }
    }
}
Esempio n. 16
0
void MovePicker::score_noncaptures() {

	Move m;

	for (MoveStack* cur = moves; cur != lastMove; cur++)
	{
		m = cur->move;
#if defined(NANOHA)
		assert(m != MOVE_NULL);
		Piece piece = is_promotion(m) ? Piece(move_piece(m) | PROMOTED) : move_piece(m);
		cur->score = H.value(piece, move_to(m));
#else
		Square from = move_from(m);
		cur->score = H.value(pos.piece_on(from), move_to(m));
#endif
	}
}
Esempio n. 17
0
void move_to_str(Move move, char *string)
{
    int from = move_from(move);
    int to = move_to(move);
    int turn = move_turn(move);
    string[0] = (from % 10) - 1 + 'a';
    string[1] = 9 - (from / 10) + '1';
    string[2] = (to % 10) - 1 + 'a';
    string[3] = 9 - (to / 10) + '1';
    switch(get_value(turn))
    {
        case QUEEN : string[4] = 'q'; break;
        case ROOK  : string[4] = 'r'; break;
        case BISHOP: string[4] = 'b'; break;
        case KNIGHT: string[4] = 'n'; break;
        default:     string[4] = '\0';
    }
    string[5] = '\0';
}
Esempio n. 18
0
void fun(){
    int i;
    Matrix a,b;
    Vector v;
    
    assign(&a,&e);
    
    for(i=0;i<nodenum;i++){
        move_from(&b,vertex[i].x, vertex[i].y);
        multiply(&a,&b);
        rotate(&b,vertex[i].degree);
        multiply(&a,&b);
        move_back(&b,vertex[i].x, vertex[i].y);
        multiply(&a,&b);
        assign(&mat[i],&a);
    }
    for(i =0;i < 3;i++){
        printf("%.2lf %.2lf %.2lf\n", a[i][0], a[i][1], a[i][2]);
    }
    v[0] = a[2][1]*a[1][0]  + a[2][0]*(1-a[1][1]);
	v[0]/= ((1-a[1][1])*(1-a[0][0]) - a[0][1] * a[1][0]);
    
    v[1] = a[0][1] * v[0] + a[2][1]*a[1][0] ;
    v[1] /= (1 - a[1][1]);
    v[2] = 1;    
    
    vertex[0].x = v[0];
    vertex[0].y = v[1];
    
    for(i =0;i < nodenum-1;i++){
        V_mul_M(&v, &mat[i]);
        vertex[i+1].x = v[0];
        vertex[i+1].y = v[1];
		v[0] = vertex[0].x;
		v[1] = vertex[0].y;
		v[2] = 1;
    }    
    for(i=0;i<nodenum;i++){
        printf("%.2lf %.2lf\n", vertex[i].x, vertex[i].y);
    }
}
Esempio n. 19
0
void make_move(Move move)
{
    U64 hash = ply->hash;
    int direction_of_pawns = turn_to_move == WHITE? -10: 10;
    int from = move_from(move);
    int figure = board[from];
    int to = move_to(move);
    int turn = move_turn(move);
    int broken = move_broken(move);
    board[from] = EMPTY;
    hash ^= zobrist_piecesquare[figure][from];
    if(turn)
    {
        board[to] = turn;
        hash ^= zobrist_piecesquare[turn][to];
    }
    else
    {
        board[to] = figure;
        hash ^= zobrist_piecesquare[figure][to];
    }
    if(get_value(figure) == PAWN && to == ply->en_passant)
    {
        int tmp = to - direction_of_pawns;
        board[tmp] = EMPTY;
        hash ^= zobrist_piecesquare[create_figure(not_turn_to_move, PAWN)][tmp];
    }
    else if(broken)
    {
        hash ^= zobrist_piecesquare[broken][to];
    }
    if(ply->en_passant)
    {
        hash ^= zobrist_en_passant[ply->en_passant];
    }
    
    ply += 1;
    
    if(get_value(figure) == PAWN && to - from == direction_of_pawns * 2)
    {
        ply->en_passant = from + direction_of_pawns;
        hash ^= zobrist_en_passant[ply->en_passant];
    }
    else
    {
        ply->en_passant = 0;
    }
    
    ply->castlings = (ply - 1)->castlings;
    if(get_value(figure) == KING)
    {
        int horizontal;
        if(turn_to_move == WHITE)
        {
            place_of_white_king = to;
            make_white_castlings_is_incorrect();
            horizontal = 90;
        }
        else
        {
            place_of_black_king = to;
            make_black_castlings_is_incorrect();
            horizontal = 20;
        }
        if(from - to == 2)
        {
            board[horizontal + 4] = board[horizontal + 1];
            board[horizontal + 1] = EMPTY;
        }
        else if(to - from == 2)
        {
            board[horizontal + 6] = board[horizontal + 8];
            board[horizontal + 8] = EMPTY;
        }
    }
    if(board[98] != create_figure(WHITE, ROOK))
        make_K_castling_is_incorrect();
    if(board[91] != create_figure(WHITE, ROOK))
        make_Q_castling_is_incorrect();
    if(board[28] != create_figure(BLACK, ROOK))
        make_k_castling_is_incorrect();
    if(board[21] != create_figure(BLACK, ROOK))
        make_q_castling_is_incorrect();
    
    if(broken || get_value(figure) == PAWN)
        ply->number_of_insignificant_plies = 0;
    else
        ply->number_of_insignificant_plies = 
            (ply - 1)->number_of_insignificant_plies + 1;
    turn_to_move = not_turn_to_move;
    
    hash ^= zobrist_color;
    hash ^= zobrist_castlings[(ply - 1)->castlings];
    hash ^= zobrist_castlings[ply->castlings];
    ply->hash = hash;
}
Esempio n. 20
0
static int print_pv(app_t *app, int depth)
{
	int count = 0;
	piece_t p;
	u8 from;
	move_t mv;

	assert(app);
	assert(app->game.board);

#define VIA_PROBE
#ifdef VIA_PROBE
	/* get the current position */
	mv = probe_hash_move(&app->hash, app->game.board->key);
	
	while ((mv != 0) && (count < depth)) {
		
		if (find_move(app, mv)) {
			from = move_from(mv);
			p = app->game.board->pos.squares[from];

			if (do_move(app->game.board, &app->game.undo, mv)) {
				app->search.pv[count++] = mv;

				print_algebraic(p, mv);
				printf(" ");
			} else {
				break;
			}
		} else {
			break;
		}

		mv = probe_hash_move(&app->hash, app->game.board->key);
	}
#else
	while (app->search.pv[count]) {
		mv = app->search.pv[count++];
		
		if (find_move(app, mv)) {
			from = move_from(mv);
			p = app->board->pos.squares[from];

			if (do_move(app->board, &app->ul, mv)) {
				print_algebraic(p, mv);
				printf(" ");
			} else {
				break;
			}
		} else {
			break;
		}
	}
#endif
	
	while (app->game.board->ply) {
		undo_move(app->game.board, &app->game.undo);
	}
	
	return count;
}
Esempio n. 21
0
void Thread::move_good(const Move b_move, const Move h_move[256], const int h_size, const int ply, const int depth){
	Piece p;
	Square from, to;

	if(!is_tactical(b_move) && b_move != MoveNull){

		if(killer[ply][0] != b_move) {
		  killer[ply][1] = killer[ply][0];
		  killer[ply][0] = b_move;
		}

		p = pos.get_piece(move_from(b_move));
		to = move_to(b_move);
		from = move_from(b_move);

		#ifndef NDEBUG
		if(p>13 || to > 63 || from > 63){
			std::cerr<<"Wrong good move!"<<std::endl;
			pos.print();
			std::cerr<<"move:"<<move_to_string(b_move)<<std::endl;
			exit(1);
		}
		#endif

		history[p][from][to] += depth*depth;

		if (history[p][from][to] >= HistoryMax) {
			for (Piece p = WP; p <= BK; p++) {
				for(Square sq_f=A1; sq_f<=H8; sq_f++){
					for(Square sq_t=A1; sq_t<=H8; sq_t++){
						history[p][sq_f][sq_t] /= 2;
					}
				}
			}
		}

		his_tot[p][from][to]++;
		his_hit[p][from][to]++;

		if (his_tot[p][from][to] >= HistoryMax) {
			his_tot[p][from][to] = (his_tot[p][from][to] + 1) / 2;
			his_hit[p][from][to] = (his_hit[p][from][to] + 1) / 2;
		}
	}

	for(int i=0; i<h_size; i++){
		if(is_tactical(h_move[i])) continue;
		p = pos.get_piece(move_from(h_move[i]));
		to = move_to(h_move[i]);
		from = move_from(h_move[i]);

		#ifndef NDEBUG
		if(p>13 || to > 63 || from > 63){
			std::cerr<<"Wrong good move!"<<std::endl;
			pos.print();
			std::cerr<<"move:"<<move_to_string(h_move[i])<<std::endl;
			exit(1);
		}
		#endif

		his_tot[p][from][to]++;

		if (his_tot[p][from][to] >= HistoryMax) {
			his_tot[p][from][to] = (his_tot[p][from][to] + 1) / 2;
			his_hit[p][from][to] = (his_hit[p][from][to] + 1) / 2;
		}
	}
}
Esempio n. 22
0
int Thread::eval_history_move(const Move move) const {
	Piece p = pos.get_piece(move_from(move));
	Square to = move_to(move);
	Square from = move_from(move);
	return (his_hit[p][from][to] * 16384) / his_tot[p][from][to];
}
Move move_from_san(Position &pos, const std::string &movestr) {
  assert(pos.is_ok());

  MovePicker mp = MovePicker(pos, false, MOVE_NONE, MOVE_NONE, MOVE_NONE,
                             MOVE_NONE, OnePly);

  // Castling moves
  if(movestr == "O-O-O") {
    Move m;
    while((m = mp.get_next_move()) != MOVE_NONE)
      if(move_is_long_castle(m) && pos.move_is_legal(m))
        return m;
    return MOVE_NONE;
  }
  else if(movestr == "O-O") {
    Move m;
    while((m = mp.get_next_move()) != MOVE_NONE)
      if(move_is_short_castle(m) && pos.move_is_legal(m))
        return m;
    return MOVE_NONE;
  }

  // Normal moves
  const char *cstr = movestr.c_str();
  const char *c;
  char *cc;
  char str[10];
  int i;

  // Initialize str[] by making a copy of movestr with the characters
  // 'x', '=', '+' and '#' removed.
  cc = str;
  for(i=0, c=cstr; i<10 && *c!='\0' && *c!='\n' && *c!=' '; i++, c++)
    if(!strchr("x=+#", *c)) {
      *cc = strchr("nrq", *c)? toupper(*c) : *c;
      cc++;
    }
  *cc = '\0';

  int left = 0, right = strlen(str) - 1;
  PieceType pt = NO_PIECE_TYPE, promotion;
  Square to;
  File fromFile = FILE_NONE;
  Rank fromRank = RANK_NONE;

  // Promotion?
  if(strchr("BNRQ", str[right])) {
    promotion = piece_type_from_char(str[right]);
    right--;
  }
  else
    promotion = NO_PIECE_TYPE;

  // Find the moving piece:
  if(left < right) {
    if(strchr("BNRQK", str[left])) {
      pt = piece_type_from_char(str[left]);
      left++;
    }
    else
      pt = PAWN;
  }

  // Find the to square:
  if(left < right) {
    if(str[right] < '1' || str[right] > '8' ||
       str[right-1] < 'a' || str[right-1] > 'h')
      return MOVE_NONE;
    to = make_square(file_from_char(str[right-1]), rank_from_char(str[right]));
    right -= 2;
  }
  else
    return MOVE_NONE;

  // Find the file and/or rank of the from square:
  if(left <= right) {
    if(strchr("abcdefgh", str[left])) {
      fromFile = file_from_char(str[left]);
      left++;
    }
    if(strchr("12345678", str[left]))
      fromRank = rank_from_char(str[left]);
  }

  // Look for a matching move:
  Move m, move = MOVE_NONE;
  int matches = 0;

  while((m = mp.get_next_move()) != MOVE_NONE) {
    bool match = true;
    if(pos.type_of_piece_on(move_from(m)) != pt)
      match = false;
    else if(move_to(m) != to)
      match = false;
    else if(move_promotion(m) != promotion)
      match = false;
    else if(fromFile != FILE_NONE && fromFile != square_file(move_from(m)))
      match = false;
    else if(fromRank != RANK_NONE && fromRank != square_rank(move_from(m)))
      match = false;
    if(match) {
      move = m;
      matches++;
    }
  }

  if(matches == 1)
    return move;
  else
    return MOVE_NONE;
}
const std::string move_to_san(Position &pos, Move m) {
  std::string str;

  assert(pos.is_ok());
  assert(move_is_ok(m));

  Square from, to;
  Piece pc;

  from = move_from(m);
  to = move_to(m);
  pc = pos.piece_on(move_from(m));

  if(m == MOVE_NONE) {
    str = "(none)";
    return str;
  }
  else if(m == MOVE_NULL) {
    str = "(null)";
    return str;
  }
  else if(move_is_long_castle(m)
          || (int(to - from) == -2 && type_of_piece(pc) == KING))
    str = "O-O-O";
  else if(move_is_short_castle(m)
          || (int(to - from) == 2 && type_of_piece(pc) == KING))
    str = "O-O";
  else {
    str = "";

    if(type_of_piece(pc) == PAWN) {
      if(pos.move_is_capture(m))
        str += file_to_char(square_file(move_from(m)));
    }
    else {
      str += piece_type_to_char(type_of_piece(pc), true);

      Ambiguity amb = move_ambiguity(pos, m);
      switch(amb) {

      case AMBIGUITY_NONE:
        break;

      case AMBIGUITY_FILE:
        str += file_to_char(square_file(from));
        break;

      case AMBIGUITY_RANK:
        str += rank_to_char(square_rank(from));
        break;

      case AMBIGUITY_BOTH:
        str += square_to_string(from);
        break;

      default:
        assert(false);
      }
    }

    if(pos.move_is_capture(m))
      str += "x";

    str += square_to_string(move_to(m));

    if(move_promotion(m)) {
      str += "=";
      str += piece_type_to_char(move_promotion(m), true);
    }
  }

  // Is the move check?  We don't use pos.move_is_check(m) here, because
  // Position::move_is_check doesn't detect all checks (not castling moves,
  // promotions and en passant captures).
  UndoInfo u;
  pos.do_move(m, u);
  if(pos.is_check())
    str += pos.is_mate()? "#" : "+";
  pos.undo_move(m, u);

  return str;
}
Esempio n. 25
0
void move_do(board_t * board, int move) {

   int me, opp;
   int from, to;
   int piece, pos, capture;
   int old_flags, new_flags;
   int sq, ep_square;
   int pawn;

   ASSERT(board_is_ok(board));
   ASSERT(move_is_ok(move));

   ASSERT(move_is_pseudo(move,board));

   // init

   me = board->turn;
   opp = colour_opp(me);

   from = move_from(move);
   to = move_to(move);

   piece = board->square[from];
   ASSERT(colour_equal(piece,me));

   pos = board->pos[from];
   ASSERT(pos>=0);

   // update turn

   board->turn = opp;
   board->key ^= random_64(RandomTurn);

   // update castling rights

   old_flags = board_flags(board);

   if (piece_is_king(piece)) {
      board->castle[me][SideH] = SquareNone;
      board->castle[me][SideA] = SquareNone;
   }

   if (board->castle[me][SideH] == from) board->castle[me][SideH] = SquareNone;
   if (board->castle[me][SideA] == from) board->castle[me][SideA] = SquareNone;

   if (board->castle[opp][SideH] == to) board->castle[opp][SideH] = SquareNone;
   if (board->castle[opp][SideA] == to) board->castle[opp][SideA] = SquareNone;

   new_flags = board_flags(board);

   board->key ^= hash_castle_key(new_flags^old_flags); // HACK

   // update en-passant square

   ep_square = sq = board->ep_square;
   if (sq != SquareNone) {
      board->key ^= random_64(RandomEnPassant+square_file(sq));
      board->ep_square = SquareNone;
   }

   if (piece_is_pawn(piece) && abs(to-from) == 32) {
      pawn = piece_make_pawn(opp);
      if (board->square[to-1] == pawn || board->square[to+1] == pawn) {
         board->ep_square = sq = (from + to) / 2;
         board->key ^= random_64(RandomEnPassant+square_file(sq));
      }
   }

   // update ply number (captures are handled later)

   board->ply_nb++;
   if (piece_is_pawn(piece)) board->ply_nb = 0; // conversion

   // update move number

   if (me == Black) board->move_nb++;

   // castle

   if (colour_equal(board->square[to],me)) {

      int rank;
      int king_from, king_to;
      int rook_from, rook_to;
      int rook;

      rank = colour_is_white(me) ? Rank1 : Rank8;

      king_from = from;
      rook_from = to;

      if (to > from) { // h side
         king_to = square_make(FileG,rank);
         rook_to = square_make(FileF,rank);
      } else { // a side
         king_to = square_make(FileC,rank);
         rook_to = square_make(FileD,rank);
      }

      // remove the rook

      pos = board->pos[rook_from];
      ASSERT(pos>=0);

      rook = Rook64 | me; // HACK

      square_clear(board,rook_from,rook);

      // move the king

      square_move(board,king_from,king_to,piece);

      // put the rook back

      square_set(board,rook_to,rook,pos);

      ASSERT(board->key==hash_key(board));

      return;
   }

   // remove the captured piece

   if (piece_is_pawn(piece) && to == ep_square) {

      // en-passant capture

      sq = square_ep_dual(to);
      capture = board->square[sq];
      ASSERT(capture==piece_make_pawn(opp));

      square_clear(board,sq,capture);

      board->ply_nb = 0; // conversion

   } else {

      capture = board->square[to];

      if (capture != Empty) {

         // normal capture

         ASSERT(colour_equal(capture,opp));
         ASSERT(!piece_is_king(capture));

         square_clear(board,to,capture);

         board->ply_nb = 0; // conversion
      }
   }

   // move the piece

   if (move_is_promote(move)) {

      // promote

      square_clear(board,from,piece);
      piece = move_promote_hack(move) | me; // HACK
      square_set(board,to,piece,pos);

   } else {

      // normal move

      square_move(board,from,to,piece);
   }

   ASSERT(board->key==hash_key(board));
}
bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {

  assert(pos.is_ok());
  assert(move_is_ok(m));
  assert(pinned == pos.pinned_pieces(pos.side_to_move()));

  Color us = pos.side_to_move();
  Color them = opposite_color(us);
  Square from = move_from(m);
  Square to = move_to(m);
  Piece pc = pos.piece_on(from);

  // Use a slower but simpler function for uncommon cases
  if (move_is_ep(m) || move_is_castle(m))
      return move_is_legal(pos, m);

  // If the from square is not occupied by a piece belonging to the side to
  // move, the move is obviously not legal.
  if (color_of_piece(pc) != us)
      return false;

  // The destination square cannot be occupied by a friendly piece
  if (pos.color_of_piece_on(to) == us)
      return false;

  // Handle the special case of a pawn move
  if (type_of_piece(pc) == PAWN)
  {
      // Move direction must be compatible with pawn color
      int direction = to - from;
      if ((us == WHITE) != (direction > 0))
          return false;

      // A pawn move is a promotion iff the destination square is
      // on the 8/1th rank.
      if ((  (square_rank(to) == RANK_8 && us == WHITE)
           ||(square_rank(to) == RANK_1 && us != WHITE)) != bool(move_is_promotion(m)))
          return false;

      // Proceed according to the square delta between the origin and
      // destination squares.
      switch (direction)
      {
      case DELTA_NW:
      case DELTA_NE:
      case DELTA_SW:
      case DELTA_SE:
      // Capture. The destination square must be occupied by an enemy
      // piece (en passant captures was handled earlier).
          if (pos.color_of_piece_on(to) != them)
              return false;
          break;

      case DELTA_N:
      case DELTA_S:
      // Pawn push. The destination square must be empty.
          if (!pos.square_is_empty(to))
              return false;
          break;

      case DELTA_NN:
      // Double white pawn push. The destination square must be on the fourth
      // rank, and both the destination square and the square between the
      // source and destination squares must be empty.
      if (   square_rank(to) != RANK_4
          || !pos.square_is_empty(to)
          || !pos.square_is_empty(from + DELTA_N))
          return false;
          break;

      case DELTA_SS:
      // Double black pawn push. The destination square must be on the fifth
      // rank, and both the destination square and the square between the
      // source and destination squares must be empty.
          if (   square_rank(to) != RANK_5
              || !pos.square_is_empty(to)
              || !pos.square_is_empty(from + DELTA_S))
              return false;
          break;

      default:
          return false;
      }
      // The move is pseudo-legal, check if it is also legal
      return pos.is_check() ? pos.pl_move_is_evasion(m, pinned) : pos.pl_move_is_legal(m, pinned);
  }

  // Luckly we can handle all the other pieces in one go
  return    bit_is_set(pos.attacks_from(pc, from), to)
        && (pos.is_check() ? pos.pl_move_is_evasion(m, pinned) : pos.pl_move_is_legal(m, pinned))
        && !move_is_promotion(m);
}
Esempio n. 27
0
int alpha_beta(app_t *app, cnodeptr_t parent, int alpha, int beta, int depth)
{
	int palpha = alpha;
	int i, score = -MATE, highest = -MATE;
	node_t node;
	move_t cutoff = 0;
	piece_t p;

	init_node(&node);

	assert(app);

	app->search.nodes++;
	node.depth = depth;

	/* max depth */
	if (app->game.board->ply > (SEARCH_MAXDEPTH - 1)) {
		/* return evaluate(app->board); */
		return quiescent(app, parent, alpha, beta);
	}

	/* recursive base */
	if (depth == 0) {
		return evaluate(app->game.board);
	}

	/* draws */
	if (repetitions(app) || (app->game.board->half >= 100)) {
		return 0;
	}

	/* if we are checked, set the nodes checked flag */
	if (check(app->game.board, app->game.board->side)) {
		node.flags |= NODE_CHECK;
		/* extend our search by 1 depth if we are in check */
		/* NOTES: we may want to NOT extend our search here if the parent
		   is in check, because the means we already extended once */
		depth++;
	}

	/* TODO:
	     - NULL moves
	     - Late-move reduction
	     - Tactical extensions (pins & forks -> depth++)
	 */

	/* probe our table */
	if (probe_hash(&app->hash, app->game.board, &cutoff, &score, depth, alpha, beta) == TRUE) {
		app->hash.cut++;
		return score;
	}

	/* generate moves */
	generate_moves(app->game.board, &node.ml, &node.ml);

	/* reset score */
	score = -MATE;

	/* try to match our hash hit move */
	if (cutoff != 0) {
		for (i = 0; i < node.ml.count; i++) {
			if (node.ml.moves[i] == cutoff) {
				node.ml.scores[i] = 20000;
				break;
			}
		}
	}

	/* search negamax */
	for (i = 0; i < node.ml.count; i++) {
		/* get the next move ordered */
		next_move(i, &node.ml);

		if (!(do_move(app->game.board, &app->game.undo, node.ml.moves[i])))
			continue;

		score = -alpha_beta(app, &node, -beta, -alpha, depth - 1);

		node.made++;
		undo_move(app->game.board, &app->game.undo);

		/* score whatever is best so far */
		if (score > highest) {
			node.best = node.ml.moves[i];
			highest = score;

			/* update alpha */
			if (score > alpha) {
				if (score >= beta) {

					/* non-captures causing beta cutoffs (killers) */
					if (!is_capture(node.ml.moves[i])) {
						app->game.board->killers[1][app->game.board->ply] =
							app->game.board->killers[0][app->game.board->ply];
						app->game.board->killers[0][app->game.board->ply] = node.ml.moves[i];
					}

					/* store this beta in our transposition table */
					store_hash(&app->hash, app->game.board, node.best, beta, HASH_BETA, depth);

					return beta;
				}

				/* update alpha */
				alpha = score;

				/* update our history */
				if (!is_capture(node.best)) {
					p = app->game.board->pos.squares[move_from(node.best)];
					app->game.board->history[piece_color(p)][piece_type(p)][move_to(node.best)] += depth;
				}
			}
		}
	}

	/* check for checkmate or stalemate */
	if (!node.made) {
		if (node.flags & NODE_CHECK) {
			return -MATE + app->game.board->ply;
		} else {
			return 0;
		}
	}

	if (alpha != palpha) {
		/* store this as an exact, since we beat alpha */
		store_hash(&app->hash, app->game.board, node.best, highest, HASH_EXACT, depth);
	} else {
		/* store the current alpha */
		store_hash(&app->hash, app->game.board, node.best, alpha, HASH_ALPHA, depth);
	}

	return alpha;
}
Esempio n. 28
0
std::string pretty(Move m, Piece movedPieceType)
{
  if (is_drop(m))
    return (pretty(move_to(m)) + pretty2(movedPieceType) + (pretty_jp ? "打" : "*"));
  else
    return pretty(move_to(m)) + pretty2(movedPieceType) + (is_promote(m) ? (pretty_jp ? "成" : "+") : "") + "["+ pretty(move_from(m))+"]";
}
Esempio n. 29
0
File: san.cpp Progetto: ageneau/scid
bool move_to_san(int move, const board_t * board, char string[], int size) {

   int from, to, piece;
   char tmp_string[256];

   ASSERT(move_is_ok(move));
   ASSERT(board_is_ok(board));
   ASSERT(string!=NULL);
   ASSERT(size>=8);

   ASSERT(move_is_legal(move,board));

   if (size < 8) return false;

   // init

   from = move_from(move);
   to = move_to(move);

   string[0] = '\0';

   // castle

   if (move_is_castle(move,board)) {

      if (to > from) {
         strcat(string,"O-O");
      } else {
         strcat(string,"O-O-O");
      }

      goto check;
   }

   // from

   piece = board->square[from];

   if (piece_is_pawn(piece)) {

      // pawn

      if (move_is_capture(move,board)) {
         sprintf(tmp_string,"%c",file_to_char(square_file(from)));
         strcat(string,tmp_string);
      }

   } else {

      // piece

      sprintf(tmp_string,"%c",toupper(piece_to_char(piece)));
      strcat(string,tmp_string);

      // ambiguity

      switch (ambiguity(move,board)) {
      case AMBIGUITY_NONE:
         break;
      case AMBIGUITY_FILE:
         sprintf(tmp_string,"%c",file_to_char(square_file(from)));
         strcat(string,tmp_string);
         break;
      case AMBIGUITY_RANK:
         sprintf(tmp_string,"%c",rank_to_char(square_rank(from)));
         strcat(string,tmp_string);
         break;
      case AMBIGUITY_SQUARE:
         if (!square_to_string(from,tmp_string,256)) return false;
         strcat(string,tmp_string);
         break;
      default:
         ASSERT(false);
         break;
      }
   }

   // capture

   if (move_is_capture(move,board)) strcat(string,"x");

   // to

   if (!square_to_string(to,tmp_string,256)) return false;
   strcat(string,tmp_string);

   // promote

   if (move_is_promote(move)) {
      sprintf(tmp_string,"=%c",toupper(piece_to_char(move_promote(move,board))));
      strcat(string,tmp_string);
   }

   // check

check:

   if (move_is_mate(move,board)) {
      strcat(string,"#");
   } else if (move_is_check(move,board)) {
      strcat(string,"+");
   }

   return true;
}