Beispiel #1
0
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;
}
int board_mobility(const board_t * board) {

   list_t list[1];

   ASSERT(board_is_ok(board));

   gen_legal_moves(list,board);

   return list_size(list);
}
static bool move_is_legal_debug(int move, const board_t * board) {

   list_t list[1];

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

   gen_legal_moves(list,board);

   return list_contain(list,move);
}
Beispiel #4
0
/* TRUE if move from START_POS to END_POS by PLAYER is legal.  */
int is_legal_move (int player, int start_pos, int end_pos) 
{
    int legal_moves[BOARD_SIZE];
    init_moves_board (legal_moves);

    gen_legal_moves (player, start_pos, legal_moves);

    if (legal_moves[end_pos] == FALSE) {
        //printf ("Error: Illegal move %d - %d\n", start_pos, end_pos);
    }

    return legal_moves[end_pos];
}
Beispiel #5
0
int parse_move(Board *board, const char *notation, Move *move) {
    char temp[16];
    Move moves[MAX_MOVES];
    int count = gen_legal_moves(board, moves);
    for (int i = 0; i < count; i++) {
        notate_move(board, &moves[i], temp);
        if (strcmp(notation, temp) == 0) {
            memcpy(move, &moves[i], sizeof(Move));
            return 1;
        }
    }
    return 0;
}
Beispiel #6
0
int book_move(board_t * board) {

   int best_move;
   int best_score;
   int pos;
   entry_t entry[1];
   int move;
   int score;
   list_t list[1];
   int i;

   ASSERT(board!=NULL);

   if (BookFile != NULL && BookSize != 0) {

      // draw a move according to a fixed probability distribution

      best_move = MoveNone;
      best_score = 0;

      for (pos = find_pos(board->key); pos < BookSize; pos++) {

         read_entry(entry,pos);
         if (entry->key != board->key) break;

         move = entry->move;
         score = entry->count;

         // pick this move?

         ASSERT(score>0);

         best_score += score;
         if (my_random(best_score) < score) best_move = move;
      }

      if (best_move != MoveNone) {

         // convert PolyGlot move into Fruit move; TODO: handle promotes

         gen_legal_moves(list,board);

         for (i = 0; i < list->size; i++) {
            move = list->move[i];
            if ((move & 07777) == best_move) return move;
         }
      }
   }

   return MoveNone;
}
Beispiel #7
0
/* Search and evaluate AI's moves. MV->START_POS and MV->END_POS store AI's best
 * move.  */
void best_move (struct move *mv)
{
    int legal_moves[BOARD_SIZE];
    int curr_util = NEG_INF, i;

    /* Generate legal moves for each black piece.  */
    for (i = 0; i < BOARD_SIZE; i++) {
        if (board[i] < chp_null) {
            init_moves_board (legal_moves);
            gen_legal_moves (BPLAYER, i, legal_moves);

            /* For each legal move, evaluate subsequent moves. If this move
             * leads to current best score, save it.  */
            int j;
            for (j = 0; j < BOARD_SIZE; j++) {
                if (legal_moves[j] == TRUE) {
                    /* Make move and evaluate subsequent moves.  */
                    int attacked_piece = move_piece (i, j);

                    /* If the move wins the game, automatically make it.  */
                    if (game_over () == TRUE) {
                        mv->start_pos = i;
                        mv->end_pos   = j;
                        unmove_piece (i, j, attacked_piece);
                        return;
                    }

                    /* Evaluate subsequent moves and choose the best one.  */
                    int move_util = -1 * abp_search (WPLAYER, SEARCH_DEP - 1, 
                        NEG_INF, POS_INF);
                    unmove_piece (i, j, attacked_piece);

                    /* If move is best yet, save it.  */
                    if (move_util > curr_util) {
                        mv->start_pos = i;
                        mv->end_pos   = j;
                        curr_util     = move_util;
                    }
                }
            }
        }
    }
}
Beispiel #8
0
int move_from_san_debug(const char string[], const board_t * board) {

   list_t list[1];
   int i, move;
   char move_string[256];

   ASSERT(string!=NULL);
   ASSERT(board_is_ok(board));

   gen_legal_moves(list,board);

   for (i = 0; i < list_size(list); i++) {
      move = list_move(list,i);
      if (!move_to_san(move,board,move_string,256)) ASSERT(false);
      if (my_string_equal(move_string,string)) return move;
   }

   return MoveNone;
}
Beispiel #9
0
/* Return TRUE if PLAYER has a legal move. This is strictly for detecting
 * checkmate, not for generating all legal moves a player has.  */
