Example #1
0
        public static val qsearch(cPosicion pos, cStackMov[] ss, int ssPos, val alpha, val beta, ply depth, NodeType NT, bool InCheck)
        {
            bool PvNode = (NT == cTipoNodo.PV);
              cPosInfo st = null;
              cTablaHashStruct tte;
              hash posKey;
              mov ttMove, move, bestMove;
              val bestValue, value, ttValue, futilityValue, futilityBase, oldAlpha = 0;
              bool givesCheck, evasionPrunable;
              ply ttDepth;

              if (PvNode)
            oldAlpha = alpha;
              ss[ssPos].currentMove = bestMove = cMovType.MOV_NAN;
              ss[ssPos].ply = ss[ssPos - 1].ply + 1;

              if (pos.IsTablas() || ss[ssPos].ply > cSearch.MAX_PLY)
            return ss[ssPos].ply > cSearch.MAX_PLY && !InCheck ? cEval.Eval(pos) : DrawValue[pos.ColorMueve()];

              ttDepth = ((InCheck || depth >= cPly.DEPTH_QS_CHECKS) ? cPly.DEPTH_QS_CHECKS
                                                              : cPly.DEPTH_QS_NO_CHECKS);

              posKey = pos.ClaveHash();
              tte = cMotor.m_TablaHash.Buscar(posKey);
              ttMove = (tte != null ? tte.GetMove() : cMovType.MOV_NAN);
              ttValue = tte != null ? value_from_tt(tte.GetValue(), ss[ssPos].ply) : cValoresJuego.NAN;
              if (tte != null
              && tte.GetDepth() >= ttDepth
              && ttValue != cValoresJuego.NAN
              && (PvNode ? tte.GetBound() == cBordes.BOUND_EXACT
              : (ttValue >= beta) ? (tte.GetBound() & cBordes.BOUND_LOWER) != 0
                                : (tte.GetBound() & cBordes.BOUND_UPPER) != 0))
              {
            ss[ssPos].currentMove = ttMove;
            return ttValue;
              }

              if (InCheck)
              {
            ss[ssPos].staticEval = cValoresJuego.NAN;
            bestValue = futilityBase = -cValoresJuego.INFINITO;
              }
              else
              {
            if (tte != null)
            {

              if ((ss[ssPos].staticEval = bestValue = tte.GetValueEval()) == cValoresJuego.NAN)
            ss[ssPos].staticEval = bestValue = cEval.Eval(pos);

              if (ttValue != cValoresJuego.NAN)
            if ((tte.GetBound() & (ttValue > bestValue ? cBordes.BOUND_LOWER : cBordes.BOUND_UPPER)) != 0)
              bestValue = ttValue;
            }
            else
              ss[ssPos].staticEval = bestValue = cEval.Eval(pos);

            if (bestValue >= beta)
            {
              if (tte == null)
            cMotor.m_TablaHash.Save(pos.ClaveHash(), value_to_tt(bestValue, ss[ssPos].ply), cBordes.BOUND_LOWER,
                cPly.DEPTH_NONE, cMovType.MOV_NAN, ss[ssPos].staticEval);
              return bestValue;
            }
            if (PvNode && bestValue > alpha)
              alpha = bestValue;
            futilityBase = bestValue + 128;
              }

              cMovOrder mp = new cMovOrder(pos, ttMove, depth, History, cTypes.GetToCasilla(ss[ssPos - 1].currentMove));
              cInfoJaque ci = new cInfoJaque(pos);
              st = new cPosInfo();

              while ((move = mp.SiguienteMovimientoEnFalso()) != cMovType.MOV_NAN)
              {
            givesCheck = cTypes.TipoMovimiento(move) == cMovType.NORMAL && 0 == ci.m_Candidatas
              ? (ci.m_Jaque[cTypes.TipoPieza(pos.GetPieza(cTypes.GetFromCasilla(move)))] & cBitBoard.m_nCasillas[cTypes.GetToCasilla(move)]) != 0
              : pos.IsJaque(move, ci);

            if (!PvNode
              && !InCheck
              && !givesCheck
              && move != ttMove
              && futilityBase > -cValoresJuego.GANA
              && !pos.IsPeonAvanzado(move))
            {
              futilityValue = futilityBase + cPosicion.m_nValPieza[cFaseJuego.FASE_FINAL][pos.GetPieza(cTypes.GetToCasilla(move))];
              if (futilityValue < beta)
              {
            bestValue = Math.Max(bestValue, futilityValue);
            continue;
              }
              if (futilityBase < beta && pos.SEE(move) <= cValoresJuego.CERO)
              {
            bestValue = Math.Max(bestValue, futilityBase);
            continue;
              }
            }

            evasionPrunable = InCheck
                       && bestValue > cValoresJuego.MATE_MAXIMO_VS
                       && !pos.IsCaptura(move)
                       && 0 == pos.CanEnroque(pos.ColorMueve());

            if (!PvNode
              && (!InCheck || evasionPrunable)
              && move != ttMove
              && cTypes.TipoMovimiento(move) != cMovType.PROMOCION
              && pos.SEEReducido(move) < cValoresJuego.CERO)
              continue;

            if (!pos.IsLegalMov(move, ci.m_Clavadas))
              continue;
            ss[ssPos].currentMove = move;

            pos.DoMov(move, st, ci, givesCheck);
            value = givesCheck ? -qsearch(pos, ss, ssPos + 1, -beta, -alpha, depth - cPly.ONE_PLY, NT, true)
                            : -qsearch(pos, ss, ssPos + 1, -beta, -alpha, depth - cPly.ONE_PLY, NT, false);
            pos.DesMov(move);

            if (value > bestValue)
            {
              bestValue = value;
              if (value > alpha)
              {
            if (PvNode && value < beta)
            {
              alpha = value;
              bestMove = move;
            }
            else
            {
              cMotor.m_TablaHash.Save(posKey, value_to_tt(value, ss[ssPos].ply), cBordes.BOUND_LOWER,
                       ttDepth, move, ss[ssPos].staticEval);
              return value;
            }
              }
            }
              }

              if (InCheck && bestValue == -cValoresJuego.INFINITO)
            return cTypes.MateEnVs(ss[ssPos].ply);
              cMotor.m_TablaHash.Save(posKey, value_to_tt(bestValue, ss[ssPos].ply),
              PvNode && bestValue > oldAlpha ? cBordes.BOUND_EXACT : cBordes.BOUND_UPPER,
              ttDepth, bestMove, ss[ssPos].staticEval);
              return bestValue;
        }