Example #1
0
int board_solve(board_t *board)
{
    if(board->count == 0) {
        return 0;
    } else {
        uint8_t u, l, offset = 0, lx = 0, ly = 0, u_max = 0, o_min = 9;
        board_t current;

        // Identify the maximum number of indentified squares per
        // unit (except those completely identified).
        for (u = 0; u < 9; u++) {
            if(board->unit_count[u] > u_max && board->unit_count[u] < 9) {
                u_max = board->unit_count[u];
            }
        }

        // Find the square with the minimum number of possible options
        // within a unit with the maximum number of identified
        // squares.
        for (u = 0; u < 9; u++) {
            if(board->unit_count[u] != u_max) {
                continue;
            }

            uint8_t x, y, ui = (u % 3) * 3, uj = (u / 3) * 3;
            for (y = uj; y < (uj + 3); y++) {
                for (x = ui; x < (ui + 3); x++) {
                    uint8_t o = board_offset(x, y);
                    if(board->values[o] == 0 &&
                       board->options_count[o] < o_min ) {
                        o_min = board->options_count[o];
                        lx = x;
                        ly = y;
                        offset = o;
                    }
                }
            }
        }

        // Use this square to explore recursively
        for (l = 1; l < 10; l++) {
            uint16_t m = value_to_option(l);
            // We iterate on the valid options for the square
            if(!(m & board->options[offset])) {
                continue;
            }

            board_copy(&current, board); // Work on a copy of the board
            if(board_set(&current, lx, ly, l) == 0 &&
               board_check_single(&current) == 0 &&
               board_solve(&current) == 0) {
                // The value we tried was a success copy back the result
                board_copy(board, &current);
                return 0;
            }
        }
    }
    return 1;
}
Example #2
0
/*----------------------------------------------------------------------------*/
int  
aigo_findmoves (long pstr, long posi, long *p_moves)
{  
  GO_GAMER *gamer = (GO_GAMER*) pstr;
  GO_POSI    *pos = (GO_POSI *) posi;
  GO_BOARD     *a = pos->a;

  int num = 0; 

  if (0) { // кажется не очень продуктивным :-( лучше делать оченку точнее
    GO_WORK  *aigo_work = gamer->work;
    work_get_groups (aigo_work, a);  

    int       num_add;
    GO_BOARD *tmp = board_copy (a);

    num = find_moves_defs (aigo_work, pos->stone, tmp, p_moves, num);
    num = find_moves_caps (aigo_work, pos->stone, tmp, p_moves, num);
    num = find_moves_cont (aigo_work,  tmp, p_moves, num);

    num_add = 15 - num;
    if (num_add < 0) num_add = 0;
    num = find_moves_random (tmp, num_add, p_moves, num);
    //num = find_moves_all (tmp, p_moves, num); // добрать остальные свободные ходы

  } else { //--------------------------------

    num = find_moves_all (a, p_moves, num); 
  }

  return (num);
}
Example #3
0
File: Chess.c Project: ishefi/chess
//copy a single move
void copy_move(move * original_move, move* new_copy){
	new_copy->start = original_move->start;
	new_copy->end = original_move->end;
	new_copy->promotion = original_move->promotion;
	new_copy->is_castle = original_move->is_castle;
	board_copy(original_move->board, new_copy->board);
}
Example #4
0
File: Chess.c Project: ishefi/chess
/*
*	return moves. in each move:
*			start = start_cord
*			end = one of the cords in end_cords (there can be at most 31 end cords)
*			board = currend board + piece moved from start to end.
*	this method is not relevant for pawns.
*/
moves cords_to_moves(cord start_cord, cord end_cords[32], char board[BOARD_SIZE][BOARD_SIZE], int color) {
	cord end_cord;
	int i = 0;
	move * new_move;
	moves new_moves = { 0 };
	while (is_valid_cord(end_cord = end_cords[i++])) {
		new_move = malloc(sizeof(move));
		if (new_move == NULL)
		{
			free_list(&new_moves, &free);
			return error_moves;
		}

		new_move->start = start_cord;
		new_move->end = end_cord;
		new_move->promotion = FALSE;
		new_move->is_castle = FALSE;
		board_copy(board, new_move->board);
		move_from_to(new_move->board, start_cord, end_cord);
		// check if psaudo-legal move is legal
		if (is_king_checked(color, new_move->board)){
			//	free(new_move);
			continue;
		}
		else if (!add_node(&new_moves, new_move, sizeof(move))){
			free(new_move);
			free_list(&new_moves, &free);
			return error_moves;
		}
		free(new_move);
	}
	return new_moves;
}
Example #5
0
static coord_t *
random_genmove(struct engine *e, struct board *b, struct time_info *ti, enum stone color, bool pass_all_alive)
{
	/* Play a random coordinate. However, we must also guard
	 * against suicide moves; repeat playing while it's a suicide
	 * unless we keep suiciding; in that case, we probably don't
	 * have any other moves available and we pass. */
	coord_t coord;
	int i = 0; bool suicide = false;

	do {
		/* board_play_random() actually plays the move too;
		 * this is desirable for MC simulations but not within
		 * the genmove. Make a scratch new board for it. */
		struct board b2;
		board_copy(&b2, b);

		board_play_random(&b2, color, &coord, NULL, NULL);

		suicide = (coord != pass && !group_at(&b2, coord));
		board_done_noalloc(&b2);
	} while (suicide && i++ < 100);

	return coord_copy(suicide ? pass : coord);
}
Example #6
0
File: Chess.c Project: ishefi/chess
moves pawn_moves(settings * set, cord curr, int color) {
	moves piece_simple_moves;
	piece_simple_moves.len = 0;
	cord dest;
	move * single_move;
	moves promotions;
	int dest_color;
	int y_dir = (color == WHITE) ? 1 : -1;

	dest.y = curr.y + y_dir;

	for (int x = -1; x <= 1; x++) {
		single_move = malloc(sizeof(move));
		if (single_move == NULL) {
			free_list(&piece_simple_moves, &free);
			return error_moves;
		}
		single_move->start = curr;
		single_move->promotion = FALSE;
		single_move->is_castle = FALSE;
		dest.x = curr.x + x;
		if (is_valid_cord(dest)) {
			dest_color = which_color(board_piece(set->board, dest));
			//logical XOR: check if pawn can eat XOR move up
			if (color == dest_color) {
				free(single_move);
				continue;
			}
			if ((x == 0) != (dest_color == other_player(color))) {
				single_move->end = dest;
				board_copy(set->board, single_move->board);
				move_from_to(single_move->board, curr, dest);
				// check if psaudo-legal move is legal
				if (is_king_checked(color, single_move->board)) {
					free(single_move);
					continue;
				}
				if (dest.y == promotion_row(color)) {
					promotions = promote(single_move);
					if (promotions.len == -1){
						free(single_move);
						free_list(&piece_simple_moves, &free);
						return promotions;
					}
					concat(&piece_simple_moves, promotions);
				}
				else if (!add_node(&piece_simple_moves, single_move, sizeof(move))) { //could not add node to linked list
					free(single_move);
					free_list(&piece_simple_moves, &free);
					return error_moves;
				}
				free(single_move);
			}
		}
	}
	return piece_simple_moves;
}
Example #7
0
  solver_c::rate_t solver_c::rate(const board_c& board) const noexcept
  {
    if(board.status.is_draw())
      return 0;
    switch(speed)
    {
      case SPEED_FAST:
        switch(board.next_player.player)
        {
          case player_c::PLAYER_X:
            if(board.status.is_win_o())
              return board.size*board.size;
            break;
          case player_c::PLAYER_O:
            if(board.status.is_win_x())
              return board.size*board.size;
            break;
        }
        break;
      case SPEED_SLOW:
        switch(board.next_player.player)
        {
          case player_c::PLAYER_X:
            if(board.status.is_win_o())
              return 1;
            break;
          case player_c::PLAYER_O:
            if(board.status.is_win_x())
              return 1;
            break;
        }
        break;
    }

    board_c board_copy(board);
    move_c* move = best_move(board_copy);
    board_copy.play(*move);
    delete move;
    rate_t new_rate = rate(board_copy);
    switch(speed)
    {
      case SPEED_FAST:
        if(new_rate > 0)
          new_rate--;
        else if(new_rate < 0)
          new_rate++;
        break;
      case SPEED_SLOW:
        if(new_rate > 0)
          new_rate++;
        else if(new_rate < 0)
          new_rate--;
        break;
    }
    return -new_rate;
  }
