예제 #1
0
int ZWS(int beta, int depth, int can_reduce)
{
    if(is_draw_by_repetition_or_50_moves()) return DRAW;
    
    Entry *entry = hash_get_entry();
    if(entry != NULL && entry->depth >= depth)
    {
        int eval = entry->eval, flag = entry->flag;
        if(flag != LESS_THAN_ALPHA && eval >= beta)
            return beta;
        if(flag != MORE_THAN_BETA && eval < beta)
            return beta - 1;
    }
    
    if(depth == 0) return quiescence(beta - 1, beta);
    
    /*if(depth <= 6 && evaluate(beta - 1, beta) >= beta)
    {
        return beta;
    }*/
    
    if(depth > 2 && can_reduce && !in_check(turn_to_move))
    {
        int R = depth > 6 ? 3: 2;
        make_null_move();
        int score = -ZWS(-beta + 1, depth - R - 1, 0);
        unmake_null_move();
        if(score >= beta) return 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);
    for(int i = 0; i < n; i += 1)
    {
        Move i_move = movelist[i];
        make_move(i_move);
        int score = -ZWS(-beta + 1, depth - 1, can_reduce);
        unmake_move(i_move);
        
        if(score >= beta)
        {
            hash_save_entry(depth, beta, i_move, MORE_THAN_BETA);
            return beta;
        }
    }
    hash_save_entry(depth, beta - 1, 0, LESS_THAN_ALPHA);
    return beta - 1;
}
예제 #2
0
파일: .c 프로젝트: leaderwing/test_repo
void print_result()
{
	int i;

	/* is there a legal move? */
	for (i = 0; i < first_move[1]; ++i)
		if (makemove(gen_dat[i].m.b)) {
			takeback();
			break;
		}
	if (i == first_move[1]) {
		if (in_check(side)) {
			if (side == LIGHT)
				printf("0-1 {Black mates}\n");
			else
				printf("1-0 {White mates}\n");
		}
		else
			printf("1/2-1/2 {Stalemate}\n");
	}
	else if (reps() == 3)
		printf("1/2-1/2 {Draw by repetition}\n");
	else if (fifty >= 100)
		printf("1/2-1/2 {Draw by fifty move rule}\n");
}
예제 #3
0
파일: search2.c 프로젝트: zwegner/zct
/**
extend_move():
Calculates the search extension to be awarded to the given move. This is based
on various information such as whether the move checks, if it is a threat or
not, etc. This also determines whether a move should be reduced or not.
Created 072007; last modified 081808
**/
int extend_move(SEARCH_BLOCK *sb)
{
	int extension;
	int lmr_moves;

	/* First, determine if the move should be extended (rather than reduced). */
	extension = 0;
	if (!(sb->move & MOVE_NOEXTEND))
	{
		/* check extension */
		if (in_check())
		{
			extension += zct->check_extension;
			zct->check_extensions_done++;
		}
		/* one-reply extension */
		if (sb->check && sb->last_move - sb->first_move == 1)
		{
			extension += zct->one_rep_extension;
			zct->one_rep_extensions_done++;
		}
		/* pawn to 7th extension */
		if (board.piece[MOVE_TO(sb->move)] == PAWN &&
			RANK_OF(SQ_FLIP_COLOR(MOVE_TO(sb->move), board.side_ntm)) == RANK_7)
		{
			extension += zct->passed_pawn_extension;
			zct->passed_pawn_extensions_done++;
		}
		extension = MIN(PLY, extension);
	}

	/* Now try to reduce the move. If the move is marked as not reducible, or
		if the depth is too low, don't bother reducing it. */
	if (extension > 0 || sb->depth < 2 * PLY || (sb->move & MOVE_NOREDUCE))
		return extension;

	lmr_moves = 0;
	switch (sb->node_type)
	{
		case NODE_PV:
			lmr_moves = 5;
			break;
		case NODE_CUT:
			lmr_moves = 2;
			break;
		case NODE_ALL:
			lmr_moves = 3;
			break;
	}

	/* Most LMR conditions are already covered in the move scoring routines.
		The only "dynamic" factor is the count of moves. */
	if (sb->moves > lmr_moves)
	{
		sb->move |= MOVE_ISREDUCED;
		extension -= PLY;
	}

	return extension;
}
예제 #4
0
파일: main.c 프로젝트: BadrElh/microwindows
/* print_result() checks to see if the game is over */
void print_result()
{
        int i;
 
        /* is there a legal move? */
        for (i = 0; i < first_move[1]; ++i)
                if (makemove(gen_dat[i].m.b)) {
                        takeback();
                        break;
                }
        if (i == first_move[1]) {
                if (in_check(side)) {
                        if (side == LIGHT)
                                gprintf("Black mates");
                        else
                                gprintf("White mates");
                }
                else
                        gprintf("Stalemate");
        }
        else if (reps() == 3)
                gprintf("Draw by repetition");
        else if (fifty >= 100)
                gprintf("Draw by fifty move rule");
}             
예제 #5
0
파일: board.c 프로젝트: konker/dreamchess
void move_set_attr(board_t *b, move_t *move)
{
    int check, mated;
    board_t board = *b;

    if (move_is_capture(b, move))
        move->type = CAPTURE;
    else
        move->type = NORMAL;

    if (PIECE(b->square[move->source]) == KING)
    {
        int hor = move->destination % 8 - move->source % 8;

        if (hor > 1)
            move->type = KINGSIDE_CASTLE;
        else if (hor < -1)
            move->type = QUEENSIDE_CASTLE;
    }

    make_move(&board, move);

    check = in_check(&board, board.turn);
    mated = is_mated(&board, board.turn);

    if (check && mated)
        move->state = MOVE_CHECKMATE;
    else if (check)
        move->state = MOVE_CHECK;
    else if (mated)
        move->state = MOVE_STALEMATE;
    else
        move->state = MOVE_NORMAL;

}
예제 #6
0
void record_a_move(int x, int y, int to_x, int to_y, int captures_only, int depth)
	{
//printf("record(%d,%d,%d,%d,%d,%d)\n",x,y,to_x,to_y,captures_only,depth);
	if (captures_only && board.cells[to_x][to_y] == 0)
		return;
	if (board.cells[x][y])
		++attacked_squares[depth][to_x][to_y];

	if (attacked_squares_only == 0)
		{
		int check;

		moves[depth][move_counter[depth]].x = x;
		moves[depth][move_counter[depth]].y = y;
		moves[depth][move_counter[depth]].piece = board.cells[x][y];
		moves[depth][move_counter[depth]].to_x = to_x;
		moves[depth][move_counter[depth]].to_y = to_y;
		moves[depth][move_counter[depth]].captured_piece = board.cells[to_x][to_y];

		make_move(&moves[depth][move_counter[depth]]);
		board.side = !board.side; // these switches are dumb
		check = in_check(depth);
		board.side = !board.side;
		unmake_move(&moves[depth][move_counter[depth]]);

		if (!check) ++move_counter[depth];
		}
	}
예제 #7
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;
}
예제 #8
0
파일: board.c 프로젝트: konker/dreamchess
int move_is_valid(board_t *b, move_t *move)
{
    board_t board = *b;

    if (!move_is_semi_valid(&board, move))
        return 0;

    make_move(&board, move);

    return !in_check(&board, b->turn);
}
예제 #9
0
void record_a_spawn(piece, to_x, to_y, depth)
	{
	int check;
	moves[depth][move_counter[depth]].x = -1;
	moves[depth][move_counter[depth]].y = -1;
	moves[depth][move_counter[depth]].piece = piece;
	moves[depth][move_counter[depth]].to_x = to_x;
	moves[depth][move_counter[depth]].to_y = to_y;
	moves[depth][move_counter[depth]].captured_piece = 0;

	make_move(&moves[depth][move_counter[depth]]);
	board.side = !board.side; // these switches are dumb
	check = in_check(depth);
	board.side = !board.side;
	unmake_move(&moves[depth][move_counter[depth]]);

	if (!check) ++move_counter[depth];
	}
