Esempio n. 1
0
/* remove n from q1 and put it in q2 if nid not in q2 */
int lqremoveputifn(void *q1p, void *q2p, int (*searchfn1)(void* elementp,void* skeyp1),
                    void* skeyp1, int (*searchfn2)(void* elementp,void* skeyp2), void * skeyp2){ 
    if(NULL != q1p && NULL != q2p){
        void * node;
        int ret = -1;
        pthread_mutex_t *q1_lock = &(((lqtype *)q1p)->q_lock);
        pthread_mutex_t *q2_lock = &(((lqtype *)q2p)->q_lock);
        int rc = pthread_mutex_lock(q1_lock);
        rc = pthread_mutex_lock(q2_lock);
        if(NULL == searchfn2 || qsearch(((lqtype *)q2p)->queue, searchfn2, skeyp2) == NULL){
            node = qremove(((lqtype *)q1p)->queue, searchfn1, skeyp1);
            if(NULL != node){
                qput(((lqtype *)q2p)->queue, node);
                ret = 0;
            }   
        }
        rc = pthread_mutex_unlock(q2_lock);
        rc = pthread_mutex_unlock(q1_lock);

        return ret;
    } else {
        printf("should open queues before using it\n");
        return -1;
    }  
}
Esempio n. 2
0
/* returns first matching element */
void* lqsearch(void *qp, int (*searchfn)(void* elementp,void* keyp),
	      void* skeyp){
    if(NULL != qp){
        pthread_mutex_t *q_lock = &(((lqtype *)qp)->q_lock);
        int rc = pthread_mutex_lock(q_lock);

        void * ret = qsearch(((lqtype *)qp)->queue, searchfn, skeyp);
        rc = pthread_mutex_unlock(q_lock);
	return ret;
    } else {
	printf("should open queue before using it\n");
	return NULL;
    }
}
Esempio n. 3
0
int Board::qsearch(int ply, int alpha, int beta)
{
	// quiescence search 

	int i, j, val;

	if (timedout) return 0;
	triangularLength[ply] = ply;
	if (isOwnKingAttacked()) return alphabetapvs(ply, 1, alpha, beta);
	
	if(EVAL_FUNC == 0){
		val = board.eval();
	}else {
		val = board.evalJL(PARAM_EVAL_MATERIAL, PARAM_EVAL_ESPACIAL, PARAM_EVAL_DINAMICA, PARAM_EVAL_POS_TABLERO, ply);
	}

	if (val >= beta) return val;
	if (val > alpha) alpha = val;

	// generate captures & promotions:
	// captgen returns a sorted move list
	moveBufLen[ply+1] = captgen(moveBufLen[ply]);
	for (i = moveBufLen[ply]; i < moveBufLen[ply+1]; i++)
	{
		makeMove(moveBuffer[i]);
		{
			if (!isOtherKingAttacked()) 
			{
				inodes++;
				if (--countdown <=0) readClockAndInput();
				val = -qsearch(ply+1, -beta, -alpha);
				unmakeMove(moveBuffer[i]);
				if (val >= beta) return val;
				if (val > alpha)
				{
					alpha = val;
					triangularArray[ply][ply] = moveBuffer[i];
					for (j = ply + 1; j < triangularLength[ply+1]; j++) 
					{
						triangularArray[ply][j] = triangularArray[ply+1][j];
					}
					triangularLength[ply] = triangularLength[ply+1];
				}
			}
			else unmakeMove(moveBuffer[i]);
		}
	}
	return alpha;
}
Esempio n. 4
0
/*! @decl int(0..0) _xpm_write_rows(Image.Image img, Image.Image alpha, @
 *!                 int bpc, array(string) colors, array(string) pixels)
 *!
 *! Fills in @[img] and @[alpha] according to xpm data in @[bpc], @[colors]
 *! and @[pixels].
 *!
 *! @param bpc
 *!   Bytes per color. Number of bytes used to encode each color in @[pixels].
 *!
 *! @param colors
 *!   Array of color definitions.
 *!
 *!   A color definition is on the format @tt{"ee c #RRGGBB"@},
 *!   where @tt{ee@} is a @[bpc] long string used to encode the color,
 *!   @tt{c@} is a literal @tt{"c"@}, and @tt{RRGGBB@} is a hexadecimal
 *!   RGB code.
 *!
 *! @param pixels
 *!   Raw picture information.
 *!
 *!   @array pixels
 *!     @elem string 0
 *!       Size information on the format
 *!         (@expr{sprintf("%d %d %d %d", h, w, ncolors, bpn)@}).
 *!     @elem string 1..ncolors
 *!       Same as @[colors].
 *!     @elem string ncolors_plus_one..ncolors_plus_h
 *!       Line information. Strings of length @[bpn]*w with encoded
 *!       pixels for each line.
 *!   @endarray
 */
