Beispiel #1
0
/**
 * Principle Variation Search (root node)
 * Difference with normal (non-root) search:
 * - Sending new PVs asap to the interface
 * - Sort order based on pv and amount of nodes of the subtrees
 * - No pruning and hash table lookup/store
 * - Compatible with all supported wild variants
 */
int search_t::pvs_root(int alpha, int beta, int depth) {

    assert(root.move_count > 0);
    int best = -score::INF;
    const bool is_pv = true;
    root.sort_moves(&stack->best_move);

    /*
     * Moves loop
     */

    for (int i = 0; i < root.move_count; i++) {
        root_move_t * rmove = &root.moves[i];
        move_t * move = &rmove->move;
        int nodes_before = nodes;

        //extensions and reductions
        int extend = extension(move, depth, is_pv, rmove->gives_check);
        int reduce = reduction(depth, i, rmove->is_dangerous);
        int score = 0;

        //go forward and search one level deeper
        forward(move, rmove->gives_check);
        if (i == 0) {
            score = -pvs(-beta, -alpha, depth - 1 + extend);
        } else {
            score = -pvs(-alpha - 1, -alpha, depth - 1 - reduce + extend);
            if (score > alpha) { //open window research w/o reductions
                score = -pvs(-beta, -alpha, depth - 1 + extend);
            }
        }
        backward(move);

        //handle results
        rmove->nodes += nodes - nodes_before;
        if (stop_all) {
            return alpha;
        } else if (score > best) {
            best = score;
            result_score = score;
            rmove->nodes += i;
            stack->best_move.set(move);
            bool exact = score::flags(score, alpha, beta) == score::EXACT;
            if (exact || false == move->equals(&stack->pv_moves[0])) {
                update_pv(&rmove->move);
            }
            uci::send_pv(best, depth, sel_depth, nodes + pruned_nodes, game->tm.elapsed(),
                    pv_to_string().c_str(), score::flags(best, alpha, beta));
            if (!exact) { //adjust asp. window
                return score;
            }
            assert(alpha < best);
            alpha = best;
        }
    }
    return best;
}
bool CPanelLabNameStrings::TransferDataFromWindow()
{
  bool bRtn = (m_pData != NULL);
  if(bRtn)
  {
    wxString s;
    wxTextCtrl *ptext[3] = {m_pTextLadder, m_pTextPos, m_pTextNeg};
    CLabSynonym *pSyn[3] =
    {
      &(m_pData->m_vsSynonymLadder),
      &(m_pData->m_vsSynonymPosCtrl),
      &(m_pData->m_vsSynonymNegCtrl)
    };
    size_t i;
    bool bRtn = true;
    for(i = 0; i < 3; i++)
    {
      s = ptext[i]->GetValue();
      vector<wxString> *pvs(pSyn[i]->GetVectorPtr());
      if(!nwxString::SplitLines(s.c_str(),pvs,true,true))
      {
        mainApp::ShowError(
          _T("Please enter at least one identifier"),this);
        nwxBookCtrlFocus::Focus(ptext[i]);
        i = 3; // loop exit
        bRtn = false;
      }
    }
    m_pData->SetUseSampleName(!!m_pRadioNameType->GetSelection());
    m_pData->m_sStdCtrlName = m_pTextStdCtrlName->GetValue();

    // Specimen Category

    size_t nTYPES = CLabSpecimenCategory::TypeCount();
    CLabSetSpecimenCategory &setSpec(m_pData->m_setSpecimenCategory);
    for(i = 0; i < nTYPES; i++)
    {
      s = m_pvTextSpecimenTypes.at(i)->GetValue();
      setSpec.SetSynonyms(i,s);
    }
  }
  return bRtn;
}
Beispiel #3
0
/**
 * Get a score for every legal move
 */
void search_t::book_calc() {
    const int count = init_root_moves();
    std::string fen = brd.to_string();
    uci::out("book_calc start");
    for (int i = 0; i < count; i++) {
        root_move_t * rmove = &root.moves[i];
        move_t * move = &rmove->move;
        forward(move, rmove->gives_check);
        int score = 0;
        U64 nodes_before = nodes;
        for (int depth = 1; depth <= game->max_depth; depth++) {
            score = -pvs(-score::INF, score::INF, depth - 1);
        }
        backward(move);
        uci::out("book_calc fen " + fen + " move " + move->to_string() + " depth " 
            + uci::itoa(game->max_depth) + " score " + uci::itoa(score) + " nodes " 
            +  uci::itoa(nodes - nodes_before) + " variant " + uci::itoa(wild));
    }
    uci::out("book_calc ready");
}
Beispiel #4
0
bool CPanelLabNameStrings::TransferDataFromWindow()
{
  bool bRtn = (m_pData != NULL);
  if(bRtn)
  {
    NAME_STRING_ARRAYS
    size_t i;
    for(i = 0; i < COUNT; i++)
    {
      s = ptext[i]->GetValue();
      vector<wxString> *pvs(pSyn[i]->GetVectorPtr());
      if(nwxString::SplitLines(s.utf8_str(),pvs,true,true))
      {}
      else if(!ALLOW_EMPTY(i))
      {
        mainApp::ShowError(
          "Please enter at least one identifier",this);
        nwxBookCtrlFocus::Focus(ptext[i]);
        i = COUNT; // loop exit
        bRtn = false;
      }
    }
    m_pData->SetUseSampleName(!!m_pRadioNameType->GetSelection());
    m_pData->m_sStdCtrlName = m_pTextStdCtrlName->GetValue();

    // Specimen Category

    size_t nTYPES = CLabSpecimenCategory::TypeCount();
    CLabSetSpecimenCategory &setSpec(m_pData->m_setSpecimenCategory);
    for(i = 0; i < nTYPES; i++)
    {
      s = m_pvTextSpecimenTypes.at(i)->GetValue();
      setSpec.SetSynonyms(i,s);
    }
  }
  return bRtn;
}
Beispiel #5
0
int maxPathSum(int n, const std::vector<int>& path)
{
	if((n*(n+1))/2!= path.size())
	{
		std::cerr<<n<<' '<<path.size()<<std::endl;
		throw std::invalid_argument("wrong argument");
		return -1;
	}
	std::vector<int> vs (n,0) , pvs(n,0);
	int k = 1;
	pvs[0] = path[0];
	for(int i = 1 ; i < n ; ++ i)
	{
		vs[0] = path[k] + pvs[0];
		vs[i] = path[k+i] + pvs[i-1];
		for(int j = 1 ; j <= i - 1; ++ j)
		{
			vs[j] = std::max(pvs[j],pvs[j-1]) + path[k+j];
		}
		pvs = vs;
		k += (i+1);
	}
	return *std::max_element(vs.begin(),vs.end());
}
Beispiel #6
0
/**
 * 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;
                        }
                    }
                }