예제 #10
0
파일: search.c 프로젝트: dylhunn/fianchetto
void search(board *b, int ply) {
	clear_stats(); // Stats for search
	sstats.depth = ply;
	// Start timer for the search
	struct timeval t1, t2;
   	gettimeofday(&t1, NULL);
   	int result;
	if (use_mtd_f) result = mtd_f(b, ply);
	else {
		coord king_loc = b->black_to_move ? b->black_king : b->white_king;
		bool side_to_move_in_check = in_check(b, king_loc.col, king_loc.row, b->black_to_move);
		result = abq(b, NEG_INFINITY, POS_INFINITY, ply, 0, true, side_to_move_in_check);
	}
	gettimeofday(&t2, NULL);
	// Compute and print the elapsed time in millisec
	double search_millisec = (t2.tv_sec - t1.tv_sec) * 1000.0; // sec to ms
	search_millisec += (t2.tv_usec - t1.tv_usec) / 1000.0; // us to ms
	sstats.time = search_millisec;
}
예제 #11
0
/* Let's make the iPod think about ;-) */
void computer_play(void)
{
	if (!is_mini) {
		pz_draw_header("computer play");
	}

	/* think about the move and make it */
	//sleep(1);
	printf("think\n");
	think(2);

	//sleep(1);
	if (!pv[0][0].u) {
		printf("No legal moves\n");
		if (!is_mini) {
			pz_draw_header ("No legal moves");
		}
	}

	sprintf(cpu_move,"%s", move_str(pv[0][0].b));

	makemove(pv[0][0].b);
	ply = 0;
	gen_moves();
	if (in_check(LIGHT)) {
		if (is_mini) {
			draw_message("     ", "Check");
		}
		else {
			pz_draw_header("Check");
		}
	}
	else
	{
		if (is_mini) {
			draw_message("     ", "Play");
		}
		else {
			pz_draw_header("Your Turn");
		}
	}
}
예제 #12
0
/* Common function for cursor positionning */
void new_cursor_position(void)
{
	char temp1[5], temp2[12];

	print_board();

	if (in_check(LIGHT))
	{
		if (sel) {
			sprintf(temp2, "Check! %c%c-%c%c",oldx,oldy,xcoord,ycoord);
		}
		else {
			sprintf(temp2, "Check! %c%c-",xcoord,ycoord);
		}
		if (!is_mini) {
			pz_draw_header(temp2);
		}
	}
	else
	{
		if(sel) {
			sprintf(temp1,"%c%c-%c%c",oldx,oldy,xcoord,ycoord);
		}
		else {
			sprintf(temp1,"%c%c-",xcoord,ycoord);
		}
		if (is_mini) {
			draw_message(temp1,"     ");
		}
		else {
			pz_draw_header(temp1);
		}
	}

	print_result();
	printf(temp1);
	printf("\n");
}
예제 #13
0
파일: search.c 프로젝트: dylhunn/fianchetto
int mtd_f(board *board, int ply) {
	int g; // First guess of evaluation
	evaluation stored;
	tt_get(board, &stored); // Use last pass in Transposition Table
	if (!e_eq(stored, no_eval)) g = stored.score; // If not present, use static evaluation as guess
	else {
		g = evaluate(board);
		if (board->black_to_move) g = -g;
	}
	int upper_bound = POS_INFINITY;
	int lower_bound = NEG_INFINITY;
	coord king_loc = board->black_to_move ? board->black_king : board->white_king;
	bool side_to_move_in_check = in_check(board, king_loc.col, king_loc.row, board->black_to_move);
	while (lower_bound < upper_bound) {
		if (search_terminate_requested) return 0;
		int beta;
		if (g == lower_bound) beta = g+1;
		else beta = g;
		g = abq(board, beta-1, beta, ply, 0, true, side_to_move_in_check);
		if (g < beta) upper_bound = g;
		else lower_bound = g;
	}
	return g;
}
예제 #14
0
void CheckBadFlow(bool reset)
{
  move_s hismoves[MOVE_BUFF];
  move_s ourmoves[MOVE_BUFF];
  int his_num_moves, our_num_moves, j, i, ic, icc;

  bool othermove = FALSE;

  int 
    pawnmates = FALSE, 
    knightmates = FALSE, 
    bishopmates = FALSE, 
    rookmates = FALSE, 
    queenmates = FALSE;
  
  static int 
    pawnmated = FALSE, 
    knightmated = FALSE, 
    bishopmated = FALSE, 
    rookmated = FALSE, 
    queenmated = FALSE;

  bool
    pawnwarn = FALSE,
    knightwarn = FALSE,
    bishopwarn = FALSE,
    rookwarn = FALSE,
    queenwarn = FALSE;

  if (reset)
    {
      pawnmated = FALSE; 
      knightmated = FALSE; 
      bishopmated = FALSE; 
      rookmated = FALSE; 
      queenmated = FALSE;
      return;
    }

  ic = in_check();

  if (!holding[!white_to_move][(white_to_move ? wpawn : bpawn)])
    {
  
      DropaddHolding((white_to_move ? wpawn : bpawn) , !white_to_move);
      
      gen(&hismoves[0]);
      his_num_moves = numb_moves;
      
      for(i = 0; (i < his_num_moves) && (pawnmates == FALSE); i++)
	{
	  make(&hismoves[0], i);
	  
	  if (check_legal(&hismoves[0], i, ic))
	    {
	      pawnmates = CANCEL_THRESH;

	      icc = in_check();
	      
	      gen(&ourmoves[0]); 
	      our_num_moves = numb_moves;
	      
	      for (j = 0; (j < our_num_moves) && (pawnmates != FALSE); j++)
		{
		  
		  make(&ourmoves[0], j);
		  
		  if (check_legal(&ourmoves[0], j, icc))
		    pawnmates = FALSE;
		  
		  unmake(&ourmoves[0], j);
		  
		}
	    }
	  unmake(&hismoves[0], i);	  
	}
      DropremoveHolding((white_to_move ? wpawn : bpawn), !white_to_move);
    }
  
  if (!holding[!white_to_move][(white_to_move ? wknight : bknight)])
    {
      
      DropaddHolding((white_to_move ? wknight : bknight) , !white_to_move);
      
      gen(&hismoves[0]); 
      his_num_moves = numb_moves;
      
      for(i = 0; (i < his_num_moves) && (knightmates == FALSE); i++)
	{
	  
	  make(&hismoves[0], i);
	  
	  if (check_legal(&hismoves[0], i, ic))
	    {
	      knightmates = CANCEL_THRESH;

	      icc = in_check();
	      
	      gen(&ourmoves[0]); 
	      our_num_moves = numb_moves;
	      
	      for (j = 0; (j < our_num_moves) && (knightmates != FALSE); j++)
		{
		  make(&ourmoves[0], j);
		  
		  if (check_legal(&ourmoves[0], j, icc))
		    knightmates = FALSE;
		  
		  unmake(&ourmoves[0], j);
		}
	    }
	  unmake(&hismoves[0], i);
	}
      DropremoveHolding((white_to_move ? wknight : bknight), !white_to_move);
    }
  
  if (!holding[!white_to_move][(white_to_move ? wbishop : bbishop)])
    {      
      
      DropaddHolding((white_to_move ? wbishop : bbishop) , !white_to_move);
      
      gen(&hismoves[0]); 
      his_num_moves = numb_moves;
      
      for(i = 0; (i < his_num_moves) && (bishopmates == FALSE); i++)
	{
	  make(&hismoves[0], i);
	  
	  if (check_legal(&hismoves[0], i, ic))
	    {
	      bishopmates = CANCEL_THRESH;
	      
	      icc = in_check();

	      gen(&ourmoves[0]);
	      our_num_moves = numb_moves;
	      
	      for (j = 0; (j < our_num_moves) && (bishopmates != FALSE); j++)
		{
		  make(&ourmoves[0], j);
		  
		  if (check_legal(&ourmoves[0], j, icc))
		    bishopmates = FALSE;
		  
		  unmake(&ourmoves[0], j);
		}
	    }
	  unmake(&hismoves[0], i);
	}
      DropremoveHolding((white_to_move ? wbishop : bbishop), !white_to_move);  
    }
  
  if (!holding[!white_to_move][(white_to_move ? wrook : brook)])
    {
      
      DropaddHolding((white_to_move ? wrook : brook) , !white_to_move);
      
      gen(&hismoves[0]);
      his_num_moves= numb_moves;
      
      for(i = 0; (i < his_num_moves) && (rookmates == FALSE); i++)
	{
	  make(&hismoves[0], i);
	  
	  if (check_legal(&hismoves[0], i, ic))
	    {
	      rookmates = CANCEL_THRESH;

	      icc = in_check();
	      
	      gen(&ourmoves[0]);
	      our_num_moves = numb_moves;
	      
	      for (j = 0; (j < our_num_moves) && (rookmates != FALSE); j++)
		{
		  make(&ourmoves[0], j);
		  
		  if (check_legal(&ourmoves[0], j, icc))
		    rookmates = FALSE;
		  
		  unmake(&ourmoves[0], j); 
		}
	    }
	  unmake(&hismoves[0], i);
	}
      DropremoveHolding((white_to_move ? wrook : brook), !white_to_move); 
    }
  
  if (!holding[!white_to_move][(white_to_move ? wqueen : bqueen)])
    {
      
      DropaddHolding((white_to_move ? wqueen : bqueen) , !white_to_move);

      gen(&hismoves[0]);
      his_num_moves= numb_moves;
      
      for(i = 0; (i < his_num_moves) && (queenmates == FALSE); i++)
	{
	  make(&hismoves[0], i);
	  
	  if (check_legal(&hismoves[0], i, ic))
	    {
	      queenmates = CANCEL_THRESH;

	      icc = in_check();
	      
	      gen(&ourmoves[0]);
	      our_num_moves = numb_moves;
	      
	      for (j = 0; (j < our_num_moves) && (queenmates != FALSE); j++)
		{
		  make(&ourmoves[0], j);
		  
		  if (check_legal(&ourmoves[0], j, icc))
		    queenmates = FALSE;
		  
		  unmake(&ourmoves[0], j); 
		}
	    }
	  unmake(&hismoves[0], i);
	}
      DropremoveHolding((white_to_move ? wqueen : bqueen), !white_to_move);
    }

  /* order in which we tell things is important if we partner ourselves */
  
  /* only update if changed */
  if (pawnmates != pawnmated)
    {
      if (pawnmates == CANCEL_THRESH)
	  pawnwarn = TRUE;
      else if (pawnmates == 0 && pawnmated == 0)
	{
	  printf("tellics ptell p doesn't mate me anymore\n");
	  othermove = TRUE;
	}
    }
  
  if (knightmates != knightmated)
    {
      if (knightmates == CANCEL_THRESH)
	  knightwarn = TRUE;
      else if (knightmates == 0 && knightmated == 0)
	{
	  printf("tellics ptell n doesn't mate me anymore\n");
	  othermove = TRUE;
	}
    }  

  if (bishopmates != bishopmated)
    {
      if (bishopmates == CANCEL_THRESH)
	  bishopwarn = TRUE;
      else if (bishopmates == 0 && bishopmated == 0)
	{
	  printf("tellics ptell b doesn't mate me anymore\n");
	  othermove = TRUE;
	}
    }  
  if (rookmates != rookmated)
    {
      if (rookmates == CANCEL_THRESH)
	  rookwarn = TRUE;
      else if (rookmates == 0 && rookmated == 0)
	{
	  printf("tellics ptell r doesn't mate me anymore\n");
	  othermove = TRUE;
	}
    }
  if (queenmates != queenmated)
    {
      if (queenmates == CANCEL_THRESH)
	  queenwarn = TRUE;
      else if (queenmates == 0 && queenmated == 0)
	{
	  printf("tellics ptell q doesn't mate me anymore\n");
	  othermove = TRUE;
	} 
    }

  if (pawnwarn)
	printf("tellics ptell ---p\n");
  if (knightwarn)
	printf("tellics ptell ---n\n");
  if (bishopwarn)
	printf("tellics ptell ---b\n");
  if (rookwarn)
	printf("tellics ptell ---r\n");
  if (queenwarn)
	printf("tellics ptell ---q\n");

  /* if other sjeng had to sit because of piece-loss, he
     may be able to go now */
  
  if (piecedead && othermove)
    {
      piecedead = FALSE;
      printf("tellics ptell x\n");
      printf("tellics ptell go\n");
      go_fast = FALSE;
    }

  (pawnmates) ? (pawnmated = pawnmates) : (pawnmated--);
  (bishopmates) ? (bishopmated = bishopmates) : (bishopmated--);
  (rookmates) ? (rookmated = rookmates) : (rookmated--);
  (queenmates) ? (queenmated = queenmates) : (queenmated--);
  (knightmates) ? (knightmated = knightmates) : (knightmated--);

  return;
}
예제 #15
0
void E_scene_main_game::update_result()
{
	
	/* check for draw by the 50 move rule: */
	if (fifty > 100) 
	{
		result = draw_by_fifty;
		return;		
	}
	else if (is_draw ()) 
	{
		result = draw_by_rep;
		return;
	}
	
	
	move_s moves[MOVE_BUFF];
	int num_moves, i, ep_temp;
	d_long temp_hash;

	ep_temp = ep_square;
	temp_hash = cur_pos;
	num_moves = 0;
	gen (&moves[0], &num_moves);
	
	// for all possible moves for all pieces
	for (i = 0; i < num_moves; i++) 
	{
		// if the move is from the side of the current player
		bool color=moves[i].from%2;
		if (current_color==WHITE)
			color=!color;
		
		// if the selected piece is not owned by the current player, continue
		if (!color) 
			continue;
		
		// test if the move is legal
		make (&moves[0], i);
		bool legal=check_legal (&moves[0], i); 
		
		unmake (&moves[0], i);
		ep_square = ep_temp;
		cur_pos = temp_hash;
		
		// if we find a legal move, game can continue
		if (legal)
			return;
	}	
	
	
	// if we are here, it means that there is no
	// move avaible for the current player
	if (in_check ())
	{
		if (white_to_move == 1)
			result = white_is_mated;
		else 
			result = black_is_mated;
	}
	else 
	{
		result = stalemate;
	}
	
}
예제 #16
0
/*
 * in_find(): Find a match for the host, user, domain spec
 */