Example #8
0
int AI::get_move(const Board *board_state) {
	std::vector<int> moves;
    int size = board_state->get_valid_moves(&moves);
	unsigned seed = ((unsigned)std::chrono::system_clock::now().time_since_epoch().count());
    std::default_random_engine generator (seed);
	
	switch (Difficulty) {
	case AI::Easy:
		{
			std::uniform_int_distribution<int> distribution(0,size);
			return moves[distribution(generator)]; // random move
		}
		break;		
	case AI::Hard:
        	{
			// Takes a winning move, or a move that doesn't result in a loss before the next turn
			
			// ==================================================================//			
			// TODO - Implement Hard AI
			// ==================================================================//
                
            std::uniform_int_distribution<int> distribution(0,size);
                for (int i = 0; i < size; i++) {
                    int move = moves[i];
                    if (check_next_move(*board_state, move, this->identity) == 1) {
                        return move;
                    }
                }
                for (int i = 0; i < size; i++) {
                    int move = moves[i];
                    if (check_next_move(*board_state, move, this->identity) == 0) {
                        return move;
                    }
                }
                return moves[0];
		}
		break;
	case AI::Impossible:
		{
			int best_rank = -1;
			int move_idx = 0;
			for (int idx = 0; idx < size; ++idx) {
		        Board board_copy(*board_state);
				int cur_rank = rank_move(board_copy, moves[idx], this->identity);
				if (cur_rank > best_rank) {
					move_idx = idx;
					best_rank = cur_rank;
				}
			}
			return moves[move_idx]; // Perfect Play
		}
		break;
	default:
		break;
	}
}
Example #9
0
void game_get_board(const game_t * game, board_t * board, int pos) {

   int start;
   int i;

   ASSERT(game!=NULL);
   ASSERT(board!=NULL);
   ASSERT(pos==-1||(pos>=0&&pos<=game->size)); // HACK

   if (pos < 0) pos = game->pos;

   if (pos >= game->pos) { // forward from current position
      start = game->pos;
      board_copy(board,game->board);
   } else { // backward => replay the whole game
      start = 0;
      board_copy(board,game->start_board);
   }

   for (i = start; i < pos; i++) move_do(board,game->move[i]);
}
Example #10
0
  move_c* solver_c::modest_reverse_move(const board_c& board) const
  {
    if(!board.status.is_playable())
      throw error_not_playable();

    move_c moves[board.size*board.size];
    int moves_number = 0;
    for(move_c& move : board.all_moves_on_empty)
    {
      board_c board_copy(board);
      board_copy.play(move);
      switch(board.next_player.player)
      {
        case player_c::PLAYER_X:
          if(!board_copy.status.is_win_x())
          {
            moves[moves_number].set(move);
            moves_number++;
          }
          break;
        case player_c::PLAYER_O:
          if(!board_copy.status.is_win_o())
          {
            moves[moves_number].set(move);
            moves_number++;
          }
          break;
      }
    }

    if(moves_number > 0)
    {
      move_c* move;
      switch(select)
      {
        case SELECT_RANDOM:
          move = new move_c(moves[util_c::random_int(0, moves_number-1)]);
          break;
        case SELECT_FIRST:
          move = new move_c(moves[0]);
          break;
        case SELECT_LAST:
          move = new move_c(moves[moves_number-1]);
          break;
      }
      return move;
    }

    return worst_move(board);
  }