void f__xpm_write_rows( INT32 args )
{
  struct object *img;
  struct object *alpha;
  struct array *pixels;
  struct array *colors;
  struct image *iimg, *ialpha;
  rgb_group *dst, *adst;
  INT_TYPE y,x,  bpc;

  get_all_args("_xpm_write_rows",args,"%o%o%i%a%a",
               &img,&alpha,&bpc,&colors,&pixels);

#if 0
  fprintf(stderr, "_xpm_write_rows(");
  print_svalue(stderr, Pike_sp-5);
  fprintf(stderr, ", ");
  print_svalue(stderr, Pike_sp-4);
  fprintf(stderr, ", ");
  print_svalue(stderr, Pike_sp-3);
  fprintf(stderr, ", ");
  print_svalue(stderr, Pike_sp-2);
  fprintf(stderr, ", ");
  print_svalue(stderr, Pike_sp-1);
  fprintf(stderr, ")\n");
#endif /* 0 */

  iimg = (struct image *)get_storage( img, image_program );
  ialpha = (struct image *)get_storage( alpha, image_program );
  if(!iimg || !ialpha)
    Pike_error("Sluta pilla på interna saker..\n");

  if (pixels->size < iimg->ysize + colors->size) {
    SIMPLE_ARG_ERROR("_xpm_write_rows", 5, "pixel array is too short.");
  }

  for(y = 0; y < iimg->ysize + colors->size + 1; y++) {
    if ((pixels->item[y].type != T_STRING) ||
	(pixels->item[y].u.string->size_shift)) {
      SIMPLE_ARG_ERROR("_xpm_write_rows", 5,
		       "Pixel array contains elements other than 8bit strings.");
    }
    if (y < colors->size) {
      if ((colors->item[y].type != T_STRING) ||
	  (pixels->item[y].u.string->size_shift)) {
	SIMPLE_ARG_ERROR("_xpm_write_rows", 5,
			 "Color array contains elements other than 8bit strings.");
      }
    } else if (y > colors->size) {
      if (pixels->item[y].u.string->len < iimg->xsize*bpc) {
	SIMPLE_ARG_ERROR("_xpm_write_rows", 5,
			 "Pixel array contains too short string (bad bpc?).");
      }
    }
  }

  dst = iimg->img;
  adst = ialpha->img;


  switch(bpc)
  {
   default:
    for(y = 0; y<iimg->ysize; y++)
    {
      char *ss = (char *)pixels->item[y+colors->size+1].u.string->str;
      for(x = 0; x<iimg->xsize; x++)
      {
        rgba_group color=qsearch(ss,bpc,colors);  ss+=bpc;
        if(color.alpha)
        {
          dst->r = color.r;
          dst->g = color.g;
          (dst++)->b = color.b;
          adst++;
        } else {
          dst++;
          adst->r = adst->g = adst->b = 0;
	  adst++;
        }
      }
    }
    break;
   case 3: 
   {
     rgba_group **p_colors;
     int i;
     p_colors = (rgba_group **)xalloc(sizeof(rgba_group *)*65536);
     MEMSET(p_colors, 0, sizeof(rgba_group *)*65536);
     for(i=0; i<colors->size; i++)
     {
       struct pike_string *c = colors->item[i].u.string;
       unsigned char ind = ((unsigned char *)(c->str))[2];
       unsigned short id = extract_short((unsigned char *)c->str);
       if(!p_colors[id])
       {
         p_colors[id] = (rgba_group *)xalloc(sizeof(rgba_group)*128);
         MEMSET(p_colors[id],0,sizeof(rgba_group)*128);
       }
       if(ind > 127) 
       {
         p_colors[id] = (rgba_group *)realloc(p_colors[id],sizeof(rgba_group)*256);
         MEMSET(p_colors[id]+sizeof(rgba_group)*128,0,sizeof(rgba_group)*128);
       }
       p_colors[id][ind]=parse_color_line( c, bpc );
     }
     for(y = 0; y<iimg->ysize; y++)
     {
       unsigned char *ss = (unsigned char *)pixels->item[y+colors->size+1].
         u.string->str;
       rgba_group *color, colorp;
       for(x = 0; x<iimg->xsize; x++)
       {
         color=p_colors[extract_short(ss)];
         if(color)
           colorp = color[((unsigned char *)ss+2)[0]];
         else
           colorp.alpha = 0;
         if(colorp.alpha)
         {
           dst->r = colorp.r;
           dst->g = colorp.g;
           (dst++)->b = colorp.b;
           adst++;
         } else {
           adst->r = adst->g = adst->b = 0;
           dst++;
         }
         ss+=bpc;
       }
     }
     for(i=0; i<65536; i++)
       if(p_colors[i]) free(p_colors[i]);
     free(p_colors);
     break;
   }
   case 2:
   {
     rgba_group p_colors[65536];
     int i;

     for(i=0; i<colors->size; i++)
     {
       unsigned short id = 
         extract_short((unsigned char*)colors->item[i].u.string->str);
       p_colors[id] = parse_color_line( colors->item[i].u.string, bpc );
     }
     for(y = 0; y<iimg->ysize; y++)
     {
       unsigned char *ss = (unsigned char *)pixels->item[y+colors->size+1].
         u.string->str;
       for(x = 0; x<iimg->xsize; x++)
       {
         rgba_group color=p_colors[extract_short(ss)];
         dst->r = color.r;
         dst->g = color.g;
         (dst++)->b = color.b;
         if(!color.alpha)
           adst->r = adst->g = adst->b = 0;
         ss+=bpc;
         adst++;
       }
     }
     break;
   }
   case 1:
   {
     rgba_group p_colors[256];
     int i;

     for(i=0; i<colors->size; i++)
     {
       unsigned char id = *((unsigned char *)colors->item[i].u.string->str);
       p_colors[id] = parse_color_line( colors->item[i].u.string, bpc );
     }
     for(y = 0; y<iimg->ysize; y++)
     {
       unsigned char *ss=(unsigned char *)
         pixels->item[y+colors->size+1].u.string->str;
       for(x = 0; x<iimg->xsize; x++)
       {
         rgba_group color=p_colors[*ss];
         dst->r = color.r;
         dst->g = color.g;
         (dst++)->b = color.b;
         if(!color.alpha)
           adst->r = adst->g = adst->b = 0;
         ss+=bpc;
         adst++;
       }
     }
     break;
   }
  }
  pop_n_elems(args);
  push_int(0);
}
Esempio n. 5
0
File: search.cpp Progetto: hof/qm2
/**
 * Principle Variation Search (fail-soft)
 * @param alpha lowerbound value
 * @param beta upperbound value
 * @param depth remaining search depth
 * @return score for the current node
 */