static int
in_find(char *ypdom, struct stringlist *sl, char *grp, const char *host,
    const char *user, const char *domain)
{
	char		*line, *p;
	int		 i;
	struct netgroup	*ng;
	char		*name;

#ifdef DEBUG_NG
	(void) fprintf(stderr, "in_find(%s)\n", grp);
#endif
	/* check for cycles */
	if (_ng_sl_find(sl, grp) != NULL) {
		_warnx("netgroup: Cycle in group `%s'", grp);
		free(grp);
		return 0;
	}
	if (_ng_sl_add(sl, grp) == -1) {
		free(grp);
		return 0;
	}

	/* Lookup this netgroup */
	if (!lookup(ypdom, grp, &line, _NG_KEYBYNAME))
		return 0;

	p = line;

	for (;;) {
		switch (_ng_parse(&p, &name, &ng)) {
		case _NG_NONE:
			/* Done with the line */
			free(line);
			return 0;

		case _NG_GROUP:
			/* new netgroup */
			i = in_check(host, user, domain, ng);
			if (ng->ng_host != NULL)
				free(ng->ng_host);
			if (ng->ng_user != NULL)
				free(ng->ng_user);
			if (ng->ng_domain != NULL)
				free(ng->ng_domain);
			free(ng);
			if (i) {
				free(line);
				return 1;
			}
			break;

		case _NG_NAME:
			/* netgroup name */
			if (in_find(ypdom, sl, name, host, user, domain)) {
				free(line);
				return 1;
			}
			break;

		case _NG_ERROR:
			free(line);
			return 0;
		}
	}
}
예제 #17
0
파일: board.c 프로젝트: joshdekock/jim-psp
BOOL makemove(move_bytes m)
{
	
	/* test to see if a castle move is legal and move the rook
	   (the king is moved with the usual move code later) */
	if (m.bits & 2) {
		int from, to;

		if (in_check(side))
			return FALSE;
		switch (m.to) {
			case 62:
				if (color[F1] != EMPTY || color[G1] != EMPTY ||
						attack(F1, xside) || attack(G1, xside))
					return FALSE;
				from = H1;
				to = F1;
				break;
			case 58:
				if (color[B1] != EMPTY || color[C1] != EMPTY || color[D1] != EMPTY ||
						attack(C1, xside) || attack(D1, xside))
					return FALSE;
				from = A1;
				to = D1;
				break;
			case 6:
				if (color[F8] != EMPTY || color[G8] != EMPTY ||
						attack(F8, xside) || attack(G8, xside))
					return FALSE;
				from = H8;
				to = F8;
				break;
			case 2:
				if (color[B8] != EMPTY || color[C8] != EMPTY || color[D8] != EMPTY ||
						attack(C8, xside) || attack(D8, xside))
					return FALSE;
				from = A8;
				to = D8;
				break;
			default:  /* shouldn't get here */
				from = -1;
				to = -1;
				break;
		}
		color[to] = color[from];
		piece[to] = piece[from];
		color[from] = EMPTY;
		piece[from] = EMPTY;
	}

	/* back up information so we can take the move back later. */
	hist_dat[hply].m.b = m;
	hist_dat[hply].capture = piece[(int)m.to];
	hist_dat[hply].castle = castle;
	hist_dat[hply].ep = ep;
	hist_dat[hply].fifty = fifty;
	++ply;
	++hply;

	/* update the castle, en passant, and
	   fifty-move-draw variables */
	castle &= castle_mask[(int)m.from] & castle_mask[(int)m.to];
	if (m.bits & 8) {
		if (side == LIGHT)
			ep = m.to + 8;
		else
			ep = m.to - 8;
	}
	else
		ep = -1;
	if (m.bits & 17)
		fifty = 0;
	else
		++fifty;

	/* move the piece */
	color[(int)m.to] = side;
	if (m.bits & 32)
		piece[(int)m.to] = m.promote;
	else
		piece[(int)m.to] = piece[(int)m.from];
	color[(int)m.from] = EMPTY;
	piece[(int)m.from] = EMPTY;

	/* erase the pawn if this is an en passant move */
	if (m.bits & 4) {
		if (side == LIGHT) {
			color[m.to + 8] = EMPTY;
			piece[m.to + 8] = EMPTY;
		}
		else {
			color[m.to - 8] = EMPTY;
			piece[m.to - 8] = EMPTY;
		}
	}

	/* switch sides and test for legality (if we can capture
	   the other guy's king, it's an illegal position and
	   we need to take the move back) */
	side ^= 1;
	xside ^= 1;
	if (in_check(xside)) {
		takeback();
		return FALSE;
	}
	return TRUE;
}
예제 #18
0
파일: search.c 프로젝트: dylhunn/fianchetto
// Unified alpha-beta and quiescence search
int abq(board *b, int alpha, int beta, int ply, int centiply_extension, bool allow_extensions, bool side_to_move_in_check) {
	if (search_terminate_requested) return 0; // Check for search termination

	int alpha_orig = alpha; // For use in later TT storage

	// Retrieve the value from the transposition table, if appropriate
	evaluation stored;
	tt_get(b, &stored);
	if (!e_eq(stored, no_eval) && stored.depth >= ply && use_ttable) {
		if (stored.type == qexact || stored.type == exact) return stored.score;
		if (stored.type == qlowerbound || stored.type == lowerbound) alpha = max(alpha, stored.score);
		else if (stored.type == qupperbound || stored.type == upperbound) beta = min(beta, stored.score);
		if (alpha >= beta) return stored.score;
	}

	// Futility pruning: enter quiescence early if the node is futile
	if (use_futility_pruning && !side_to_move_in_check && ply == 1) {
		if (relative_evaluation(b) + frontier_futility_margin < alpha) ply = 0;
	} else if (use_futility_pruning && !side_to_move_in_check && ply == 2) {
		if (relative_evaluation(b) + prefrontier_futility_margin < alpha) ply = 0;
	}

	bool quiescence = (ply <= 0);

	// Generate all possible moves for the quiscence search or normal search, and compute the
	// static evaluation if applicable.
	move *moves = NULL;
	int num_available_moves = 0;
	if (quiescence) moves = board_moves(b, &num_available_moves, true); // Generate only captures
	else moves = board_moves(b, &num_available_moves, false); // Generate all moves
	if (quiescence && !use_qsearch) {
		free(moves);
		return relative_evaluation(b); // If qsearch is turned off
	}

	// Abort if the quiescence search is too deep (currently 45 plies)
	if (ply < -quiesce_ply_cutoff) { 
		sstats.qnode_aborts++;
		free(moves);
		return relative_evaluation(b);
	}

	int quiescence_stand_pat;
	// Allow the quiescence search to generate cutoffs
	if (quiescence) {
		quiescence_stand_pat = relative_evaluation(b);
		alpha = max(alpha, quiescence_stand_pat);
		if (alpha >= beta) {
			free(moves);
			return quiescence_stand_pat;
		}
	} else if (!e_eq(stored, no_eval) && use_tt_move_hueristic) {
		assert(is_legal_move(b, stored.best)); // TODO
		// For non-quiescence search, use the TT entry as a hueristic
		moves[num_available_moves] = stored.best;
		num_available_moves++;
	}

	// Update search stats
	if (quiescence) sstats.qnodes_searched++;
	else sstats.nodes_searched++;

	// Search hueristic: sort exchanges using MVV-LVA
	if (quiescence && mvvlva) nlopt_qsort_r(moves, num_available_moves, sizeof(move), b, &capture_move_comparator);

	// Search extensions
	bool no_more_extensions = false;

	// Extend the search if we are in check
	//coord king_loc = b->black_to_move ? b->black_king : b->white_king;
	bool currently_in_check = side_to_move_in_check; //in_check(b, king_loc.col, king_loc.row, b->black_to_move);
	if (check_extend && currently_in_check && ply <= check_extend_threshold && !quiescence && allow_extensions) { // only extend in shallow non-quiescence situations 
		centiply_extension += check_extension_centiply;
		no_more_extensions = true;
	}

	// Process any extensions
	if (allow_extensions && centiply_extension >= 100) {
		centiply_extension -= 100;
		ply += 1;
	} else if (allow_extensions && centiply_extension <= -100) {
		centiply_extension += 100;
		ply -= 1;
	}

	if (no_more_extensions) allow_extensions = false; // Only allow one check extension

	move best_move_yet = no_move;
	int best_score_yet = NEG_INFINITY; 
	int num_moves_actually_examined = 0; // We might end up in checkmate
	//for (int iterations = 0; iterations < 2; iterations++) { // ABDADA iterations
		for (int i = num_available_moves - 1; i >= 0; i--) { // Iterate backwards to match MVV-LVA sort order
			/*int claimed_node_id = -1;
			if (i != num_available_moves - 1 && iterations == 1) { // Skip redundant young brothers on the first pass
				if (!tt_try_to_claim_node(b, &claimed_node_id)) continue; // Skip the node if it is already being searched
			} else tt_always_claim_node(b, &claimed_node_id);*/
			apply(b, moves[i]);
			bool we_moved_into_check;
			// Choose the more efficient version if possible
			// If we were already in check, we need to do the expensive search
			if (side_to_move_in_check) {
				coord king_loc = b->black_to_move ? b->white_king : b->black_king; // for side that just moved
				we_moved_into_check = in_check(b, king_loc.col, king_loc.row, !(b->black_to_move));
			} else we_moved_into_check = puts_in_check(b, moves[i], !b->black_to_move);
			// Never move into check
			if (we_moved_into_check) {
				unapply(b, moves[i]);
				//tt_unclaim_node(claimed_node_id);
				continue;
			}
			bool opponent_in_check = puts_in_check(b, moves[i], b->black_to_move);
			/*coord opp_king_loc = b->black_to_move ? b->black_king : b->white_king;
			bool opponent_in_check = in_check(b, opp_king_loc.col, opp_king_loc.row, (b->black_to_move));*/
			int score = -abq(b, -beta, -alpha, ply - 1, centiply_extension, allow_extensions, opponent_in_check);
			num_moves_actually_examined++;
			unapply(b, moves[i]);
			if (score > best_score_yet) {
				best_score_yet = score;
				best_move_yet = moves[i];
			}
			alpha = max(alpha, best_score_yet);
			if (alpha >= beta) {
				//tt_unclaim_node(claimed_node_id);
				break;
			}
			//tt_unclaim_node(claimed_node_id);
		}
	//}
	free(moves); // We are done with the array

	// We have no available moves (or captures) that don't leave us in check
	// This means checkmate or stalemate in normal search
	// It might mean no captures are available in quiescence search
	if (num_moves_actually_examined == 0) {
		if (quiescence) return quiescence_stand_pat; // TODO: qsearch doesn't understand stalemate or checkmate
		// This seems paradoxical, but the +1 is necessary so we pick some move in case of checkmate
		if (currently_in_check) return NEG_INFINITY + 1; // checkmate
		else return 0; // stalemate
	}

	if (quiescence && best_score_yet < quiescence_stand_pat) return quiescence_stand_pat; // TODO experimental stand pat

	if (search_terminate_requested) return 0; // Search termination preempts tt_put

	// Record the selected move in the transposition table
	evaltype type;
	if (best_score_yet <= alpha_orig) type = (quiescence) ? qupperbound : upperbound;
	else if (best_score_yet >= beta) type = (quiescence) ? qlowerbound : lowerbound;
	else type = (quiescence) ? qexact : exact;
	evaluation eval = {.best = best_move_yet, .score = best_score_yet, .type = type, .depth = ply};
	tt_put(b, eval);
	return best_score_yet;
}
예제 #19
0
int generate_moves(Move *movelist)
{
    int horizontal2 = turn_to_move == WHITE? 8 : 3;
    int horizontal7 = turn_to_move == WHITE? 3 : 8;
    int direction_of_pawns = turn_to_move == WHITE? -10: 10;
    int captures_of_pawns[2] = {direction_of_pawns + 1, direction_of_pawns - 1};
    int place_of_king = turn_to_move == WHITE? place_of_white_king:
                                               place_of_black_king;
    int n = 0;
    
    int king_castling, queen_castling;
    if(turn_to_move == WHITE)
    {
        king_castling  = ply->castlings & K_castling;
        queen_castling = ply->castlings & Q_castling;
    }
    else
    {
        king_castling  = ply->castlings & k_castling;
        queen_castling = ply->castlings & q_castling;
    }
    int is_in_check = in_check(turn_to_move);
    for(int i = 0; i < 8; i += 1)
    {
        int i_move = moves_of_king[i];
        int tmp = place_of_king + i_move;
        if(board[tmp] == EMPTY || get_color(board[tmp]) == not_turn_to_move)
        {
            int i_move_is_possible = 0;
            Move tmp_move = create_move(place_of_king, tmp, board[tmp], 0);
            make_move(tmp_move);
            if(!in_check(not_turn_to_move))
            {
                i_move_is_possible = 1;
                movelist[n] = tmp_move;
                n += 1;
            }
            unmake_move(tmp_move);
            
            if(is_in_check || !i_move_is_possible || board[tmp] != EMPTY)
                continue;
            if(i_move == 1 && king_castling && board[place_of_king + 2] == EMPTY)
            {
                movelist[n] = create_move(place_of_king, place_of_king + 2, 0, 0);
                n += 1;
            }
            if(i_move == -1 && queen_castling &&
               board[place_of_king - 2] == EMPTY &&
               board[place_of_king - 3] == EMPTY)
            {
                movelist[n] = create_move(place_of_king, place_of_king - 2, 0, 0);
                n += 1;
            }
        }
    }
    
    if(ply->en_passant)
    {
        for(int i = 0; i < 2; i += 1)
        {
            int tmp = ply->en_passant - captures_of_pawns[i];
            if(board[tmp] == create_figure(turn_to_move, PAWN))
            {
                movelist[n] = create_move(tmp, ply->en_passant, 0, 0);
                n += 1;
            }
        }
    }
    for(int i64 = 0; i64 < 64; i64 += 1)
    {
        int current_cell = board64[i64];
        int figure = board[current_cell];
        if(get_color(figure) != turn_to_move)
            continue;
        switch(get_value(figure))
        {
            case QUEEN:
                for(int i = 0; i < 8; i += 1)
                {
                    int inc = directions_of_queen[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                    {
                        movelist[n] = create_move(current_cell, x, 0, 0);
                        n += 1;
                        x += inc;
                    }
                    if(get_color(board[x]) == not_turn_to_move )
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case ROOK:
                for(int i = 0; i < 4; i += 1)
                {
                    int inc = directions_of_rook[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                    {
                        movelist[n] = create_move(current_cell, x, 0, 0);
                        n += 1;
                        x += inc;
                    }
                    if(get_color(board[x]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case BISHOP:
                for(int i = 0; i < 4; i += 1)
                {
                    int inc = directions_of_bishop[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                    {
                        movelist[n] = create_move(current_cell, x, 0, 0);
                        n += 1;
                        x += inc;
                    }
                    if(get_color(board[x]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case KNIGHT:
                for(int i = 0; i < 8; i += 1)
                {
                    int tmp = current_cell + moves_of_knight[i];
                    if(board[tmp] == EMPTY ||
                        get_color(board[tmp]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, tmp, board[tmp], 0);
                        n += 1;
                    }
                }
                break;
            case PAWN:
                ;int tmp = current_cell + direction_of_pawns;
                if(board[tmp] == EMPTY)
                {
                    if(current_cell/10 == horizontal7)
                    {
                        for(int j = 0; j < 4; j += 1)
                        {
                            movelist[n] = create_move(current_cell, tmp, 0,
                                create_figure(turn_to_move, turn_figures[j]));
                            n += 1;
                        }
                    }
                    else
                    {
                        movelist[n] = create_move(current_cell, tmp, 0, 0);
                        n += 1;
                    }
                    tmp += direction_of_pawns;
                    if(board[tmp] == EMPTY && current_cell/10 == horizontal2)
                    {
                        movelist[n] = create_move(current_cell, tmp, 0, 0);
                        n += 1;
                    }
                }
                for(int i = 0; i < 2; i += 1)
                {
                    int tmp = current_cell + captures_of_pawns[i];
                    if(get_color(board[tmp]) == not_turn_to_move)
                    {
                        if(current_cell/10 == horizontal7)
                        {
                            for(int j = 0; j < 4; j += 1)
                            {
                                movelist[n] = create_move(current_cell, tmp, board[tmp],
                                    create_figure(turn_to_move, turn_figures[j]));
                                n += 1;
                            }
                        }
                        else
                        {
                            movelist[n] = create_move(current_cell, tmp, board[tmp], 0);
                            n += 1;
                        }
                    }
                }
        }
    }
    for(int i = 0; i < n; i += 1)
    {
        Move i_move = movelist[i];
        make_move(i_move);
        if(in_check(not_turn_to_move))
        {
            movelist[i] = movelist[n - 1];
            n -= 1;
            i -= 1;
        }
        unmake_move(i_move);
    }
    return n;
}
예제 #20
0
int generate_captures(Move *movelist)
{
    int horizontal2 = turn_to_move == WHITE? 8 : 3;
    int horizontal7 = turn_to_move == WHITE? 3 : 8;
    int direction_of_pawns = turn_to_move == WHITE? -10: 10;
    int captures_of_pawns[2] = {direction_of_pawns + 1, direction_of_pawns - 1};
    int place_of_king = turn_to_move == WHITE? place_of_white_king:
                                               place_of_black_king;
    int n = 0;
    
    for(int i = 0; i < 8; i += 1)
    {
        int tmp = place_of_king + moves_of_king[i];
        if(get_color(board[tmp]) == not_turn_to_move)
        {
            movelist[n] = create_move(place_of_king, tmp, board[tmp], 0);
            n += 1;
        }
    }
    for(int i64 = 0; i64 < 64; i64 += 1)
    {
        int current_cell = board64[i64];
        int figure = board[current_cell];
        if(get_color(figure) != turn_to_move)
            continue;
        switch(get_value(figure))
        {
            case QUEEN:
                for(int i = 0; i < 8; i += 1)
                {
                    int inc = directions_of_queen[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                        x += inc;
                    if(get_color(board[x]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case ROOK:
                for(int i = 0; i < 4; i += 1)
                {
                    int inc = directions_of_rook[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                        x += inc;
                    if(get_color(board[x]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case BISHOP:
                for(int i = 0; i < 4; i += 1)
                {
                    int inc = directions_of_bishop[i];
                    int x = current_cell + inc;
                    while(board[x] == EMPTY)
                        x += inc;
                    if(get_color(board[x]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, x, board[x], 0);
                        n += 1;
                    }
                }
                break;
            case KNIGHT:
                for(int i = 0; i < 8; i += 1)
                {
                    int tmp = current_cell + moves_of_knight[i];
                    if(get_color(board[tmp]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, tmp, board[tmp], 0);
                        n += 1;
                    }
                }
                break;
            case PAWN:
                for(int i = 0; i < 2; i += 1)
                {
                    int tmp = current_cell + captures_of_pawns[i];
                    if(get_color(board[tmp]) == not_turn_to_move)
                    {
                        movelist[n] = create_move(current_cell, tmp, board[tmp], 0);
                        n += 1;
                    }
                }
        }
    }
    for(int i = 0; i < n; i += 1)
    {
        Move i_move = movelist[i];
        make_move(i_move);
        if(in_check(not_turn_to_move))
        {
            movelist[i] = movelist[n - 1];
            n -= 1;
            i -= 1;
        }
        unmake_move(i_move);
    }
    return n;
}
예제 #21
0
파일: move.c 프로젝트: cxd4/chess
int is_legal_move(int x1, int y1, int x2, int y2)
{
    square backup;
    double slope, distance;
    int a, b;
    int putting_yourself_in_check;
    register int xt, yt;
    const double infinity = (double)(BOARD_SIZE - 0) / (double)(1 - 0);
    const int moving_piece_color = get_player_by_square(x1, y1);
    const int target_piece_color = get_player_by_square(x2, y2);

/*
 * If either the starting or ending squares lie outside the legal boundary of
 * the board, then obviously the move cannot be legal.
 */
    if (x1 < 0 || x1 >= BOARD_SIZE)
        return 0;
    if (y1 < 0 || y1 >= BOARD_SIZE)
        return 0;
    if (x2 < 0 || x2 >= BOARD_SIZE)
        return 0;
    if (y2 < 0 || y2 >= BOARD_SIZE)
        return 0;

    if (board[y1][x1] == BLANK_SQUARE)
        return 0; /* can move to no squares, from an empty square */

    if (game_state.player_turn != moving_piece_color)
        return 0; /* White can't command Black pieces, and vice versa. */
    if (board[y2][x2] != BLANK_SQUARE)
        if (target_piece_color == moving_piece_color)
            return 0; /* Nobody can capture pieces of their own color. */

    a = x2 - x1; /* horizontal leg, if any */
    b = y2 - y1; /* vertical leg, if any */
    distance = sqrt(a*a + b*b); /* vector resultant, if not also hypotenuse */

    if (distance == 0)
        return 0; /* null move */

    if (a == 0)
        slope = (b < 0) ? -infinity : +infinity;
    else
        slope = (double)b / (double)a;

    switch (board[y1][x1])
    {
    default: /* probably intended as a blank square, except not BLANK_SQUARE */
        return 0;

    case WHITE_KING:
    case BLACK_KING:
        if (distance == 1) /* up, down, right, left by one */
            break;
        if (distance == sqrt(2)) /* diagonally by one */
            break;
        if (distance == 2 && y2 == y1 && x1 == e) { /* castling from rank e */
            if (in_check(game_state.player_turn))
                return 0; /* Castling out of check is illegal. */

            if (board[y1][x1] == WHITE_KING && y1 == 0) {
                if (game_state.castling.K && x2 == g) {
                    if (test_King(f, 0) | test_Queen(f, 0) | test_knight(f, 0))
                        return 0; /* Castling "through" check is illegal. */
                    if (SQUARE(f1) == BLANK_SQUARE)
                        break;
                }
                if (game_state.castling.Q && x2 == c) {
                    if (test_King(d, 0) | test_Queen(d, 0) | test_knight(d, 0))
                        return 0;
                    if (SQUARE(d1) == BLANK_SQUARE && SQUARE(b1) == BLANK_SQUARE)
                        break;
                }
            } else if (board[y1][x1] == BLACK_KING && y1 == BOARD_SIZE - 1) {
                if (game_state.castling.k && x2 == g) {
                    if (test_King(f, 7) | test_Queen(f, 7) | test_knight(f, 7))
                        return 0; /* Castling "through" check is illegal. */
                    if (SQUARE(f8) == BLANK_SQUARE)
                        break;
                }
                if (game_state.castling.q && x2 == c) {
                    if (test_King(d, 7) | test_Queen(d, 7) | test_knight(d, 7))
                        return 0;
                    if (SQUARE(d8) == BLANK_SQUARE && SQUARE(b8) == BLANK_SQUARE)
                        break;
                }
            }
        }
        return 0;

    case WHITE_QUEEN:
    case BLACK_QUEEN:
        if (slope == -1 || slope == +1)
            goto bishop_testing;
        if (slope != -infinity && slope != +infinity && slope != 0)
            return 0; /* not a legal rook move */
     /* Fall through. */

    case WHITE_ROOK:
    case BLACK_ROOK:
        if (y2 == y1) {
            if (x2 < x1) /* destination to the left of the rook */
                for (xt = x1 - 1; xt > x2; xt--) {
                    if (board[y2][xt] == BLANK_SQUARE)
                        continue;
                    return 0;
                }
            else /* destination to the right of the rook */
                for (xt = x1 + 1; xt < x2; xt++) {
                    if (board[y2][xt] == BLANK_SQUARE)
                        continue;
                    return 0;
                }
            break;
        } else if (x2 == x1) {
            if (y2 < y1) /* destination downwards from the rook */
                for (yt = y1 - 1; yt > y2; yt--) {
                    if (board[yt][x2] == BLANK_SQUARE)
                        continue;
                    return 0;
                }
            else /* destination upwards from the rook */
                for (yt = y1 + 1; yt < y2; yt++) {
                    if (board[yt][x2] == BLANK_SQUARE)
                        continue;
                    return 0;
                }
            break;
        } else
            return 0;

    case WHITE_BISHOP:
    case BLACK_BISHOP:
    bishop_testing:
        if (slope != +1 && slope != -1)
            return 0;
        if (y2 > y1 && x2 > x1) /* quadrant I, range check to upper-right */
            for (xt = x1 + 1, yt = y1 + 1; xt < x2 && yt < y2; xt++, yt++)
                if (board[yt][xt] != BLANK_SQUARE)
                    return 0;
        if (y2 > y1 && x2 < x1) /* quadrant II, range check to upper-left */
            for (xt = x1 - 1, yt = y1 + 1; xt > x2 && yt < y2; xt--, yt++)
                if (board[yt][xt] != BLANK_SQUARE)
                    return 0;
        if (y2 < y1 && x2 < x1) /* quadrant III, range check to lower-left */
            for (xt = x1 - 1, yt = y1 - 1; xt > x2 && yt > y2; xt--, yt--)
                if (board[yt][xt] != BLANK_SQUARE)
                    return 0;
        if (y2 < y1 && x2 > x1) /* quadrant IV, range check to lower-right */
            for (xt = x1 + 1, yt = y1 - 1; xt < x2 && yt > y2; xt++, yt--)
                if (board[yt][xt] != BLANK_SQUARE)
                    return 0;
        break;

    case WHITE_KNIGHT:
    case BLACK_KNIGHT:
        if (distance == sqrt(5))
            break;
        return 0;

    case WHITE_PAWN:
        if (distance == 2) /* optional pawn push from start position */
            if (y2 == y1 + 2 && board[y2][x2] == BLANK_SQUARE)
                if (y1 == -1 + 2 && board[y1 + 1][x1] == BLANK_SQUARE)
                    break;
        if (distance == 1) /* pawn advances, without capture */
            if (y2 == y1 + 1 && board[y2][x2] == BLANK_SQUARE)
                break;
        if (distance == sqrt(2)) /* pawn captures */
            if (y2 == y1 + 1)
                if (board[y2][x2] != BLANK_SQUARE
                 || (game_state.en_passant_file == x2 && y2 == BOARD_SIZE - 3))
                    break;
        return 0;
    case BLACK_PAWN:
        if (distance == 2) /* optional pawn push from start position */
            if (y2 == y1 - 2 && board[y2][x2] == BLANK_SQUARE)
                if (y1 == BOARD_SIZE - 2 && board[y1 - 1][x1] == BLANK_SQUARE)
                    break;
        if (distance == 1)
            if (y2 == y1 - 1 && board[y2][x2] == BLANK_SQUARE)
                break;
        if (distance == sqrt(2)) /* pawn captures */
            if (y2 == y1 - 1)
                if (board[y2][x2] != BLANK_SQUARE
                 || (game_state.en_passant_file == x2 && y2 == -1 + 3))
                    break;
        return 0;
    }

/*
 * Finally, is the moving player putting himself in check with this move?
 * This we will test by temporarily executing the move on the board.
 *
 * In ancient chess, exposing one's King is a legal move, so this code could
 * be deleted actually for a theoretically faster analysis.
 */
    backup = board[y2][x2];
    board[y2][x2] = board[y1][x1];
    board[y1][x1] = BLANK_SQUARE;
    putting_yourself_in_check = in_check(moving_piece_color);

    board[y1][x1] = board[y2][x2];
    board[y2][x2] = backup;
    if (putting_yourself_in_check)
        return 0;

    return 1;
}
예제 #22
0
int search(int alpha, int beta, int depth)
{
    int i, j, x;
    BOOL c, f;

    /* we're as deep as we want to be; call quiesce() to get
       a reasonable score and return it. */
    if (!depth)
        return quiesce(alpha,beta);
    ++nodes;

    /* do some housekeeping every 1024 nodes */
    if ((nodes & 1023) == 0)
        checkup();

    pv_length[ply] = ply;

    /* if this isn't the root of the search tree (where we have
       to pick a move and can't simply return 0) then check to
       see if the position is a repeat. if so, we can assume that
       this line is a draw and return 0. */
    if (ply && reps())
        return 0;

    /* are we too deep? */
    if (ply >= MAX_PLY - 1)
        return eval();
    if (hply >= HIST_STACK - 1)
        return eval();

    /* are we in check? if so, we want to search deeper */
    c = in_check(side);
    if (c)
        ++depth;
    gen();
    if (follow_pv)  /* are we following the PV? */
        sort_pv();
    f = FALSE;

    /* loop through the moves */
    for (i = first_move[ply]; i < first_move[ply + 1]; ++i) {
        sort(i);
        if (!makemove(gen_dat[i].m.b))
            continue;
        f = TRUE;
        x = -search(-beta, -alpha, depth - 1);
        takeback();
        if (x > alpha) {

            /* this move caused a cutoff, so increase the history
               value so it gets ordered high next time we can
               search it */
            history[(int)gen_dat[i].m.b.from][(int)gen_dat[i].m.b.to] += depth;
            if (x >= beta)
                return beta;
            alpha = x;

            /* update the PV */
            pv[ply][ply] = gen_dat[i].m;
            for (j = ply + 1; j < pv_length[ply + 1]; ++j)
                pv[ply][j] = pv[ply + 1][j];
            pv_length[ply] = pv_length[ply + 1];
        }
    }

    /* no legal moves? then we're in checkmate or stalemate */
    if (!f) {
        if (c)
            return -10000 + ply;
        else
            return 0;
    }

    /* fifty move draw rule */
    if (fifty >= 100)
        return 0;
    return alpha;
}
예제 #23
0
/*
Aggiorna la scacchiera e le altre strutture dati eseguendo la mossa
La verifica di legalita' viene effettuata quando:
-la mossa è una mossa di re
-il re è sotto scacco
-il re è sotto attacco x-ray
*/
int makemove(const MOVE m, const unsigned char s) {

	unsigned char from=0; /*da dove parte il pezzo*/
	unsigned char to=0; /*dove copiare il pezzo*/
	char was=0; /*cosa era il pezzo?*/
	char wh=0;
	unsigned char del=0; /*dove cancellare*/

	assert(Name(WHITE,0)==king);
	assert(Name(BLACK,0)==king);

	

	if (Piece(m.ms.to)==king) return 0;

	/*copia la chiave hash per l'unmake()*/
	BHash(N_moves) = Hash;

	/*copia la castle_exe per l'unmake()*/
	BCste(N_moves) = Cste;

	/*copia la bitboard per l'unmake()*/
	BBitb(N_moves, Side) = Bitboard(Side);


	/*Controlla che l'arrocco sia legale e sposta la torre
*/
	if (m.ms.flag & (M_OO | M_OOO)) {
			if (tree.check[Side][Ply])
				return 0;

			switch (m.ms.to) {
					case C8:

						if (attacked(C8, WHITE) || attacked(D8, WHITE))
							return 0;
						from = A8;
						to = D8;
						Cste |= cas_booo;
						break;

					case G8:
						if (attacked(F8, WHITE) || attacked(G8, WHITE))
							return 0;
						from = H8;
						to = F8;
						Cste |= cas_boo;
						break;

					case C1:
						if (attacked(C1, BLACK) || attacked(D1, BLACK))
							return 0;
						from = A1;
						to = D1;
						Cste |= cas_wooo;
						break;

					case G1:
						if (attacked(F1, BLACK) || attacked(G1, BLACK))
							return 0;
						from = H1;
						to = F1;
						Cste |= cas_woo;
						break;

					default:
						puts("Bad castle request.");
						assert(0);
					}
			/*sposta torre aggiornando la chiave hash*/
			UpdateHash(from);

			Piece(to) = Piece(from);

			Color(to) = Color(from);

			Plist(to) = Plist(from);

			Position((Color(to)), (Plist(to))) = to;

			Piece(from) = no_piece;

			Color(from) = EMPTY;

			Plist(from) = no_list;

			UpdateHash(to);

			SetBB(Side, to);

			DelBB(Side, from);
			}
	/*sposta il pezzo*/
	from = m.ms.from;

	to = m.ms.to;

	was = Piece(from);

	wh = Plist(from);
	assert(was>=0);
	assert(was<=king);

	assert(Name(Side,0)==king);
	assert(Name(Xside,0)==king);
	if (wh>0){
		assert(Name(Side,wh)!=king);
	}

	

	/*Se la mossa e' una cattura cancella il pezzo dalla casella di arrivo*/
	if (m.ms.flag & M_CAP) {
			del = to;

			/*se è una cattura en passant aggiustiamo casella*/
			if (m.ms.flag & M_ENP) {
					if (Side)
						del += DOWN;
					else
						del += UP;
			}

			

			BCapP(N_moves) = Piece(del);
			BCapPos(N_moves) = Plist(del);
			BCapC(N_moves) = Xside;
			BBitb(N_moves, Xside) = Bitboard(Xside);
			Active(Xside, (Plist(del))) = CAPTURED;
			Piece(del) = no_piece;
			Color(del) = EMPTY;
			Plist(del) = no_list;
			DelBB(Xside, del);
			}

	Piece(to) = Piece(from);
	if (m.ms.piece!=was)Piece(to)=m.ms.piece;
	Color(to) = Side;
	Plist(to) = wh;
	Position((Side), (wh)) = to;
	Piece(from) = no_piece;
	Color(from) = EMPTY;
	Plist(from) = no_list;
	SetBB(Side, to);
	DelBB(Side, from);
	/*effettuato il minimo indispensabile verifica, se opportuno, la legalità della mossa*/
	
	assert(Name(Side,0)==king);
	assert(Name(Xside,0)==king);
	if (wh>0){
		assert(Name(Side,wh)!=king);
	}
	

	if ( tree.verify[Ply] || tree.check[Side][Ply] || (m.ms.flag & M_KNG) ||(m.ms.flag & M_ENP)) {
			if (in_check(Side)) {
					/*unmake() locale*/
					Piece(from) = Piece(to);
					if (Piece(from)!=was)Piece(from)=was;
					Color(from) = Side;
					Plist(from) = wh;
					Position((Side), (wh)) = from;
					Piece(to) = no_piece;
					Color(to) = EMPTY;
					Plist(to) = no_list;
					Bitboard(Side) = BBitb(N_moves, Side);

					if (m.ms.flag & M_CAP) {
							Piece(del) = BCapP(N_moves);
							Color(del) = BCapC(N_moves);
							Plist(del) = BCapPos(N_moves);
							Active((Xside), (Plist(del))) = FREE;
							Position((Xside), (Plist(del))) = del;
							Bitboard(Xside) = BBitb(N_moves, Xside);
							assert(Name(Side,0)==king);
							assert(Name(Xside,0)==king);
							if (Plist(del)>0){
								assert(Name(Xside,Plist(del))!=king);
								}
							}
					assert(Name(Side,0)==king);
					assert(Name(Xside,0)==king);
					if (wh>0){
						assert(Name(Side,wh)!=king);
						}
					return 0;
					}

			}
	/*Selectivity*/
	if (s && ((!in_check(Xside)) || ((m.ms.flag& M_CAP)==0))) {
		/*unmake() locale*/
					Piece(from) = Piece(to);
					if (Piece(from)!=was)Piece(from)=was;
					Color(from) = Side;
					Plist(from) = wh;
					Position((Side), (wh)) = from;
					Piece(to) = no_piece;
					Color(to) = EMPTY;
					Plist(to) = no_list;
					Bitboard(Side) = BBitb(N_moves, Side);

					if (m.ms.flag & M_CAP) {
							Piece(del) = BCapP(N_moves);
							Color(del) = BCapC(N_moves);
							Plist(del) = BCapPos(N_moves);
							Active((Xside), (Plist(del))) = FREE;
							Position((Xside), (Plist(del))) = del;
							Bitboard(Xside) = BBitb(N_moves, Xside);
							assert(Name(Side,0)==king);
							assert(Name(Xside,0)==king);
							if (Plist(del)>0){
								assert(Name(Xside,Plist(del))!=king);
								}
							}
					assert(Name(Side,0)==king);
					assert(Name(Xside,0)==king);
					if (wh>0){
						assert(Name(Side,wh)!=king);
						}
					return 0;
		}
	/*back up per l'unmakemove()
	i dati per la cattura e la hash della posizione sono gia' memorizzati*/
	tree.history[N_moves].m.mi = m.mi;
	tree.history[N_moves].cast.castle_right = Cstr;
	tree.history[N_moves].enp = Enp;
	tree.history[N_moves].fifty = tree.fifty;
	tree.history[N_moves].was = was;
	tree.history[N_moves].material[Side] = Material(Side);
	tree.history[N_moves].material[Xside] = Material(Xside);
	BPBitb(N_moves, Side) = Pbitboard(Side);
	BPBitb(N_moves, Xside) = Pbitboard(Xside);

	/*aggiorna diritti arrocco*/
	UpdateHashCastle(Cstr);
	Cstr &= castle_mask[b256to64[from]] & castle_mask[b256to64[to]];
	UpdateHashCastle(Cstr);

	Hash ^= zobrist_enp[b256to64[Enp]];
	Enp = 0;
	tree.fifty++;
	/*se irreversibile...*/

	if (m.ms.flag&(M_PAW | M_CAP)) {
			tree.fifty = 0;
			

			if (m.ms.flag&M_DBP) {
					if (Side)
						Enp = to + DOWN;
					else
						Enp = to + UP;
					}

			if (m.ms.flag&M_PAW) {
					DelPBB(Side, from);

					if ((m.ms.flag&M_PRO) == 0)
						SetPBB(Side, to);
					}

			if (m.ms.flag&M_CAP) {
					tree.history[N_moves].del = del;
					Hash ^= zobrist[Xside][BCapP(N_moves)][b256to64[del]];
					Material(Xside) -= piece_value[BCapP(N_moves)];
					Num_piece(Xside, BCapP(N_moves))--;
					Pbitboard(Xside) &= (~(bit_square[del]));
					}

			Material(Side) -= piece_value[was];
			Material(Side) += piece_value[m.ms.piece];
			Num_piece(Side, was)--;
			Num_piece(Side, m.ms.piece)++;
			}

	Hash ^= zobrist_enp[b256to64[Enp]];

	Hash ^= zobrist[Side][was][b256to64[from]];
	Hash ^= zobrist[Side][m.ms.piece][b256to64[to]];
	Hash ^= zobrist_side;



	Ply++;
	N_moves++;

	Change(Side);
	Change(Xside);

	assert(Name(WHITE,0)==king);
	assert(Name(BLACK,0)==king);

	return 1;

	}
예제 #24
0
/* print_result() checks to see if the game is over */
void print_result()
{
	int i;

	/* is there a legal move? */
	for (i = 0; i < first_move[1]; ++i) {
		if (makemove(gen_dat[i].m.b)) {
			takeback();
			break;
		}
	}

	if (i == first_move[1]) {
		if (in_check(side)) {
			if (side == LIGHT) {
				printf("GR_RGB(0,0,0) mates");
				if (is_mini) {
					draw_message("GR_RGB(0,0,0)","Mates");
				}
				else {
					pz_draw_header("GR_RGB(0,0,0) mates");
				}
				draw_end('b');
			}
			else {
				printf("GR_RGB(255,255,255) mates");
				if (is_mini) {
					draw_message("GR_RGB(255,255,255)","Mates");
				}
				else {
					pz_draw_header("GR_RGB(255,255,255) mates");
				}
				draw_end('w');
			}
		}
		else {
			printf("Stalemate");
			if (is_mini) {
				draw_message("Stale","Mate");
			}
			else {
				pz_draw_header("Stalemate");
			}
			draw_end('d');
		}
	}
/*
	else if (reps() == 3)
	{
		printf("Draw by repetition");
		if (is_mini == 0)
			pz_draw_header("Draw by repetition");
		draw_end('d');
	}
*/
	else if (fifty >= 100) {
		printf("Draw by fifty move rule");
		if (is_mini == 0) {
			pz_draw_header("Draw : fifty moves");
		}
		draw_end('d');
	}
}
예제 #25
0
// 利きのある場所への取れない近接王手からの3手詰め
Move Position::weak_mate_n_ply(int ply) const
{
	// 1手詰めであるならこれを返す
	Move m = mate1ply();
	if (m)
		return m;

	// 詰まない
	if (ply <= 1)
		return MOVE_NONE;

	Color us = side_to_move();
	Color them = ~us;
	Bitboard around8 = kingEffect(king_square(them));

	// const剥がし
	Position* This = ((Position*)this);

	StateInfo si;
	StateInfo si2;

	// 近接王手で味方の利きがあり、敵の利きのない場所を探す。
	for (auto m : MoveList<CHECKS>(*this))
	{
		// 近接王手で、この指し手による駒の移動先に敵の駒がない。
		Square to = to_sq(m);
		if ((around8 & to)

#ifndef LONG_EFFECT_LIBRARY
			// toに利きがあるかどうか。mが移動の指し手の場合、mの元の利きを取り除く必要がある。
			&& (is_drop(m) ? effected_to(us, to) : (attackers_to(us, to, pieces() ^ from_sq(m)) ^ from_sq(m)))

			// 敵玉の利きは必ずtoにあるのでそれを除いた利きがあるかどうか。
			&& (attackers_to(them,to,pieces()) ^ king_square(them))
#else
			&& (is_drop(m) ? effected_to(us, to) :
					board_effect[us].effect(to) >= 2 ||
					(long_effect.directions_of(us, from_sq(m)) & Effect8::directions_of(from_sq(m), to)) != 0)

			// 敵玉の利きがあるので2つ以上なければそれで良い。
			&& (board_effect[them].effect(to) <= 1)
#endif
			)
		{
			if (!legal(m))
				continue;

			ASSERT_LV3(gives_check(m));

			This->do_move(m,si,true);

			ASSERT_LV3(in_check());

			// この局面ですべてのevasionを試す
			for (auto m2 : MoveList<EVASIONS>(*this))
			{
				if (!legal(m2))
					continue;

				// この指し手で逆王手になるなら、不詰めとして扱う
				if (gives_check(m2))
					goto NEXT_CHECK;

				This->do_move(m2, si2, false);

				ASSERT_LV3(!in_check());

				if (!weak_mate_n_ply(ply-2))
				{
					// 詰んでないので、m2で詰みを逃れている。
					This->undo_move(m2);
					goto NEXT_CHECK;
				}

				This->undo_move(m2);
			}

			// すべて詰んだ
			This->undo_move(m);

			// mによって3手で詰む。
			return m;

		NEXT_CHECK:;
			This->undo_move(m);
		}
	}
	return MOVE_NONE;
}
예제 #26
0
score_t search_ab(boost::shared_ptr<search_info> proc_info)
{
    if(proc_info->get_abort())
        return bad_min_score;
    // Unmarshall the info struct
    node_t board = proc_info->board;
    const int depth = proc_info->depth;
    if(depth != board.depth) {
      std::cout << "depth=" << depth << "board.depth=" << board.depth << std::endl;
    }
    assert(depth == board.depth);
    score_t alpha = proc_info->alpha;
    score_t beta = proc_info->beta;
    assert(depth >= 0);
    
    std::ostringstream strB;
    print_board(board, strB, true);
    std::string strBoard = strB.str();
    
    // if we are a leaf node, return the value from the eval() function
    if (depth == 0)
    {
        evaluator ev;
        DECL_SCORE(s,ev.eval(board, chosen_evaluator),board.hash);
        return s;
    }


    /* if this isn't the root of the search tree (where we have
       to pick a chess_move and can't simply return 0) then check to
       see if the position is a repeat. if so, we can assume that
       this line is a draw and return 0. */
    if (board.ply && reps(board)==3) {
        DECL_SCORE(z,0,board.hash);
        proc_info->draw = true;
        return z;
    }

    // fifty chess_move draw rule
    if (board.fifty >= 100) {
        DECL_SCORE(z,0,board.hash);
        proc_info->draw = true;
        return z;
    }


    score_t max_val = bad_min_score;
    score_t p_board = board.p_board;
    score_t zlo = bad_min_score,zhi = bad_max_score;
    bool white =board.side == LIGHT;
    bool entry_found = false;
    int excess =0;
    bool exact = false;
    if (white && board.root_side == LIGHT && db_on && board.ply > 0 && !proc_info->quiescent){
      entry_found = dbase.get_transposition_value (board, zlo, zhi, white,p_board,excess,exact,board.depth);
      int pe = proc_info->excess;
      if (excess > proc_info->excess){
        proc_info->excess = excess;
        //if (!board.follow_capt && search_method == MTDF)
        board.follow_capt = true;
      }
      else{
        //board.follow_depth = 0;
      }
      if(entry_found && excess > 0) {
        assert(depth == board.depth);
        std::cout << "excess = " << (excess+depth) << std::endl;
        zhi = bad_max_score;
        verify(strBoard,board.side,depth+excess,board.castle,board.ep,zlo,bad_max_score);
      }
    }
      
    if (entry_found){
      return zlo;
    }
   
    if(!entry_found) {
      entry_found = get_transposition_value (board, zlo, zhi);

      if(!entry_found && db_on && board.side == LIGHT){
        entry_found = dbase.get_transposition_value(board,zlo,zhi,white,p_board,excess,true,depth);
        verify(strBoard,board.side,depth,board.castle,board.ep,zlo,zhi);
      }
    }

    if (entry_found) {
        if(zlo >= beta) {
            return zlo;
        }
        if(alpha >= zhi) {
            return zhi;
        }
        alpha = max(zlo,alpha);
        beta  = min(zhi,beta);
    }
    
    if(alpha >= beta) {
        //proc_info->stop=false;
        //deeper= false;
        return alpha;
    }

    const score_t alpha0 = alpha;

    std::vector<chess_move> workq;
    std::vector<chess_move> max_move;
    

    gen(workq, board); // Generate the moves

#ifdef PV_ON
    if(!proc_info->use_srand)
      proc_info->incr = rand();
    proc_info->use_srand = false;
    srand(proc_info->incr);
    sort_pv(workq, board.depth); // Part of iterative deepening
#endif

    const int worksq = workq.size();
    std::vector<boost::shared_ptr<task> > tasks;

    int j=0;
    score_t val;
    bool aborted = false;
    bool children_aborted = false;
    // loop through the moves
    //for (; j < worksq; j++) 
    while(j < worksq) {
        while(j < worksq) {
            chess_move g = workq[j++];

            boost::shared_ptr<search_info> child_info{new search_info(board)};
            bool parallel;
            if (!aborted && !proc_info->get_abort() && makemove(child_info->board, g)) {
            
                parallel = j > 0 && !capture(board,g);
                boost::shared_ptr<task> t = parallel_task(depth, &parallel);

                t->info = child_info;
                int d = depth - 1;
                if(!test_alphabeta && d == 0 && capture(board,g)) {
                  d = 1;
                  /*
                  if(!proc_info->quiescent) {
                    t->info->alpha = bad_min_score;
                    t->info->beta = bad_max_score;
                  }
                  */
                  t->info->quiescent = true;
                } else if(proc_info->quiescent) {
                  t->info->quiescent = true;
                }
                t->info->board.depth = child_info->depth = d;
                assert(depth >= 0);
                t->info->alpha = -beta;
                t->info->beta = -alpha;
                t->info->mv = g;
                t->pfunc = search_ab_f;
                t->start();
                tasks.push_back(t);

                // Control branching
                if (!parallel)
                    break;
                /*
                else if (beta >= max_score*.9)
                    continue;
                    */
                else if (tasks.size() < 5)
                    continue;
                else
                    break;
            }
        }

        When when(tasks);
        size_t const count = tasks.size();
        for(size_t n_=0;n_<count;n_++) {
            int n = when.any();
            boost::shared_ptr<task> child_task = tasks[n];
            //assert(child_task.valid());
            child_task->join();
            
            boost::shared_ptr<search_info> child_info = child_task->info;
            
            tasks.erase(tasks.begin()+n);

            if(!children_aborted && (aborted || child_info->get_abort())) {
                for(unsigned int m = 0;m < tasks.size();m++) {
                     tasks[m]->info->set_abort(true);
                }
                children_aborted = true;
            }

            //child_task->join();
            if(child_info->get_abort()) 
                continue;
            
            if(child_info->draw)
              proc_info->draw = true;

            val = -child_info->result;
            proc_info->log << " " << child_info->mv << "=" << val;

            bool found = false; 
            if (child_info->excess > proc_info->excess){
              proc_info->excess = child_info->excess;
              found = true;
              if (!board.follow_capt){
                board.follow_capt = true;
              }
            }
            
            if (val > max_val || found ) {
                max_move.clear();
                max_move.push_back(child_info->mv); 
                if (val > max_val)
                  max_val = val;
                if (val > alpha)
                {
                    alpha = val;
#ifdef PV_ON
                    if(!child_info->get_abort())
                        ;//pv[board.search_depth - 1].set(child_info->mv);
#endif
                    if(alpha >= beta) {
                      //aborted = true;
                      j += worksq;
                      continue;
                    }
                }
            } else if(val == max_val && proc_info->excess == 0) {
              max_move.push_back(child_info->mv);
            }
        }
        if(alpha >= beta) {
            j += worksq;
            break;
        }
    
    }
    // no legal moves? then we're in checkmate or stalemate
    if (max_move.size()==0) {
        if (in_check(board, board.side))
        {
            DECL_SCORE(s,max_score,board.hash);
            return s;
       }
        else
        {
            DECL_SCORE(z,0,board.hash);
            return z;
        }
    }
    if(db_on) {
      if (board.ply == 0 || board.depth>0) {
        assert(max_move.size() != 0);
        ScopedLock s(cmutex);
        move_to_make = max_move.at(rand() % max_move.size());
      }
    }
    
    bool store = true;
    if(proc_info->draw) {
      store = false;
    }
    if(proc_info->quiescent)
      store = false;

    score_t lo, hi;
    if(proc_info->excess) {
      lo = max_val;
      hi = max_score;
      //std::cout<<"Max depth: "<<proc_info->excess+depth<<std::endl;
      store = false;
    } else if(alpha0 < max_val && max_val < beta) {
      lo = max_val-1;
      hi = max_val;
    } else if(max_val <= alpha0) {
      hi = max_val;
      lo = zlo;
      if(lo == zlo)
        store = false;
    } else if (max_val >= beta){
      lo = max_val;
      hi = zhi;
      if(hi == zhi)
        store = false;
    } else {
      store = false;
      lo = hi = 0;
    }
    if(store && lo > hi) {
      std::cout << "lo=" << lo << " hi=" << hi << std::endl;
      abort();
    }

    if(store && db_on) {
      verify(strBoard,board.side,depth,board.castle,board.ep,lo,hi);
    }
    if(store) {
      //if(board.depth > 1)
        dbase.add_data(board,lo,hi,white,proc_info->excess);
      set_transposition_value(board,lo,hi);
    }
    return max_val;
}