bool pseudo_is_legal(int move, const board_t * board) {

   board_t new_board[1];

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

   ASSERT(move_is_pseudo(move,board));

   board_copy(new_board,board);
   move_do(new_board,move);

   return !is_in_check(new_board,colour_opp(new_board->turn));
}
Example #12
0
File: Chess.c Project: ishefi/chess
/* find and return the best computer's next move acording to minimax algorithm.
* in case of an error - return a move with .steps_len = -1
* (envelope function that calls minimax())
*/
moves best_next_moves(settings set, int maximizer) {
	// minimax function
	moves best_moves = { 0 };
	move * temp_best_move;
	moves possible_moves = make_all_moves(&set);
	int best_score = INT_MIN;
	int curr_alpha = INT_MIN;
	if (possible_moves.len == -1) { //error
		return possible_moves;
	}

	int is_best_difficulty = (set.minimax_depth == BEST_DIFFICULTY);
	int depth = (!is_best_difficulty) ? set.minimax_depth : get_best_depth(&set, maximizer);

	move_node * curr = possible_moves.first;
	while (curr != NULL) {
		//get the score of each next possible moves, according to minimax algorithm
		settings next_set;
		memcpy(&next_set, &set, sizeof(settings));
		next_set.next = other_player(set.next);
		board_copy(((move*)curr->data)->board, next_set.board);
		int curr_score = minimax(next_set, curr_alpha, INT_MAX, FALSE, depth - 1, is_best_difficulty);
		if (curr_score == SCORE_ERROR) {
			free_list(&possible_moves, &free);
			free_list(&best_moves, &free);
			return error_moves;
		}
		if (curr_score > curr_alpha)
			curr_alpha = curr_score;
		temp_best_move = curr->data;
		if (curr_score > best_score) { // if new score is higher - free previous best moves
			free_list(&best_moves, &free);
			best_score = curr_score;
		}
		if (!(curr_score < best_score)) {
			if (!add_node(&best_moves, temp_best_move, sizeof(move))) {
				free_list(&best_moves, &free);
				free_list(&possible_moves, &free);
				return error_moves;
			}
		}
		curr = curr->next;
	}
	free_list(&possible_moves, &free);
	if (DEBUG)
		printf("CHOSEN SCORE: %d\n", best_score);
	return best_moves;
}
Example #13
0
bool game_init(game_t * game, const char fen[]) {

   ASSERT(game!=NULL);
   ASSERT(fen!=NULL);

   if (!board_from_fen(game->start_board,fen)) return false;

   game->size = 0;

   board_copy(game->board,game->start_board);
   game->pos = 0;

   game_update(game);

   return true;
}
Example #14
0
  move_c* solver_c::best_move(const board_c& board) const
  {
    if(!board.status.is_playable())
      throw error_not_playable();

    rate_t rates[board.size][board.size];
    for(move_c& move : board.all_moves_on_empty)
    {
      board_c board_copy(board);
      board_copy.play(move);
      rates[move.x][move.y] = rate(board_copy);
    }

    move_c moves[board.size*board.size];
    int moves_number = 0;
    for(move_c& move : board.all_moves_on_empty)
      if(moves_number == 0)
      {
        moves[0].set(move);
        moves_number = 1;
      }
      else if(compare_rate(rates[move.x][move.y], rates[moves[0].x][moves[0].y]))
      {
        moves[0].set(move);
        moves_number = 1;
      }
      else if(rates[move.x][move.y] == rates[moves[0].x][moves[0].y])
      {
        moves[moves_number].set(move);
        moves_number++;
      }

    move_c* move;
    switch(select)
    {
      case SELECT_RANDOM:
        move = new move_c(moves[util_c::random_int(0, moves_number-1)]);
        break;
      case SELECT_FIRST:
        move = new move_c(moves[0]);
        break;
      case SELECT_LAST:
        move = new move_c(moves[moves_number-1]);
        break;
    }
    return move;
  }