int player_has_moves (int player)
{
    int i, mod = (player == BPLAYER) ? -1 : 1;

    /* If a board square contains a player's piece, generate all legal moves for
     * that piece, then check if there are any legal moves. If there are, simply
     * return TRUE. Else continue for all pieces.  */
    for (i = 0; i < BOARD_SIZE; i++) {
        if (board[i] * mod > chp_null) {
            int moves_array[BOARD_SIZE];
            init_moves_board (moves_array);
            gen_legal_moves (player, i, moves_array);

            int j;
            for (j = 0; j < BOARD_SIZE; j++) {
                if (moves_array[j] == TRUE) {
                    return TRUE;
                }
            }
        }
    }
    
    return FALSE;
}
Beispiel #10
0
/* Return position score for knight at START_POS owned by PLAYER.  */
int knight_pos_score (int player, int start_pos)
{
    int score = 0, legal_moves[BOARD_SIZE];
    int mod   = (player == BPLAYER) ? -1 : 1;
    init_moves_board (legal_moves);
    gen_legal_moves (player, start_pos, legal_moves);

    int i;
    for (i = 0; i < BOARD_SIZE; i++) {
        /* Each legal move increases score.  */
        if (legal_moves[i] == TRUE) {
            score++;
            
            /* Each enemy piece attacked increases score.  */
            if (board[i] * mod < chp_null) {
                printf (":: EVAL: %c attacking piece\n", (player == WPLAYER) ?
                    'W' : 'B');
                score -= board[i] * mod;
            }
        }
    }

    return score;
}
Beispiel #11
0
void search() {

   int move;
   int depth;
   int i;
   bool search_ready;

     
   for (i = 0; i < MultiPVMax; i++){
	  save_multipv[SearchCurrent->multipv].mate = 0;
	  save_multipv[SearchCurrent->multipv].depth = 0;
	  save_multipv[SearchCurrent->multipv].max_depth = 0;
	  save_multipv[SearchCurrent->multipv].value = 0;
	  save_multipv[SearchCurrent->multipv].time = 0;
	  save_multipv[SearchCurrent->multipv].node_nb = 0;
	  strcpy(save_multipv[SearchCurrent->multipv].pv_string,""); 
   }
  
   SearchInput->multipv = option_get_int("MultiPV")-1;
   SearchCurrent->multipv = 0;
   
   
   ASSERT(board_is_ok(SearchInput->board));

   // opening book

   if (option_get_bool("OwnBook") && !SearchInput->infinite) {

      move = book_move(SearchInput->board);

      if (move != MoveNone) {

         // play book move

         SearchBest[SearchCurrent->multipv].move = move;
         SearchBest[SearchCurrent->multipv].value = 1;
         SearchBest[SearchCurrent->multipv].flags = SearchExact;
         SearchBest[SearchCurrent->multipv].depth = 1;
         SearchBest[SearchCurrent->multipv].pv[0] = move;
         SearchBest[SearchCurrent->multipv].pv[1] = MoveNone;

         search_update_best();

         return;
      }
   }

   // SearchInput

   gen_legal_moves(SearchInput->list,SearchInput->board);

   if (LIST_SIZE(SearchInput->list) < SearchInput->multipv+1){ 
	  SearchInput->multipv = LIST_SIZE(SearchInput->list)-1;
   }

   if (LIST_SIZE(SearchInput->list) <= 1) {
      SearchInput->depth_is_limited = true;
      SearchInput->depth_limit = 4; // was 1
   }

   // SearchInfo

   if (setjmp(SearchInfo->buf) != 0) {
      ASSERT(SearchInfo->can_stop);
      ASSERT(SearchBest->move!=MoveNone);
      search_update_current();
      return;
   }

   // SearchRoot

   list_copy(SearchRoot->list,SearchInput->list);

   // SearchCurrent

   board_copy(SearchCurrent->board,SearchInput->board);
   my_timer_reset(SearchCurrent->timer);
   my_timer_start(SearchCurrent->timer);

   // init

   trans_inc_date(Trans);

   sort_init();
   search_full_init(SearchRoot->list,SearchCurrent->board);

   // analyze game for evaluation
   
   if (SearchCurrent->board->piece_size[White] < 3 && SearchCurrent->board->piece_size[Black] < 3){
	   trans_endgame = true;
   }
   else{
	   trans_endgame = false;
   }

   
   // iterative deepening

   search_ready = false;

   for (depth = 1; depth < DepthMax; depth++) {
	   for (SearchCurrent->multipv = 0; SearchCurrent->multipv <= SearchInput->multipv; SearchCurrent->multipv++){

		  if (DispDepthStart && SearchCurrent->multipv == 0) send("info depth %d",depth);

		  SearchCurrent->max_extensions = depth * 10;
		  SearchRoot->bad_1 = false;
		  SearchRoot->change = false;

		  board_copy(SearchCurrent->board,SearchInput->board);

		  if (UseShortSearch && depth <= ShortSearchDepth) {
			 search_full_root(SearchRoot->list,SearchCurrent->board,depth,SearchShort);
		  } else {
			 search_full_root(SearchRoot->list,SearchCurrent->board,depth,SearchNormal);
		  }

		  search_update_current();

		  if (DispDepthEnd && SearchCurrent->multipv == SearchInput->multipv) {
			 send("info depth %d seldepth %d time %.0f nodes " S64_FORMAT " nps %.0f",depth,SearchCurrent->max_depth,SearchCurrent->time*1000.0,SearchCurrent->node_nb,SearchCurrent->speed);
		  }

		  // update search info

		  if (depth >= 1) SearchInfo->can_stop = true;

		  if (depth == 1
		   && LIST_SIZE(SearchRoot->list) >= 2
		   && LIST_VALUE(SearchRoot->list,0) >= LIST_VALUE(SearchRoot->list,1) + EasyThreshold) {
			 SearchRoot->easy = true;
		  }

		  if (depth > 1) {
			 SearchRoot->bad_2 = SearchRoot->bad_1;
			 SearchRoot->bad_1 = false;
			 ASSERT(SearchRoot->bad_2==(SearchBest->value<=SearchRoot->last_value-BadThreshold));
		  }

		  SearchRoot->last_value = SearchBest[SearchCurrent->multipv].value;

		  // stop search?

		  if (SearchInput->depth_is_limited && SearchCurrent->multipv >= SearchInput->multipv
		   && depth >= SearchInput->depth_limit) {
			 SearchRoot->flag = true;
		  }

		  if (SearchInput->time_is_limited
		   && SearchCurrent->time * 2 >= SearchInput->time_limit_1
		   && !SearchRoot->bad_2) {
			 SearchRoot->flag = true;
		  }

		  if (SearchInput->time_is_limited
		   && SearchCurrent->time >= SearchInput->time_limit_1 * EasyRatio
		   && SearchRoot->easy) {
			 ASSERT(!SearchRoot->bad_2);
			 ASSERT(!SearchRoot->change);
			 SearchRoot->flag = true;
		  }

		  if (SearchInput->time_is_limited
		   && SearchCurrent->time >= SearchInput->time_limit_1 * EarlyRatio
		   && !SearchRoot->bad_2
		   && !SearchRoot->change) {
			 SearchRoot->flag = true;
		  }

		  if (SearchInfo->can_stop 
		   && (SearchInfo->stop || (SearchRoot->flag && !SearchInput->infinite))) {
			  search_ready = true;
			  break;
		  }
	   }
	   if (search_ready)
		   break;
   }
}
Beispiel #12
0
bool TEngine::SearchPos(board_t * Board, TFindPos * fp, mv_t pv[], bool full)
{
   //------------------------
   if (Eval(Board,fp)) {
     pv[0] = 0;
     return true;
   }
   //-----------------------
   if (LastMove) {
      undo_t undo;
      move_do(Board,LastMove,&undo);
      bool eval = Eval(Board,fp);
      if (Eval(Board,fp)) {
         move_undo(Board,LastMove, &undo);
         pv[0] = LastMove;
         pv[1] = 0;
         return true;
      }
      list_t list;
      gen_legal_moves(&list,Board);
      for (int i=0; i<LIST_SIZE(&list); i++) {
         undo_t undo2;
         mv_t move2 = LIST_MOVE(&list,i);
         move_do(Board,move2,&undo2);
         bool eval = Eval(Board,fp);
         move_undo(Board,move2, &undo2);
         if (eval) {
             move_undo(Board,LastMove, &undo);
             pv[0] = LastMove;
             pv[1] = move2;
             pv[2] = 0;
             return true;;
         }
      }
      move_undo(Board,LastMove,&undo);
   }
   //----------------------------------------------------
   list_t list;
   gen_legal_moves(&list,Board);
   //----------------------------------------------------
   for (int i=0; i<LIST_SIZE(&list); i++) {
      undo_t undo;
      mv_t move = LIST_MOVE(&list,i);
      move_do(Board,move,&undo);
      bool eval = Eval(Board,fp);
      move_undo(Board,move,&undo);
      if (eval) {
         pv[0] = move;
         pv[1] = 0;
         return true;
      }
   }
   //------------------------------------------------------
   if (full) {
     for (int i=0; i<LIST_SIZE(&list); i++) {
        undo_t undo;
        mv_t move = LIST_MOVE(&list,i);
        move_do(Board,move,&undo);
        list_t list2;
        gen_legal_moves(&list2,Board);
        for (int j=0; j<LIST_SIZE(&list2); j++) {
           undo_t undo2;
           mv_t move2 = LIST_MOVE(&list2,j);
           move_do(Board,move2,&undo2);
           /*
           char s_move[6], s_move2[6];
           move_to_string(move,s_move,6);
           move_to_string(move2,s_move2,6);
           */
           bool eval = Eval(Board,fp);
           move_undo(Board,move2,&undo2);
           if (eval) {
              pv[0] = move;
              pv[1] = move2;
              pv[2] = 0;
              move_undo(Board,move,&undo);
              return true;
          }
        }
        move_undo(Board,move,&undo);
     }
   }
   //-------------------------------------------------------
   return false;
}
Beispiel #13
0
void notate_move(Board *board, Move *move, char *result) {
    Move moves[MAX_MOVES];
    int count = gen_legal_moves(board, moves);
    int piece = board->squares[move->src];
    int capture = board->squares[move->dst];
    char rank1 = '1' + move->src / 8;
    char file1 = 'a' + move->src % 8;
    char rank2 = '1' + move->dst / 8;
    char file2 = 'a' + move->dst % 8;
    int show_rank1 = 0;
    int show_file1 = 0;
    if (PIECE(piece) == PAWN) {
        if (file1 != file2) {
            capture = 1;
        }
        if (capture) {
            show_file1 = 1;
        }
    }
    // ambiguity
    int ambiguous = 0;
    int unique_rank = 1;
    int unique_file = 1;
    for (int i = 0; i < count; i++) {
        Move *other = moves + i;
        if (move->dst != other->dst) {
            continue; // different target
        }
        if (move->src == other->src) {
            continue; // same move
        }
        if (piece != board->squares[other->src]) {
            continue; // different piece
        }
        ambiguous = 1;
        if (move->src % 8 == other->src % 8) {
            unique_file = 0;
        }
        if (move->src / 8 == other->src / 8) {
            unique_rank = 0;
        }
    }
    if (ambiguous) {
        if (unique_rank && unique_file) {
            show_file1 = 1;
        }
        else if (unique_rank) {
            show_rank1 = 1;
        }
        else if (unique_file) {
            show_file1 = 1;
        }
        else {
            show_rank1 = 1;
            show_file1 = 1;
        }
    }
    // castle
    int castle = 0;
    if (PIECE(piece) == KING) {
        castle = 1;
        if (move->src == 4 && move->dst == 6) {
            strcpy(result, "O-O");
            result += 3;
        }
        else if (move->src == 4 && move->dst == 2) {
            strcpy(result, "O-O-O");
            result += 5;
        }
        else if (move->src == 60 && move->dst == 62) {
            strcpy(result, "O-O");
            result += 3;
        }
        else if (move->src == 60 && move->dst == 58) {
            strcpy(result, "O-O-O");
            result += 5;
        }
        else {
            castle = 0;
        }
    }
    if (!castle) {
        // piece
        switch (PIECE(piece)) {
            case KNIGHT: *result++ = 'N'; break;
            case BISHOP: *result++ = 'B'; break;
            case ROOK:   *result++ = 'R'; break;
            case QUEEN:  *result++ = 'Q'; break;
            case KING:   *result++ = 'K'; break;
        }
        // source
        if (show_file1) {
            *result++ = file1;
        }
        if (show_rank1) {
            *result++ = rank1;
        }
        // capture
        if (capture) {
            *result++ = 'x';
        }
        // target
        *result++ = file2;
        *result++ = rank2;
        // promotion
        if (move->promotion) {
            *result++ = '=';
            switch (move->promotion) {
                case KNIGHT: *result++ = 'N'; break;
                case BISHOP: *result++ = 'B'; break;
                case ROOK:   *result++ = 'R'; break;
                case QUEEN:  *result++ = 'Q'; break;
            }
        }
    }
    // check
    Undo undo;
    do_move(board, move, &undo);
    if (is_check(board)) {
        if (has_legal_moves(board)) {
            *result++ = '+';
        }
        else {
            *result++ = '#';
        }
    }
    undo_move(board, move, &undo);
    // null terminator
    *result++ = 0;
}