int search_t::pvs(int alpha, int beta, int depth) {

    assert(alpha < beta);
    assert(alpha >= -score::INF);
    assert(beta <= score::INF);

    stack->pv_count = 0;
    sel_depth = MAX(brd.ply, sel_depth);
    stack->best_move.clear();

    /*
     * If no more depth remaining, return quiescence value
     */

    if (depth < 1) {
        const int score = qsearch(alpha, beta, 0);
        return score;
    }

    /*
     * Stop conditions
     */

    //time 
    nodes++;
    if (abort()) {
        return alpha;
    }

    //ceiling
    if (brd.ply >= (MAX_PLY - 1)) {
        return evaluate(this);
    }

    assert(depth > 0 && depth <= MAX_PLY);
    int alpha1 = alpha;

    //mate distance pruning: if mate(d) in n don't search deeper
    if ((score::MATE - brd.ply) < beta) {
        beta = score::MATE - brd.ply;
        if (alpha >= beta) {
            return beta;
        }
    }
    if ((-score::MATE + brd.ply) > alpha) {
        alpha = -score::MATE + brd.ply;
        if (beta <= alpha) {
            return alpha;
        }
    }

    //draw by lack of material or fifty quiet moves
    if (is_draw()) {
        return draw_score();
    }

    /*
     * Transposition table lookup
     */

    const bool pv = alpha + 1 < beta;
    stack->tt_key = brd.stack->tt_key; //needed for testing repetitions
    int tt_move = 0, tt_flag = 0, tt_score;
    if (trans_table::retrieve(stack->tt_key, brd.ply, depth, tt_score, tt_move, tt_flag)) {
        if (pv && tt_flag == score::EXACT) {
            return tt_score;
        } else if (!pv && tt_score >= beta && tt_flag == score::LOWERBOUND) {
            return tt_score;
        } else if (!pv && tt_score <= alpha && tt_flag == score::UPPERBOUND) {
            return tt_score;
        }
    }
    stack->tt_move.set(tt_move);

    /*
     * Node pruning
     */

    const bool in_check = stack->in_check;
    const int eval = evaluate(this);
    const bool do_prune_node = eval >= beta && !in_check && !pv && !score::is_mate(beta) && brd.has_pieces(brd.us());

    // beta pruning
    if (do_prune_node && depth < 4 && beta_pruning) {
        int bp_score = eval - 50 * depth;
        if (bp_score >= beta) {
            return bp_score;
        }
    }

    //null move pruning
    if (do_prune_node && null_enabled) {
        int R = 3;
        forward();
        int null_score = -pvs(-beta, -alpha, depth - 1 - R);
        backward();
        if (stop_all) {
            return alpha;
        } else if (null_score >= beta) {
            const int RV = 5;
            if (null_verify && depth > RV && material::is_eg(this)) {
                //verification
                int verified_score = pvs(alpha, beta, depth - 1 - RV);
                if (verified_score >= beta) {
                    return verified_score;
                }
            } else {
                //no verification
                return null_score;
            }
        }
    }

    /*
     * Internal iterative deepening (IID)
     */

    if (pv && depth > 2 && tt_move == 0) {
        int iid_score = pvs(alpha, beta, depth - 2);
        if (score::is_mate(iid_score)) {
            return iid_score;
        } else if (stack->best_move.piece) {
            stack->tt_move.set(&stack->best_move);
        }
    }

    /*
     * Moves loop
     */

    //if there is no first move, it's checkmate or stalemate
    move_t * move = move::first(this, depth);
    if (!move) {
        return in_check ? -score::MATE + brd.ply : draw_score();
    }

    //set futility pruning delta value
    bool do_ffp = false;
    int delta = score::INVALID;
    if (depth <= 8 && !in_check && !score::is_mate(alpha) && !material::is_eg(this) && ffp_enabled) {
        int ffp_score = eval + 40 * depth;
        if (ffp_score <= alpha) {
            do_ffp = true;
            delta = ffp_score + 50;
        }
    }

    //prepare and do the loop
    int best = -score::INF;
    int searched_moves = 0;
    const int score_max = score::MATE - brd.ply - 1;
    stack->best_move.clear();
    do {

        assert(brd.valid(move) && brd.legal(move));
        assert(stack->best_move.equals(move) == false);
        assert(in_searched(move, searched_moves) == false);

        const int gives_check = brd.gives_check(move);
        assert(gives_check == 0 || gives_check == 1 || gives_check == 2);

        /*
         * Move pruning: skip all futile moves
         */

        const bool is_dangerous = in_check || gives_check || move->capture || move->promotion || move->castle || is_advanced_passed_pawn(move);

        bool pruned = false;
        if (do_ffp && searched_moves > 0) {
            pruned = !is_dangerous;
            pruned |= gives_check == 0 && (move->capture || move->promotion) && brd.max_gain(move) + delta <= alpha;
            if (pruned) {
                pruned_nodes++;
                continue;
            }
        }


        /*
         * Move extensions
         */

        int extend = extension(move, depth, pv, gives_check);

        /*
         * Move Reductions (Late Move Reductions, LMR) 
         */

        int reduce = reduction(depth, searched_moves, is_dangerous);

        /*
         * Go forward and search next node
         */

        forward(move, gives_check);
        int score;
        if (searched_moves == 0) {
            score = -pvs(-beta, -alpha, depth - 1 + extend);
        } else {
            score = -pvs(-alpha - 1, -alpha, depth - 1 - reduce + extend);
            if (score > alpha && (pv || reduce > 0)) { //open window research without reductions
                score = -pvs(-beta, -alpha, depth - 1 + extend);
            }
        }
        backward(move);

        /*
         * Handle results: update the best value / do a beta cutoff
         */

        if (stop_all) {
            return alpha;
        } else if (score > best) {
            stack->best_move.set(move);
            if (score >= beta) {
                trans_table::store(stack->tt_key, brd.root_ply, brd.ply, depth, score, move->to_int(), score::LOWERBOUND);
                if (!move->capture && !move->promotion && !move->castle) {
                    update_killers(move);
                    update_history(move);
                    for (int i = 0; i < searched_moves; i++) {
                        move_t * m = &stack->searched[i];
                        if (!m->capture && !m->promotion && !m->castle) {
                            history[m->piece][m->tsq] >>= searched_moves;
                        }
                    }
                }
Esempio n. 6
0
t_chess_value qsearch(struct t_board *board, int ply, int depth, t_chess_value alpha, t_chess_value beta) {

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

    //-- Has the maximum depth been reached
    if (ply >= MAXPLY || uci.stop)
        return pv->eval->static_score;

    //-- Increment the node count
    qnodes++;

    //-- Is this the deepest?
    if (ply > deepest) {
        deepest = ply;
        do_uci_depth();
    }

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

    //-- PV of Next Ply
    struct t_pv_data *next_pv = &(board->pv_data[ply + 1]);

    //-- Define the local variables
    pv->legal_moves_played = 0;
    t_chess_value best_score;
    t_chess_value a = alpha;
    t_chess_value b = beta;
    t_chess_value e;


    // Declare local variables
    t_undo undo[1];

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

    //-----------------------------------------------
    //-- Handling In-Check (e.g. Cannot Stand-Pat)
    //-----------------------------------------------
    if (board->in_check) {

        best_score = -CHECKMATE;

        //-- Generate moves which get out of check
        generate_evade_check(board, moves);

        // Are we in checkmate?
        if (moves->count == 0) {
            pv->best_line_length = ply;
            return -CHECKMATE + ply;
        }

        //-- Order the moves
        order_evade_check(board, moves, ply);

        //-- Play moves
        while (make_next_best_move(board, moves, undo)) {

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

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

            //-- Search the next ply at reduced depth
            e = -qsearch(board, ply + 1, depth - 1, -b - 1, -a);

            //-- Is a research required?
            if (alpha + 1 != beta && e > a && a + 1 == b)
                e = -qsearch(board, ply + 1, depth - 1, -beta, -a);

            unmake_move(board, undo);

            //-- Is it good enough to cut-off?
            if (e >= beta) {
                update_check_killers(pv, 0);
                return e;
            }

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

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

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

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

        }

    }
    else {
        //--------------------------------------------------------
        //-- Normal moves handled differently (e.g. can stand-pat)
        //--------------------------------------------------------

        //-- Does stand-pat cause a cutoff?
        e = pv->eval->static_score;
        if (e >= beta)
            return e;

        //-- Does the current value raise alpha?
        best_score = e;
        if (e > alpha) {
            a = e;
            pv->best_line_length = ply;
        }

        //-- Generate all captures
        generate_captures(board, moves);

        //-- Order the moves
        order_captures(board, moves);

		//-- Only search break even captures during the PV
		//int threshold = 10;
		//if (beta != alpha + 1)
		int threshold = 0;

        //-- Play moves
        while (make_next_see_positive_move(board, moves, threshold, undo)) {

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

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

            //-- Search the next ply at reduced depth
            e = -qsearch(board, ply + 1, depth - 1, -b, -a);

            //-- Is a research required?
            if (alpha + 1 != beta && e > a && a + 1 == b)
                e = -qsearch(board, ply + 1, depth - 1, -beta, -a);

            unmake_move(board, undo);

            //-- Is it good enough to cut-off?
            if (e >= beta)
                return e;

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

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

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

        }
    }

    // Return Best Score found
    return best_score;

}
Esempio n. 7
0
t_chess_value qsearch_plus(struct t_board *board, int ply, int depth, t_chess_value alpha, t_chess_value beta) {

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

    //-- Has the maximum depth been reached
    if (ply >= MAXPLY || uci.stop)
        return pv->eval->static_score;

    //-- Increment the node count
    qnodes++;

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

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

    //-- Next Principle Variation
    struct t_pv_data *next_pv = &(board->pv_data[ply + 1]);

    //-- Define the local variables
    pv->legal_moves_played = 0;
    t_chess_value best_score;
    t_chess_value a = alpha;
    t_chess_value b = beta;
	t_chess_value e;

    // Declare local variables
    t_undo undo[1];

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

    //-----------------------------------------------
    //-- Handling In-Check (e.g. Cannot Stand-Pat)
    //-----------------------------------------------
    if (board->in_check) {

        best_score = -CHECKMATE;

        //-- Generate moves which get out of check
        generate_evade_check(board, moves);

        // Are we in checkmate?
        if (moves->count == 0) {
            pv->best_line_length = ply;
            return -CHECKMATE + ply;
        }

        t_chess_value(*q_search)(struct t_board *board, int ply, int depth, t_chess_value alpha, t_chess_value beta);

        if (moves->count == 1)
            q_search = &qsearch_plus;
        else {
            q_search = &qsearch;
            //-- Order the moves
            order_evade_check(board, moves, ply);
        }

        //-- Play moves
        while (make_next_best_move(board, moves, undo)) {

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

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

            //-- More than one move out of check so just use "vanilla" qsearch
            e = -q_search(board, ply + 1, depth - 1, -b, -a);

            //-- Is a research required?
            if (alpha + 1 != beta && e > a && a + 1 == b)
                e = -q_search(board, ply + 1, depth - 1, -beta, -a);

            unmake_move(board, undo);

            //-- Is it good enough to cut-off?
            if (e >= beta) {
                update_check_killers(pv, 0);
                poke(board->hash, e, ply, depth, HASH_LOWER, pv->current_move);
                return e;
            }

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

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

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

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

        }
    }
    else {
        //--------------------------------------------------------
        //-- Normal moves handled differently (e.g. can stand-pat)
        //--------------------------------------------------------

        //-- Does stand-pat cause a cut-off?
        e = pv->eval->static_score;
        if (e >= beta)
            return e;

        //-- Does the current value raise alpha?
        best_score = e;
        if (e > alpha) {
            a = e;
            pv->best_line_length = ply;
        }

        //-- Generate all captures
        generate_captures(board, moves);

        //-- Order the moves
        order_captures(board, moves);

        //-- Play *ALL* captures
        while (make_next_best_move(board, moves, undo)) {

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

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

			//-- Search the next ply at reduced depth
			e = -qsearch(board, ply + 1, depth - 1, -b, -a);

			//-- Is a research required?
			if (alpha + 1 != beta && e > a && a + 1 == b)
				e = -qsearch(board, ply + 1, depth - 1, -beta, -a);

            unmake_move(board, undo);

            //-- Is it good enough to cut-off?
            if (e >= beta) {
                return e;
            }

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

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

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

        }

		//-- Reset the move count
		moves->count = 0;

        //-- Now Try the checks!
		generate_quiet_checks(board, moves);

		////-- Maybe if there are many, one will be a checkmate?
		//if (moves->count > 4){

		//	while (simple_make_next_move(board, moves, undo)) {

		//		assert(board->in_check);

		//		//-- Generate moves
		//		struct t_move_list evade_check_moves[1];
		//		generate_evade_check(board, evade_check_moves);

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

		//		//-- Is it Checkmate?
		//		if (evade_check_moves->count == 0){
		//			pv->best_line_length = ply + 1;
		//			e = +CHECKMATE - ply - 1;
		//			return e;
		//		}
		//	}
		//	//-- Reset the real move count 
		//	moves->imove = moves->count;
		//}
		
        //-- Order the moves
        order_moves(board, moves, ply);

        //-- Play moves
        while (make_next_best_move(board, moves, undo)) {

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

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

            //-- Search the next ply at reduced depth
            e = -qsearch_plus(board, ply + 1, depth - 1, -b, -a);

            //-- Is a research required?
            if (alpha + 1 != beta && e > a && a + 1 == b)
                e = -qsearch_plus(board, ply + 1, depth - 1, -beta, -a);

            unmake_move(board, undo);

            //-- Is it good enough to cut-off?
            if (e >= beta) {
                poke(board->hash, e, ply, depth, HASH_LOWER, pv->current_move);
                update_killers(pv, 0);
                return e;
            }

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

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

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

        }
    }

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

    // Return Best Score found
    return best_score;
}
Esempio n. 8
0
int Board::alphabetapvs(int ply, int depth, int alpha, int beta)
{
  // PV search
  
  int i, j, movesfound, pvmovesfound, val;
  triangularLength[ply] = ply;
  if (depth == 0)
  {
    followpv = false;
    return qsearch(ply, alpha, beta);
  }
  
  // repetition check:
  if (repetitionCount() >= 3) return DRAWSCORE;
  movesfound = 0;
  pvmovesfound = 0;
  moveBufLen[ply+1] = movegen(moveBufLen[ply]);
  for (i = moveBufLen[ply]; i < moveBufLen[ply+1]; i++)
  {
    selectmove(ply, i, depth, followpv);
    makeMove(moveBuffer[i]);
    {
      if (!isOtherKingAttacked())
      {
        inodes++;
        movesfound++;
        if (!ply) displaySearchStats(3, ply, i);
        if (pvmovesfound)
        {
          val = -alphabetapvs(ply+1, depth-1, -alpha-1, -alpha);
          if ((val > alpha) && (val < beta))
          {
            // in case of failure, proceed with normal alphabeta
            val = -alphabetapvs(ply+1, depth - 1, -beta, -alpha);                        
          }
        }
        // normal alphabeta
        else val = -alphabetapvs(ply+1, depth-1, -beta, -alpha);         
        unmakeMove(moveBuffer[i]);
        if (val >= beta)
        {
          // update the history heuristic
          if (nextMove)
            blackHeuristics[moveBuffer[i].getFrom()][moveBuffer[i].getTosq()] += depth*depth;
          else
            whiteHeuristics[moveBuffer[i].getFrom()][moveBuffer[i].getTosq()] += depth*depth;
          return beta;
        }
        if (val > alpha)
        {
          alpha = val;                                                      // both sides want to maximize from *their* perspective
          pvmovesfound++;
          triangularArray[ply][ply] = moveBuffer[i];                                  // save this move
          for (j = ply + 1; j < triangularLength[ply+1]; j++)
          {
            triangularArray[ply][j] = triangularArray[ply+1][j];   // and append the latest best PV from deeper plies
          }
          triangularLength[ply] = triangularLength[ply+1];
          if (!ply)
          {
            msStop = timer.getms();
            displaySearchStats(2, depth, val);
          }
        }
      }
      else unmakeMove(moveBuffer[i]);
    }
  }
  
  // update the history heuristic
  if (pvmovesfound)
  {
    if (nextMove)
      blackHeuristics[triangularArray[ply][ply].getFrom()][triangularArray[ply][ply].getTosq()] += depth*depth;
    else
      whiteHeuristics[triangularArray[ply][ply].getFrom()][triangularArray[ply][ply].getTosq()] += depth*depth;
  }
  
  //     50-move rule:
  if (fiftyMove >= 100) return DRAWSCORE;
  
  //     Checkmate/stalemate detection:
  if (!movesfound)
  {
    if (isOwnKingAttacked())  return (-CHECKMATESCORE+ply-1);
    else  return (STALEMATESCORE);
  }
  
  return alpha;
}
Esempio n. 9
0
int Board::alphabetapvs(int ply, int depth, int alpha, int beta)
{
	// PV search

	int i, j, movesfound, pvmovesfound, val;

	triangularLength[ply] = ply;
	if (depth <= 0) 
	{
		followpv = false;
		return qsearch(ply, alpha, beta);
	}

	// repetition check:
	if (repetitionCount() >= 3) return DRAWSCORE;
	
	// now try a null move to get an early beta cut-off:
	if (!followpv && allownull)
	{
		if ((nextMove && (board.totalBlackPieces > NULLMOVE_LIMIT)) || (!nextMove && (board.totalWhitePieces > NULLMOVE_LIMIT)))
		{
			if (!isOwnKingAttacked())
			{
				allownull = false;
				inodes++;
				if (--countdown <=0) readClockAndInput();
				nextMove = !nextMove;
				hashkey ^= KEY.side; 
				val = -alphabetapvs(ply, depth - NULLMOVE_REDUCTION, -beta, -beta+1);
				nextMove = !nextMove;
				hashkey ^= KEY.side;
				if (timedout) return 0;
				allownull = true;
				if (val >= beta) return val;
			}
		}
	}
	allownull = true;

	movesfound = 0;
	pvmovesfound = 0;
	moveBufLen[ply+1] = movegen(moveBufLen[ply]);
	for (i = moveBufLen[ply]; i < moveBufLen[ply+1]; i++)
	{
		selectmove(ply, i, depth, followpv); 
		makeMove(moveBuffer[i]);
		{
			if (!isOtherKingAttacked()) 
			{
				inodes++;
				if (--countdown <=0) readClockAndInput();
				movesfound++;
				if (!ply) displaySearchStats(3, ply, i); 
				if (pvmovesfound)
				{
					val = -alphabetapvs(ply+1, depth-1, -alpha-1, -alpha); 
		            if ((val > alpha) && (val < beta))
					{
						 // in case of failure, proceed with normal alphabeta
						val = -alphabetapvs(ply+1, depth - 1, -beta, -alpha);  		        
					}
				} 
				// normal alphabeta
	 			else val = -alphabetapvs(ply+1, depth-1, -beta, -alpha);	    
				unmakeMove(moveBuffer[i]);
				if (timedout) return 0;
				if (val >= beta)
				{
					// update the history heuristic
					if (nextMove) 
						blackHeuristics[moveBuffer[i].getFrom()][moveBuffer[i].getTosq()] += depth*depth;
					else 
						whiteHeuristics[moveBuffer[i].getFrom()][moveBuffer[i].getTosq()] += depth*depth;
					return beta;
				}
				if (val > alpha)
				{
					alpha = val;								    // both sides want to maximize from *their* perspective
					pvmovesfound++;
					triangularArray[ply][ply] = moveBuffer[i];					// save this move
					for (j = ply + 1; j < triangularLength[ply+1]; j++) 
					{
						triangularArray[ply][j] = triangularArray[ply+1][j];	// and append the latest best PV from deeper plies
					}
					triangularLength[ply] = triangularLength[ply+1];
					if (!ply) displaySearchStats(2, depth, val);
				}
			}
			else unmakeMove(moveBuffer[i]);
		}
	}

	// update the history heuristic
	if (pvmovesfound)
	{
		if (nextMove) 
			blackHeuristics[triangularArray[ply][ply].getFrom()][triangularArray[ply][ply].getTosq()] += depth*depth;
		else
			whiteHeuristics[triangularArray[ply][ply].getFrom()][triangularArray[ply][ply].getTosq()] += depth*depth;
	}

	//	50-move rule:
	if (fiftyMove >= 100) return DRAWSCORE;

	//	Checkmate/stalemate detection:
	if (!movesfound)
	{
		if (isOwnKingAttacked())  return (-CHECKMATESCORE+ply-1);
		else  return (STALEMATESCORE);
	}

	return alpha;
}
Esempio n. 10
0
int qsearch(s_search_info *info, s_stack *stack, s_board *board, int alpha, int beta)
{
    assert(info != NULL);
    assert(stack != NULL);
    assert(board != NULL);
    assert(alpha < beta);

    int stand_pat = evaluate(board);

    if(stack->ply > info->seldepth)
    {
        info->seldepth = stack->ply-1;
    }

    if(stand_pat >= beta)
    {
        return beta;
    }

#ifdef DELTA_PRUNING
    const int safety = 900; // The value of a queen

    if(stand_pat < alpha - safety && !is_endgame(board))
    {
        return alpha;
    }
#endif

    if(stand_pat > alpha)
    {
        alpha = stand_pat;
    }

    if(stack->ply >= MAX_DEPTH)
    {
        return stand_pat;
    }

    // Set old permissions
    s_irreversible permissions;
    store_irreversible(&permissions, board);

    s_move moves[MAX_MOVES];
    int num_moves = find_moves_captures(board, moves, board->turn);
#ifdef SORT_MOVES
    moves_sort_see(board, moves, num_moves);
#endif

    for(int m = 0; m < num_moves; ++m)
    {
        int val = see_capture(board, moves[m]);
        if(val < -50)
        {
            break;
        }

        move_make(board, &moves[m]);

        if(square_attacked(board, board->pieces[KINGS]&board->colour[!board->turn], board->turn))
        {
            // Restore old permissions
            restore_irreversible(&permissions, board);

            move_undo(board, &moves[m]);
            continue;
        }

        info->nodes++;

        int score = -qsearch(info, stack+1, board, -beta, -alpha);

        // Restore old permissions
        restore_irreversible(&permissions, board);

        move_undo(board, &moves[m]);

        if(score >= beta)
        {
#ifndef NDEBUG
            info->num_cutoffs[m]++;
#endif
            return beta;
        }

        if(score > alpha)
        {
            alpha = score;
        }
    }

    return alpha;
}