Example #15
0
static coord_t *
proof_genmove(struct engine *e, struct board *b, struct time_info *ti, enum stone color, bool pass_all_alive)
{
    coord_t *coord;
    fprintf(stderr, "HELLO WORLD!");
    struct board b2;
    board_copy(&b2, b);
    for (int i=0; i<=19; i++){
        for (int j=0; j<=19; j++){
            coord = coord_init(i,j,board_size(&b2));
            if (board_is_valid_play(&b2, color, *coord))
                return coord;
        }
    }
    *coord = -1;
    return coord;
}
Example #16
0
File: Chess.c Project: ishefi/chess
move get_castling_move(settings  * set, cord curr, int color) {
	cord c0 = { 0, curr.y };
	cord c1 = { 1, curr.y };
	cord c2 = { 2, curr.y };
	cord c3 = { 3, curr.y };
	cord c5 = { 5, curr.y };
	cord c6 = { 6, curr.y };
	cord c7 = { 7, curr.y };
	move castle = error_move;
	cord king_dest;
	cord king_loc = { 4, (color == WHITE) ? 0 : 7 };

	castle.start = curr;
	castle.is_castle = TRUE;
	castle.promotion = FALSE;
	board_copy(set->board, castle.board);

	int king_moved = (color == WHITE) ? set->white_king_moved : set->black_king_moved;
	int rook1_moved = (color == WHITE) ? set->white_rook_1_moved : set->black_rook_1_moved;
	int rook2_moved = (color == WHITE) ? set->white_rook_2_moved : set->black_rook_2_moved;

	int relevant_rook_moved = (!rook1_moved && (curr.x == 0) || !rook2_moved && (curr.x == 7));

	if (!king_moved && !is_king_checked(color, set->board) && !relevant_rook_moved) {
		if ((curr.x == 0) &&  //relevant rook is rook1 (big castle)
			((board_piece(set->board, c1) == EMPTY) &&
			(board_piece(set->board, c2) == EMPTY) &&
			(board_piece(set->board, c3) == EMPTY) && !is_cord_checked(c3, color, set->board))) {
			castle.end = c3;
			king_dest = c6;
		}
		else if ((curr.x == 7) &&
			(board_piece(set->board, c5) == EMPTY) &&
			(board_piece(set->board, c6) == EMPTY) && !is_cord_checked(c6, color, set->board)) {
			castle.end = c5;
			king_dest = c6;
			
		}
		move_from_to(castle.board, castle.start, castle.end);
		move_from_to(castle.board, king_loc, king_dest);
	}
	return castle;
}
Example #17
0
void game_goto(game_t * game, int pos) {

   int i;

   ASSERT(game!=NULL);
   ASSERT(pos>=0&&pos<=game->size);

   if (pos < game->pos) { // going backward => replay the whole game
      board_copy(game->board,game->start_board);
      game->pos = 0;
   }

   for (i = game->pos; i < pos; i++) move_do(game->board,game->move[i]);
   ASSERT(i==pos);

   game->pos = pos;

   game_update(game);
}
Example #18
0
bool line_to_san(const move_t line[], const board_t * board, char string[], int size) {

	board_t new_board[1];
	int pos;
	int move;
	char move_string[256];

	ASSERT(line_is_ok(line));
	ASSERT(board_is_ok(board));
	ASSERT(string!=NULL);
	ASSERT(size>=StringSize);

	// init
	string[0]='\0';
	if (size < StringSize) return false;
//    return false;
	board_copy(new_board,board);
	pos = 0;

	// loop

	while ((move = *line++) != MoveNone) {
		if (pos != 0) {
			if (pos >= size) return false;
			string[pos++] = ' ';
		}
		if (!move_is_legal(move,new_board)
			|| !move_to_san(move,new_board,&string[pos],size-pos)) {
				if (Strict || UseDebug) {
					move_to_can(move,new_board,move_string,sizeof(move_string));
					my_log("POLYGLOT ILLEGAL MOVE IN LINE %s\n",move_string);
					board_disp(new_board);
					if (Strict) my_fatal("line_to_san(): illegal move\n");
				}
				break;
		}
		pos += (int)strlen(&string[pos]);
		move_do(new_board,move);
	}
	if (pos >= size) return false;
	string[pos] = '\0';
	return true;
}
Example #19
0
static void perft(const board_t * board, int depth) {

   int me;
   list_t list[1];
   int i, move;
   board_t new_board[1];

   ASSERT(board_is_ok(board));
   ASSERT(depth_is_ok(depth));

   ASSERT(!is_in_check(board,colour_opp(board->turn)));

   // init

   NodeNb++;

   // leaf

   if (depth == 0) {
      LeafNb++;
      return;
   }

   // more init

   me = board->turn;

   // move loop

   gen_moves(list,board);

   for (i = 0; i < list_size(list); i++) {

      move = list_move(list,i);

      board_copy(new_board,board);
      move_do(new_board,move);

      if (!is_in_check(new_board,me)) perft(new_board,depth-1);
   }
}
AIMoves *ai_threats(const Board *original)
{
        AIMoves *moves;
        AIWEIGHT u_sum = 0;
        int i;

        b = board_new();
        board_copy(original, b);

        /* Clear threat tallys */
        for (i = 0; i < connect_k; i++) {
                threat_counts[i][0] = 0;
                threat_counts[i][1] = 0;
        }

        /* Horizontal lines */
        for (i = 0; i < board_size; i++)
                u_sum += threat_line(0, i, 1, 0);

        /* Vertical lines */
        for (i = 0; i < board_size; i++)
                u_sum += threat_line(i, 0, 0, 1);

        /* SE diagonals */
        for (i = 0; i < board_size - connect_k + 1; i++)
                u_sum += threat_line(i, 0, 1, 1);
        for (i = 1; i < board_size - connect_k + 1; i++)
                u_sum += threat_line(0, i, 1, 1);

        /* SW diagonals */
        for (i = connect_k - 1; i < board_size; i++)
                u_sum += threat_line(i, 0, -1, 1);
        for (i = 1; i < board_size - connect_k + 1; i++)
                u_sum += threat_line(board_size - 1, i, -1, 1);

        moves = ai_marks(b, PIECE_THREAT(1));
        moves->utility = u_sum;
        board_free(b);
        return moves;
}
Example #21
0
bool game_is_ok(const game_t * game) {

   board_t board[1];
   int pos, move;

   if (game == NULL) return false;

   if (game->size < 0 || game->size > GameSize) return false;
   if (game->pos < 0 || game->pos > game->size) return false;

   // optional heavy DEBUG mode

   if (!UseSlowDebug) return true;

   if (!board_is_ok(game->start_board)) return false;

   board_copy(board,game->start_board);

   for (pos = 0; pos <= game->size; pos++) {

      if (pos == game->pos) {
         if (!board_equal(game->board,board)) return false;
      }

      if (pos >= game->size) break;

      if (game->key[pos] != board->key) return false;

      move = game->move[pos];
      if (!move_is_legal(move,board))
          ;

      move_do(board,move);
   }

   if (game->status != game_comp_status(game)) return false;

   return true;
}
Example #22
0
bool line_to_can(const move_t line[], const board_t * board, char string[], int size) {

   board_t new_board[1];
   int pos;
   int move;

   ASSERT(line_is_ok(line));
   ASSERT(board_is_ok(board));
   ASSERT(string!=NULL);
   ASSERT(size>=StringSize);

   // init

   if (size < StringSize) return false;

   board_copy(new_board,board);
   pos = 0;

   // loop

   while ((move = *line++) != MoveNone) {

      if (pos != 0) {
         if (pos >= size) return false;
         string[pos++] = ' ';
      }

      if (!move_to_can(move,new_board,&string[pos],size-pos)) return false;
      pos += (int)strlen(&string[pos]);

      move_do(new_board,move);
   }

   if (pos >= size) return false;
   string[pos] = '\0';

   return true;
}
Example #23
0
void game_disp(const game_t * game) {

   board_t board[1];
   int i, move;

   ASSERT(game_is_ok(game));

   board_copy(board,game->start_board);

   board_disp(board);

   for (i = 0; i < game->pos; i++) {

      move = game->move[i];
      move_disp(move,board);

      move_do(board,move);
   }

   my_log("POLYGLOT\n");

   board_disp(board);
}
Example #24
0
bool line_from_can (move_t line[], const board_t * board, const char string[], int size) {

   int pos;
   char new_string[StringSize], *p;
   int move;
   board_t new_board[1];

   ASSERT(line!=NULL);
   ASSERT(board_is_ok(board));
   ASSERT(string!=NULL);
   ASSERT(size>=LineSize);

   // init

   pos = 0;
   board_copy(new_board,board);

   // loop

   strcpy(new_string,string); // HACK

   for (p = strtok(new_string," "); p != NULL; p = strtok(NULL," ")) {
      move = move_from_can(p,new_board);
      ASSERT(move!=MoveNone);
      ASSERT(move_is_legal(move,new_board));
      if (move == MoveNone || !move_is_legal(move,new_board)) break; // HACK: ignore illegal moves
      if (pos >= size) return false;
      line[pos++] = move;

      move_do(new_board,move);
   }

   if (pos >= size) return false;
   line[pos] = MoveNone;

   return true;
}
Example #25
0
File: Chess.c Project: ishefi/chess
/*
*	compute computer's next move and play.
*	return move in case of success, in case of lose/tie - return LOSE_CODE / TIE_CODE.
*	in case of an error - exit
*/
move computer_turn(settings * game_settings) {
	moves best_moves = best_next_moves(*game_settings, game_settings->next); //find next move
	move_node * random_best_move;
	move best_move;
	if (best_moves.len == -1) { // there was an error
		return error_move;
	}
	if (best_moves.len == 0) { // no possible moves - player wins
		best_move.promotion = NO_MOVE_CODE;
		return best_move;
	}
	else { // play best_move
		int r = rand() % best_moves.len;
		random_best_move = best_moves.first;
		for (int i = 0; i < r; i++) {
			random_best_move = random_best_move->next;
		};
		best_move = *(move*)random_best_move->data;
		board_copy(best_move.board, game_settings->board);
		free_list(&best_moves, &free);
		game_settings->is_next_checked = (is_king_checked(other_player(game_settings->next), game_settings->board));
		return best_move;
	}
}
Example #26
0
static void search_update() {

   int move;
   int move_nb;
   board_t board[1];

   ASSERT(!Uci->searching);

   // launch a new search if needed

   if (State->state == THINK || State->state == PONDER || State->state == ANALYSE) {

      // opening book

      if (State->state == THINK && option_get_bool("Book")) {

         game_get_board(Game,Uci->board);

         move = book_move(Uci->board,option_get_bool("BookRandom"));

         if (move != MoveNone && move_is_legal(move,Uci->board)) {

            my_log("POLYGLOT *BOOK MOVE*\n");

            search_clear(); // clears Uci->ponder_move
            Uci->best_move = move;

            board_copy(board,Uci->board);
            move_do(board,move);
            Uci->ponder_move = book_move(board,false); // expected move = best book move

            Uci->best_pv[0] = Uci->best_move;
            Uci->best_pv[1] = Uci->ponder_move; // can be MoveNone
            Uci->best_pv[2] = MoveNone;

            comp_move(Uci->best_move);

            return;
         }
      }

      // engine search

      my_log("POLYGLOT START SEARCH\n");

      // options

      uci_send_option(Uci,"UCI_Chess960","%s",option_get_bool("Chess960")?"true":"false");

      if (option_get_int("UCIVersion") >= 2) {
         uci_send_option(Uci,"UCI_Opponent","none none %s %s",(XB->computer)?"computer":"human",XB->name);
         uci_send_option(Uci,"UCI_AnalyseMode","%s",(XB->analyse)?"true":"false");
      }

      uci_send_option(Uci,"Ponder","%s",ponder()?"true":"false");

      // position

      move = (State->state == PONDER) ? State->exp_move : MoveNone;
      send_board(move); // updates Uci->board global variable

      // search

      if (State->state == THINK || State->state == PONDER) {

         engine_send_queue(Engine,"go");

         if (XB->time_limit) {

            // fixed time per move

            engine_send_queue(Engine," movetime %.0f",XB->time_max*1000.0);

         } else {

            // time controls

            if (colour_is_white(Uci->board->turn)) {
               engine_send_queue(Engine," wtime %.0f btime %.0f",XB->my_time*1000.0,XB->opp_time*1000.0);
            } else {
               engine_send_queue(Engine," wtime %.0f btime %.0f",XB->opp_time*1000.0,XB->my_time*1000.0);
            }

            if (XB->inc != 0.0) engine_send_queue(Engine," winc %.0f binc %.0f",XB->inc*1000.0,XB->inc*1000.0);

            if (XB->mps != 0) {

               move_nb = XB->mps - (Uci->board->move_nb % XB->mps);
               ASSERT(move_nb>=1&&move_nb<=XB->mps);

               engine_send_queue(Engine," movestogo %d",move_nb);
            }
         }

         if (XB->depth_limit) engine_send_queue(Engine," depth %d",XB->depth_max);

         if (State->state == PONDER) engine_send_queue(Engine," ponder");

         engine_send(Engine,""); // newline

      } else if (State->state == ANALYSE) {

         engine_send(Engine,"go infinite");

      } else {

         ASSERT(false);
      }

      // init search info

      ASSERT(!Uci->searching);

      search_clear();

      Uci->searching = true;
      Uci->pending_nb++;
   }
}
Example #27
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;
   }
}
Example #28
0
void Notation::image(const Board & b, const Move & m, OutputFormat format, ostream &image) {
   if (format == UCI) {
      return UCIMoveImage(m,image);
   }
   else if (format == WB_OUT) {
      if (TypeOfMove(m) == KCastle) {
          image << "O-O";
      }
      else if (TypeOfMove(m) == QCastle) {
          image << "O-O-O";
      }
      else {
         image << FileImage(StartSquare(m));
         image << RankImage(StartSquare(m));
         image << FileImage(DestSquare(m));
         image << RankImage(DestSquare(m));
         if (TypeOfMove(m) == Promotion) {
            // N.b. ICS requires lower case.
            image << (char)tolower((int)PieceImage(PromoteTo(m)));
         }
      }
      return;
   }
   // format is SAN
   if (IsNull(m)) {
       image << "(null)";
      return;
   }

   PieceType p = PieceMoved(m);
   ASSERT(p != Empty);
   if (TypeOfMove(m) == KCastle) {
       image << "O-O";
   }
   else if (TypeOfMove(m) == QCastle) {
       image << "O-O-O";
   }
   else {
      if (p == Pawn) {
         if (Capture(m) == Empty) {
            image << FileImage(DestSquare(m));
            image << RankImage(DestSquare(m));
         }
         else {
            image << FileImage(StartSquare(m));
            image << 'x';
            image << FileImage(DestSquare(m));
            image << RankImage(DestSquare(m));
         }
         if (TypeOfMove(m) == Promotion) {
            image << '=';
            image << PieceImage(PromoteTo(m));
         }
      }
      else {
         image << PieceImage(p);
         Bitboard attacks =
            b.calcAttacks(DestSquare(m), b.sideToMove());
         unsigned n = attacks.bitCount();
         int dups = 0;
         int filedups = 0;
         int rankdups = 0;
         int files[9];
         int ranks[9];

         if (n > 1) {
            Square sq;
            while (attacks.iterate(sq)) {
               if (TypeOfPiece(b[sq]) == p) {
                  files[dups] = File(sq);
                  if (files[dups] == File(StartSquare(m)))
                     filedups++;
                  ranks[dups] = Rank(sq,White);
                  if (ranks[dups] == Rank(StartSquare(m),White))
                     rankdups++;
                  ++dups;
               }
            }
         }
         if (dups > 1) {
            // need to disambiguate move.
            if (filedups == 1) {
               image << FileImage(StartSquare(m));
            }
            else if (rankdups == 1) {
               image << RankImage(StartSquare(m));
            }
            else {
               // need both rank and file to disambiguate
               image << FileImage(StartSquare(m));
               image << RankImage(StartSquare(m));
            }
         }
         if (Capture(m) != Empty) {
            image << 'x';
         }
         image << FileImage(DestSquare(m));
         image << RankImage(DestSquare(m));
      }
   }
   Board board_copy(b);
   board_copy.doMove(m);
   if (board_copy.checkStatus() == InCheck) {
      Move moves[Constants::MaxMoves];
      MoveGenerator mg(board_copy);
      if (mg.generateEvasions(moves))
         image << '+';
      else
         image << '#';                        // mate
   }
}
Example #29
0
Move Notation::value(const Board & board, ColorType side, InputFormat format, const string &image) 
{
    int rank = 0;
    int file = 0;

    PieceType piece = Empty;
    PieceType promotion = Empty;
    Square dest = InvalidSquare, start = InvalidSquare;
    int capture = 0;

    stringstream s(image);
    string::const_iterator it = image.begin();
    int i = 0;
    while (it != image.end() && isspace(*it)) {
        it++;
        i++;
    }
    if (it == image.end() || !isalpha(*it)) return NullMove;
    string img(image,i); // string w/o leading spaces
    ASSERT(img.length());
    it = img.begin();
    if (*it == 'O' || *it == '0') {
       // castling, we presume
       return parseCastling(board, side, img);
    } else if (format == WB_IN) {
       if (img.length() < 4) return NullMove;
       Square start = SquareValue(img.substr(0,2));
       if (!OnBoard(start)) return NullMove;
       Square dest = SquareValue(img.substr(2,2));
       if (!OnBoard(dest)) return NullMove;
       PieceType promotion = Empty;
       if (img.length() > 4) {
          promotion = PieceCharValue(toupper(img[4]));
       }
       return CreateMove(board,start,dest,promotion);
    }
    int have_start = 0;
    if (isupper(*it)) {
       piece = PieceCharValue(*it);
       it++;
    }
    else {
       piece = Pawn;
       if ((it+1) != img.end()) {
          char next = *it;
          file = next-'a'+1;
          if (file < 1 || file > 8) return NullMove;
          char next2 = *(it+1);
          if (next2 == 'x' || is_file(next2)) {
             // allow "dc4" as in Informant, instead of dxc4
             it++;
             capture = 1;
          }
          else if (isdigit(next2) && img.length()>2) {
             char next3 = *(it+2);
             if ((next3 == 'x' || next3 == '-') && img.length()>=5) {
                // long algebraic notation
                have_start++;
                start = SquareValue(next,next2);
                if (start == InvalidSquare) return NullMove;
                it+=3; // point to dest
                piece = TypeOfPiece(board[start]);
             }
          }
       }
    }
    if (piece == Empty) {
       return NullMove;
    }
    if (piece != Pawn && !have_start && it != img.end()) {
       char next = *it;
       char next2 = '\0';
       if (it + 1 != img.end()) next2 = *(it+1);
       if (is_file(next) && isdigit(next2) && img.length()>=5) {
          // long algebraic notation, or a SAN move like Qd1d3
          start = SquareValue(next,next2);
          if (IsInvalid(start)) return NullMove;
          it+=2;
          have_start++;
       }
       // also look for disambiguating rank, e.g. '2' in "N2e4".
       else if (isdigit(next)) {
          rank = next - '0';
          if (rank < 1 || rank > 8) return NullMove;
          it++;
       }
       else if (is_file(next) && isalpha(next2)) {
          // disamiguating rank, e.g. "Rfd1"
          file = next - 'a' + 1;
          if (file < 1 || file > 8) return NullMove;
          it++;
       }
    }

    if (it != img.end() && *it == 'x') {
       capture = 1;
       it++;
    }
    if (it != img.end() && (it+1) != img.end()) {
       // remainder of move should be a square identifier, e.g. "g7"
       dest = SquareValue(*it,*(it+1));
       it += 2;
    }
    if (IsInvalid(dest)) {
       return NullMove;
    }
    if (it != img.end() && *it == '=') {
       it++;
       if (it == img.end()) {
          return NullMove;
       } else {
          promotion = PieceCharValue(*it);
          if (piece != Pawn || promotion == Empty)
             return NullMove;
          it++;
       }
    }
    else if (piece == Pawn && it != img.end() && isupper(*it)) {
       // Quite a few "PGN" files have a8Q instead of a8=Q.
       promotion = PieceCharValue(*it);
       if (promotion == Empty || Rank(dest,side) != 8)
          return NullMove;
    } else if (piece == Pawn && Rank(dest,side) == 8) {
       // promotion but no piece specified, treat as error
       return NullMove;
    }

    // Informant does not use "x" for captures.  Assume that if the destination
    // is occupied, this is a capture move.
    if (board[dest] != EmptyPiece) {
       capture = 1;
    }
    // Do a sanity check on capture moves:
    if (capture && !IsEmptyPiece(board[dest]) && PieceColor(board[dest]) == board.sideToMove()) {
       return NullMove;
    }

    // Ok, now we need to figure out where the start square is. For pawn
    // moves this is implicit.

    int dups = 0;

    if (!have_start) {
       if (capture && piece == Pawn && IsEmptyPiece(board[dest]) &&
           Rank(dest,board.sideToMove()) != 8) {
          // en passant capture, special case
          int start_rank = (board.sideToMove() == White) ?
             Rank(dest,White) - 1 :
             Rank(dest,White) + 1;

          start = MakeSquare(file, start_rank, White);
          dups = 1;
       }
       else if (piece == Pawn && board[dest] == EmptyPiece) {
          start = MakeSquare(file,Rank(dest,board.sideToMove())-1,board.sideToMove());
          if (board[start] == EmptyPiece && Rank(dest,board.sideToMove())==4) {
             start = MakeSquare(file,Rank(dest,board.sideToMove())-2,board.sideToMove());
          }
          if (board[start] == EmptyPiece) return NullMove;
          dups = 1;
       }
       else {
          Bitboard attacks = board.calcAttacks(dest,side);
          Square maybe;
          while (attacks.iterate(maybe)) {
             if (TypeOfPiece(board[maybe]) == piece &&
                 PieceColor(board[maybe]) == board.sideToMove()) {
                if (file && File(maybe) != file)
                   continue;
                if (rank && Rank(maybe,White) != rank)
                   continue;
                if (PieceColor(board[maybe]) == board.sideToMove()) {
                   // Possible move to this square.  Make sure it is legal.
                   Board board_copy(board);
                   Move emove = CreateMove(board,maybe,dest,
                                           promotion);
                   board_copy.doMove(emove);
                   if (!board_copy.anyAttacks(
                          board_copy.kingSquare(board_copy.oppositeSide()),
                          board_copy.sideToMove())) {
                      ++dups;
                      start = maybe;
                   }
                }
             }
          }
       }
    }
    if (dups == 1 || have_start) {
       if (start == InvalidSquare || board[start] == EmptyPiece)
          return NullMove;
       else
          return CreateMove(board, start, dest, promotion);
    }
    else                                           // ambiguous move
       return NullMove;
}
Example #30
0
static int parse_bestmove(uci_t * uci, const char string[]) {

   parse_t parse[1];
   char command[StringSize];
   char option[StringSize];
   char argument[StringSize];
   board_t board[1];

   ASSERT(uci_is_ok(uci));
   ASSERT(string!=NULL);

   // init

   strcpy(command,"bestmove");

   parse_open(parse,string);
   parse_add_keyword(parse,"ponder");

   // bestmove

   if (!parse_get_string(parse,argument,StringSize)) {
      my_fatal("parse_bestmove(): missing argument\n");
   }

   uci->best_move = move_from_can(argument,uci->board);
   if (uci->best_move == MoveNone) my_fatal("parse_bestmove(): not a move \"%s\"\n",argument);

   ASSERT(uci->best_move!=MoveNone);
   ASSERT(move_is_legal(uci->best_move,uci->board));

   // loop

   while (parse_get_word(parse,option,StringSize)) {

      parse_get_string(parse,argument,StringSize);

      if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);

      if (false) {

      } else if (my_string_equal(option,"ponder")) {

         ASSERT(!my_string_empty(argument));

         board_copy(board,uci->board);
         move_do(board,uci->best_move);

         uci->ponder_move = move_from_can(argument,board);
         // if (uci->ponder_move == MoveNone) my_fatal("parse_bestmove(): not a move \"%s\"\n",argument);

         ASSERT(uci->ponder_move!=MoveNone);
         ASSERT(move_is_legal(uci->ponder_move,board));

      } else {

         my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);
      }
   }

   parse_close(parse);

   return EVENT_MOVE;
}