//---------------------------------------------------------------------------------------- public static int Enroques(cPosicion pos, cMov[] mlist, int mPos, color us, cInfoJaque ci, enroque Cr, bool Checks, bool Chess960) { bool KingSide = (Cr==cEnroque.OO_BLANCAS||Cr==cEnroque.OO_NEGRAS); if(pos.CanNotEnroque(Cr)||0==pos.PosibleEnrocar(Cr)) return mPos; sq kfrom = pos.GetRey(us); sq rfrom = pos.CasillaTorreEnroque(Cr); sq kto = cTypes.CasillaProxima(us, KingSide ? cCasilla.G1 : cCasilla.C1); bitbrd enemies = pos.PiezasColor(cTypes.Contrario(us)); sq K = Chess960 ? kto>kfrom ? cCasilla.OESTE : cCasilla.ESTE : KingSide ? cCasilla.OESTE : cCasilla.ESTE; for(sq s = kto; s!=kfrom; s+=K) if((pos.AtaquesA(s)&enemies)!=0) return mPos; if(Chess960&&(cBitBoard.AtaquesPieza(kto, pos.Piezas()^cBitBoard.m_nCasillas[rfrom], cPieza.TORRE)&pos.PiezasColor(cTypes.Contrario(us), cPieza.TORRE, cPieza.DAMA))!=0) return mPos; mov m = cTypes.CreaMov(kfrom, rfrom, cMovType.ENROQUE, cPieza.CABALLO); if(Checks&&!pos.IsJaque(m, ci)) return mPos; mlist[mPos++].m=m; return mPos; }
//---------------------------------------------------------------------------------------- public static int Capturas(cPosicion pos, cMov[] mlist, int mPos, type Type) { color us = pos.ColorMueve(); bitbrd target = Type==cMovType.CAPTURES ? pos.PiezasColor(cTypes.Contrario(us)) : Type==cMovType.QUIETS ? ~pos.Piezas() : Type==cMovType.NON_EVASIONS ? ~pos.PiezasColor(us) : 0; return us==cColor.BLANCO ? ToDO(pos, mlist, mPos, target, cColor.BLANCO, Type, null) : ToDO(pos, mlist, mPos, target, cColor.NEGRO, Type, null); }
//--------------------------------------------------------------------------------- public static mov GetFromUCI(cPosicion pos, string str) { if (str.Length == 5) { char[] strChar = str.ToCharArray(); strChar[4] = char.ToLower(strChar[4]); str = new String(strChar); } for (cReglas it = new cReglas(pos, cMovType.LEGAL); it.GetActualMov() != cMovType.MOV_NAN; ++it) if (str == GetMovimiento(it.GetActualMov(), pos.IsChess960() != false)) return it.GetActualMov(); return cMovType.MOV_NAN; }
//------------------------------------------------------------------------------------ public mov Buscar(cPosicion posicion) { mov move = cMovType.MOV_NAN; if (Open()) { cLibro.stLineaLibro lineaLibro = new cLibro.stLineaLibro(); UInt16 bMejorJugada = 0; uint sum = 0; hash key = PolyglotKey(posicion); m_Stream.Seek(FindFirst(key) * SIZE_OF_BOOKENTRY, SeekOrigin.Begin); while (Read(ref lineaLibro) && lineaLibro.key == key) { bMejorJugada = Math.Max(bMejorJugada, lineaLibro.count); sum += lineaLibro.count; if ((sum != 0 && ((((uint)m_Rand.GetRand()) % sum) < lineaLibro.count)) || (lineaLibro.count == bMejorJugada)) move = (lineaLibro.move); } if (move != 0) { int pt = (move >> 12) & 7; if (pt != 0) move = cTypes.CreaMov(cTypes.GetFromCasilla(move), cTypes.GetToCasilla(move), cMovType.PROMOCION, (pt + 1)); for (cReglas listaMovimientos = new cReglas(posicion, cMovType.LEGAL); listaMovimientos.GetActualMov() != cMovType.MOV_NAN; ++listaMovimientos) if (move == (listaMovimientos.GetActualMov() ^ cTypes.TipoMovimiento(listaMovimientos.GetActualMov()))) { move = listaMovimientos.GetActualMov(); break; } } } return move; }
public static string uci_pv(cPosicion pos, int depth, val alpha, val beta) { StringBuilder s = new StringBuilder(); long elaspsed = cReloj.Now() - SearchTime + 1; int uciPVSize = Math.Min(cMotor.m_mapConfig["MultiPV"].Get(), RootMoves.Count); int selDepth = 0; for (int i = 0; i < cMotor.m_Threads.Count; ++i) if (cMotor.m_Threads[i].m_nMaxPly > selDepth) selDepth = cMotor.m_Threads[i].m_nMaxPly; for (int i = 0; i < uciPVSize; ++i) { bool updated = (i <= PVIdx); if (depth == 1 && !updated) continue; int d = (updated ? depth : depth - 1); if (RootMoves[i].m_PV.Count > 0 && RootMoves[i].m_PV[0] != cMovType.MOV_NAN && 0 < d) { val v = (updated ? RootMoves[i].m_nVal : RootMoves[i].m_LastVal); if (s.Length != 0) s.Append(cTypes.LF); /*bool bShow = true; for (int j = 0; j < d; ++j) { if (RootMoves[i].m_PV.Count > j && RootMoves[i].m_PV[j] == cMovType.MOV_NAN) bShow = false; }*/ if (RootMoves[i].m_PV[0] != cMovType.MOV_NAN) { s.Append("info depth "); s.Append(d); s.Append(" score "); s.Append((i == PVIdx ? cUci.Puntos(v, alpha, beta) : cUci.Puntos(v, -cValoresJuego.INFINITO, cValoresJuego.INFINITO))); s.Append(" nodes "); s.Append(pos.GetNodos()); s.Append(" nps "); s.Append((pos.GetNodos() * 1000 / (UInt64)elaspsed).ToString()); s.Append(" time "); s.Append(elaspsed); s.Append(" cpuload "); s.Append(Program.m_CPU.Get() * 10); s.Append(" hashfull "); s.Append(cMotor.m_TablaHash.HashFullPercent()); //if (bShow) { if (i > 0) { s.Append(" multipv "); s.Append(i + 1); } s.Append(" pv"); for (int j = 0; RootMoves[i].m_PV.Count > j && RootMoves[i].m_PV[j] != cMovType.MOV_NAN && j < d; ++j) { s.Append(" "); s.Append(cUci.GetMovimiento(RootMoves[i].m_PV[j], pos.IsChess960() != false)); } } } } } return s.ToString(); }
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; }
public void insert_pv_in_tt(cPosicion pos) { cPosInfo[] state = new cPosInfo[cSearch.MAX_PLY_PLUS_6]; int st = 0; for (int i = 0; i < cSearch.MAX_PLY_PLUS_6; i++) state[i] = new cPosInfo(); cTablaHashStruct tte; int idx = 0; do { tte = cMotor.m_TablaHash.Buscar(pos.ClaveHash()); if (tte == null || tte.GetMove() != m_PV[idx]) cMotor.m_TablaHash.Save(pos.ClaveHash(), cValoresJuego.NAN, cBordes.BOUND_NONE, cPly.DEPTH_NONE, m_PV[idx], cValoresJuego.NAN); pos.DoMov(m_PV[idx++], state[st++]); } while (m_PV[idx] != cMovType.MOV_NAN); while (idx != 0) pos.DesMov(m_PV[--idx]); }
public void extract_pv_from_tt(cPosicion pos) { cPosInfo[] estate = new cPosInfo[cSearch.MAX_PLY_PLUS_6]; for (int i = 0; i < cSearch.MAX_PLY_PLUS_6; i++) estate[i] = new cPosInfo(); cTablaHashStruct tte; int st = 0; int ply = 1; mov m = m_PV[0]; val expectedScore = m_nVal; m_PV.Clear(); do { m_PV.Add(m); pos.DoMov(m_PV[ply++ - 1], estate[st++]); tte = cMotor.m_TablaHash.Buscar(pos.ClaveHash()); expectedScore = -expectedScore; } while (tte != null && expectedScore == cSearch.value_from_tt(tte.GetValue(), ply) && pos.IsPseudoLegalMov(m = tte.GetMove()) && pos.IsLegalMov(m, pos.pinned_pieces(pos.ColorMueve())) && ply < cSearch.MAX_PLY && (!pos.IsTablas() || ply <= 2)); m_PV.Add(cMovType.MOV_NAN); while (--ply != 0) pos.DesMov(m_PV[ply - 1]); }
//----------------------------------------------------------------------------------------------- public factor KRPPKRP(cPosicion pos) { sq wnCasillaPeon1 = pos.GetList(m_cFuerte, cPieza.PEON)[0]; sq wnCasillaPeon2 = pos.GetList(m_cFuerte, cPieza.PEON)[1]; sq nCasillaReyNegro = pos.GetRey(m_cDebil); if (pos.IsPeonPasado(m_cFuerte, wnCasillaPeon1) || pos.IsPeonPasado(m_cFuerte, wnCasillaPeon2)) return cFactorEscala.NAN; fila r = Math.Max(cTypes.FilaProxima(m_cFuerte, wnCasillaPeon1), cTypes.FilaProxima(m_cFuerte, wnCasillaPeon2)); if (cBitBoard.ColumDistancia(nCasillaReyNegro, wnCasillaPeon1) <= 1 && cBitBoard.ColumDistancia(nCasillaReyNegro, wnCasillaPeon2) <= 1 && cTypes.FilaProxima(m_cFuerte, nCasillaReyNegro) > r) { switch (r) { case FILA.F2: return (10); case FILA.F3: return (10); case FILA.F4: return (15); case FILA.F5: return (20); case FILA.F6: return (40); default: break; } } return cFactorEscala.NAN; }
//----------------------------------------------------------------------------------------------- public factor KPKP(cPosicion pos) { color colr = m_cFuerte==pos.ColorMueve() ? cColor.BLANCO : cColor.NEGRO; val result = cFactorEscala.TABLAS; if(SetConjuntoPiezasPosicion(pos)) { ProbeResultType pr = cTablaFinales.Probe(whitePieceSquares, blackPieceSquares, whiteTypesSquares, blackTypesSquares, colr, enPassantSquare); if(pr.found) { if(pr.stm==MateResult.MATE_NEGRAS||pr.stm==MateResult.MATE_BLANCAS) result=cFactorEscala.NAN; } } return result; /*sq nCasillaReyBlanco = Normalizar(pos, m_cFuerte, pos.GetRey(m_cFuerte)); sq nCasillaReyNegro = Normalizar(pos, m_cFuerte, pos.GetRey(m_cDebil)); sq nCasillaPeon = Normalizar(pos, m_cFuerte, pos.GetList(m_cFuerte, cPieza.PEON)[0]); color us = m_cFuerte == pos.ColorMueve() ? cColor.BLANCO : cColor.NEGRO; if (cTypes.Fila(nCasillaPeon) >= FILA.F5 && cTypes.Columna(nCasillaPeon) != COLUMNA.A) return cFactorEscala.NAN; return cBitbaseKPK.Buscar(nCasillaReyBlanco, nCasillaPeon, nCasillaReyNegro, us) ? cFactorEscala.NAN : cFactorEscala.TABLAS;*/ }
//----------------------------------------------------------------------------------------------- public val KPK(cPosicion pos) { //sq posReyBlanco = Normalizar(posicion, m_cFuerte, posicion.GetRey(m_cFuerte)); //sq posReyNegro = Normalizar(posicion, m_cFuerte, posicion.GetRey(m_cDebil));*/ //sq casillaFromPos = Normalizar(posicion, m_cFuerte, posicion.GetList(m_cFuerte, cPieza.PEON)[0]); //color colr = m_cFuerte == posicion.ColorMueve() ? cColor.BLANCO : cColor.NEGRO; //if (!cBitbaseKPK.Buscar(posReyBlanco, casillaFromPos, posReyNegro, colr)) // return cValoresJuego.TABLAS; //val result = cValoresJuego.GANA + cValoresJuego.PEON_FINAL + cTypes.Fila(casillaFromPos); //return m_cFuerte == posicion.ColorMueve() ? result : -result;*/ color colr = m_cFuerte==pos.ColorMueve() ? cColor.BLANCO : cColor.NEGRO; val result = cValoresJuego.TABLAS; if(SetConjuntoPiezasPosicion(pos)) { ProbeResultType pr = cTablaFinales.Probe(whitePieceSquares, blackPieceSquares, whiteTypesSquares, blackTypesSquares, colr, enPassantSquare); if(pr.found) { if(pr.stm==MateResult.MATE_NEGRAS||pr.stm==MateResult.MATE_BLANCAS) { if(m_cFuerte==pos.ColorMueve()) result=(cValoresJuego.MATE-pr.ply); else result=-cValoresJuego.MATE+pr.ply; } } } return result; }
//----------------------------------------------------------------------------------------------- public factor KNPKB(cPosicion pos) { sq sqPeon = pos.GetList(m_cFuerte, cPieza.PEON)[0]; sq alfilCasillaPeon = pos.GetList(m_cDebil, cPieza.ALFIL)[0]; sq weakerKingSq = pos.GetRey(m_cDebil); if ((cBitBoard.Atras(m_cFuerte, sqPeon) & pos.attacks_from_square_piecetype(alfilCasillaPeon, cPieza.ALFIL)) != 0) return cBitBoard.Distancia(weakerKingSq, sqPeon); return cFactorEscala.NAN; }
//----------------------------------------------------------------------------------------------- public factor KNPK(cPosicion pos) { sq sqPeon = Normalizar(pos, m_cFuerte, pos.GetList(m_cFuerte, cPieza.PEON)[0]); sq weakKingSq = Normalizar(pos, m_cFuerte, pos.GetRey(m_cDebil)); if (sqPeon == cCasilla.A7 && cBitBoard.Distancia(cCasilla.A8, weakKingSq) <= 1) return cFactorEscala.TABLAS; return cFactorEscala.NAN; }
//----------------------------------------------------------------------------------------------- public val KNNK(cPosicion pos) { return cValoresJuego.TABLAS; }
//----------------------------------------------------------------------------------------------- public factor KBPsK(cPosicion pos) { bitbrd pawns = pos.PiezasColor(m_cFuerte, cPieza.PEON); colum pawnFile = cTypes.Columna(pos.GetList(m_cFuerte, cPieza.PEON)[0]); if ((pawnFile == COLUMNA.A || pawnFile == COLUMNA.H) && 0 == (pawns & ~cBitBoard.GetColumna(pawnFile))) { sq bishonCasillaPeon = pos.GetList(m_cFuerte, cPieza.ALFIL)[0]; sq queeningSq = cTypes.CasillaProxima(m_cFuerte, cTypes.CreaCasilla(pawnFile, FILA.F8)); sq kingSq = pos.GetRey(m_cDebil); if (cTypes.IsColorContrario(queeningSq, bishonCasillaPeon) && cBitBoard.Distancia(queeningSq, kingSq) <= 1) return cFactorEscala.TABLAS; } if ((pawnFile == COLUMNA.B || pawnFile == COLUMNA.G) && 0 == (pos.GetNumPiezas(cPieza.PEON) & ~cBitBoard.GetColumna(pawnFile)) && pos.MaterialPieza(m_cDebil) == 0 && pos.GetNum(m_cDebil, cPieza.PEON) >= 1) { sq weaksqPeon = cBitBoard.backmost_sq(m_cDebil, pos.PiezasColor(m_cDebil, cPieza.PEON)); sq strongKingSq = pos.GetRey(m_cFuerte); sq weakKingSq = pos.GetRey(m_cDebil); sq bishonCasillaPeon = pos.GetList(m_cFuerte, cPieza.ALFIL)[0]; if (cTypes.FilaProxima(m_cFuerte, weaksqPeon) == FILA.F7 && (pos.PiezasColor(m_cFuerte, cPieza.PEON) & cBitBoard.m_nCasillas[(weaksqPeon + cTypes.AtaquePeon(m_cDebil))]) != 0 && (cTypes.IsColorContrario(bishonCasillaPeon, weaksqPeon) || pos.GetNum(m_cFuerte, cPieza.PEON) == 1)) { int strongKingDist = cBitBoard.Distancia(weaksqPeon, strongKingSq); int weakKingDist = cBitBoard.Distancia(weaksqPeon, weakKingSq); if (cTypes.FilaProxima(m_cFuerte, weakKingSq) >= FILA.F7 && weakKingDist <= 2 && weakKingDist <= strongKingDist) return cFactorEscala.TABLAS; } } return cFactorEscala.NAN; }
//----------------------------------------------------------------------------------------------- public factor KRPKB(cPosicion pos) { if ((pos.GetNumPiezas(cPieza.PEON) & (cBitBoard.A | cBitBoard.H)) != 0) { sq ksq = pos.GetRey(m_cDebil); sq bsq = pos.GetList(m_cDebil, cPieza.ALFIL)[0]; sq nCasillaPeon = pos.GetList(m_cFuerte, cPieza.PEON)[0]; fila rk = cTypes.FilaProxima(m_cFuerte, nCasillaPeon); sq push = cTypes.AtaquePeon(m_cFuerte); if (rk == FILA.F5 && !cTypes.IsColorContrario(bsq, nCasillaPeon)) { int d = cBitBoard.Distancia(nCasillaPeon + 3 * push, ksq); if (d <= 2 && !(d == 0 && ksq == pos.GetRey(m_cFuerte) + 2 * push)) return (24); else return (48); } if (rk == FILA.F6 && cBitBoard.Distancia(nCasillaPeon + 2 * push, ksq) <= 1 && (cBitBoard.m_PseudoAtaques[cPieza.ALFIL][bsq] & cBitBoard.m_nCasillas[(nCasillaPeon + push)]) != 0 && cBitBoard.ColumDistancia(bsq, nCasillaPeon) >= 2) return (8); } return cFactorEscala.NAN; }
//----------------------------------------------------------------------------------------------- public factor KRPKR(cPosicion pos) { sq nCasillaReyBlanco = Normalizar(pos, m_cFuerte, pos.GetRey(m_cFuerte)); sq nCasillaReyNegro = Normalizar(pos, m_cFuerte, pos.GetRey(m_cDebil)); sq wnCasillaTorre = Normalizar(pos, m_cFuerte, pos.GetList(m_cFuerte, cPieza.TORRE)[0]); sq wnCasillaPeon = Normalizar(pos, m_cFuerte, pos.GetList(m_cFuerte, cPieza.PEON)[0]); sq bnCasillaTorre = Normalizar(pos, m_cFuerte, pos.GetList(m_cDebil, cPieza.TORRE)[0]); colum f = cTypes.Columna(wnCasillaPeon); fila r = cTypes.Fila(wnCasillaPeon); sq queeningSq = cTypes.CreaCasilla(f, FILA.F8); int tempo = (pos.ColorMueve() == m_cFuerte ? 1 : 0); if (r <= FILA.F5 && cBitBoard.Distancia(nCasillaReyNegro, queeningSq) <= 1 && nCasillaReyBlanco <= cCasilla.H5 && (cTypes.Fila(bnCasillaTorre) == FILA.F6 || (r <= FILA.F3 && cTypes.Fila(wnCasillaTorre) != FILA.F6))) return cFactorEscala.TABLAS; if (r == FILA.F6 && cBitBoard.Distancia(nCasillaReyNegro, queeningSq) <= 1 && cTypes.Fila(nCasillaReyBlanco) + tempo <= FILA.F6 && (cTypes.Fila(bnCasillaTorre) == FILA.F1 || (0 == tempo && Math.Abs(cTypes.Columna(bnCasillaTorre) - f) >= 3))) return cFactorEscala.TABLAS; if (r >= FILA.F6 && nCasillaReyNegro == queeningSq && cTypes.Fila(bnCasillaTorre) == FILA.F1 && (0 == tempo || cBitBoard.Distancia(nCasillaReyBlanco, wnCasillaPeon) >= 2)) return cFactorEscala.TABLAS; if (wnCasillaPeon == cCasilla.A7 && wnCasillaTorre == cCasilla.A8 && (nCasillaReyNegro == cCasilla.H7 || nCasillaReyNegro == cCasilla.G7) && cTypes.Columna(bnCasillaTorre) == COLUMNA.A && (cTypes.Fila(bnCasillaTorre) <= FILA.F3 || cTypes.Columna(nCasillaReyBlanco) >= COLUMNA.D || cTypes.Fila(nCasillaReyBlanco) <= FILA.F5)) return cFactorEscala.TABLAS; if (r <= FILA.F5 && nCasillaReyNegro == wnCasillaPeon + cCasilla.NORTE && cBitBoard.Distancia(nCasillaReyBlanco, wnCasillaPeon) - tempo >= 2 && cBitBoard.Distancia(nCasillaReyBlanco, bnCasillaTorre) - tempo >= 2) return cFactorEscala.TABLAS; if (r == FILA.F7 && f != COLUMNA.A && cTypes.Columna(wnCasillaTorre) == f && wnCasillaTorre != queeningSq && (cBitBoard.Distancia(nCasillaReyBlanco, queeningSq) < cBitBoard.Distancia(nCasillaReyNegro, queeningSq) - 2 + tempo) && (cBitBoard.Distancia(nCasillaReyBlanco, queeningSq) < cBitBoard.Distancia(nCasillaReyNegro, wnCasillaTorre) + tempo)) return (factor)(cFactorEscala.MAXIMO - 2 * cBitBoard.Distancia(nCasillaReyBlanco, queeningSq)); if (f != COLUMNA.A && cTypes.Columna(wnCasillaTorre) == f && wnCasillaTorre < wnCasillaPeon && (cBitBoard.Distancia(nCasillaReyBlanco, queeningSq) < cBitBoard.Distancia(nCasillaReyNegro, queeningSq) - 2 + tempo) && (cBitBoard.Distancia(nCasillaReyBlanco, wnCasillaPeon + cCasilla.NORTE) < cBitBoard.Distancia(nCasillaReyNegro, wnCasillaPeon + cCasilla.NORTE) - 2 + tempo) && (cBitBoard.Distancia(nCasillaReyNegro, wnCasillaTorre) + tempo >= 3 || (cBitBoard.Distancia(nCasillaReyBlanco, queeningSq) < cBitBoard.Distancia(nCasillaReyNegro, wnCasillaTorre) + tempo && (cBitBoard.Distancia(nCasillaReyBlanco, wnCasillaPeon + cCasilla.NORTE) < cBitBoard.Distancia(nCasillaReyNegro, wnCasillaTorre) + tempo)))) return (factor)(cFactorEscala.MAXIMO - 8 * cBitBoard.Distancia(wnCasillaPeon, queeningSq) - 2 * cBitBoard.Distancia(nCasillaReyBlanco, queeningSq)); if (r <= FILA.F4 && nCasillaReyNegro > wnCasillaPeon) { if (cTypes.Columna(nCasillaReyNegro) == cTypes.Columna(wnCasillaPeon)) return 10; if (Math.Abs(cTypes.Columna(nCasillaReyNegro) - cTypes.Columna(wnCasillaPeon)) == 1 && cBitBoard.Distancia(nCasillaReyBlanco, nCasillaReyNegro) > 2) return (24 - 2 * cBitBoard.Distancia(nCasillaReyBlanco, nCasillaReyNegro)); } return cFactorEscala.NAN; }
//----------------------------------------------------------------------------------------------- public factor KPsK(cPosicion pos) { sq ksq = pos.GetRey(m_cDebil); bitbrd pawns = pos.PiezasColor(m_cFuerte, cPieza.PEON); sq nCasillaPeon = pos.GetList(m_cFuerte, cPieza.PEON)[0]; if (0 == (pawns & ~cBitBoard.EnFrente(m_cDebil, cTypes.Fila(ksq))) && !((pawns & ~cBitBoard.A) != 0 && (pawns & ~cBitBoard.H) != 0) && cBitBoard.ColumDistancia(ksq, nCasillaPeon) <= 1) return cFactorEscala.TABLAS; return cFactorEscala.NAN; }
//----------------------------------------------------------------------------------------------- public val KXK(cPosicion pos) { if (pos.ColorMueve() == m_cDebil && 0 == (new cReglas(pos, cMovType.LEGAL)).Size()) return cValoresJuego.TABLAS; sq posReyGanador = pos.GetRey(m_cFuerte); sq posReyPerdedor = pos.GetRey(m_cDebil); val result = pos.MaterialPieza(m_cFuerte) + pos.GetNum(m_cFuerte, cPieza.PEON) * cValoresJuego.PEON_FINAL + m_lstValorBorde[posReyPerdedor] + m_lstValorCerrado[cBitBoard.Distancia(posReyGanador, posReyPerdedor)]; if (pos.GetNum(m_cFuerte, cPieza.DAMA) != 0 || pos.GetNum(m_cFuerte, cPieza.TORRE) != 0 || (pos.GetNum(m_cFuerte, cPieza.ALFIL) != 0 && pos.GetNum(m_cFuerte, cPieza.CABALLO) != 0) || pos.IsAlfilPar(m_cFuerte)) { result += cValoresJuego.GANA; } return m_cFuerte == pos.ColorMueve() ? result : -result; }
//----------------------------------------------------------------------------------------------- public val KQKP(cPosicion pos) { sq nCasillaReyGanador = pos.GetRey(m_cFuerte); sq nCasillaReyPerdedor = pos.GetRey(m_cDebil); sq nCasillaPeon = pos.GetList(m_cDebil, cPieza.PEON)[0]; val result = (m_lstValorCerrado[cBitBoard.Distancia(nCasillaReyGanador, nCasillaReyPerdedor)]); if (cTypes.FilaProxima(m_cDebil, nCasillaPeon) != FILA.F7 || cBitBoard.Distancia(nCasillaReyPerdedor, nCasillaPeon) != 1 || 0 == ((cBitBoard.A | cBitBoard.C | cBitBoard.F | cBitBoard.H) & cBitBoard.m_nCasillas[nCasillaPeon])) result += cValoresJuego.DAMA_FINAL - cValoresJuego.PEON_FINAL; return m_cFuerte == pos.ColorMueve() ? result : -result; }
public static void update_stats(cPosicion pos, cStackMov[] ss, int ssPos, mov move, ply depth, mov[] quiets, int quietsCnt) { if (ss[ssPos].killers0 != move) { ss[ssPos].killers1 = ss[ssPos].killers0; ss[ssPos].killers0 = move; } val bonus = ((depth) * (depth)); History.Fill(pos.GetPiezaMovida(move), cTypes.GetToCasilla(move), bonus); for (int i = 0; i < quietsCnt; ++i) { mov m = quiets[i]; History.Fill(pos.GetPiezaMovida(m), cTypes.GetToCasilla(m), -bonus); } if (cTypes.is_ok_move(ss[ssPos - 1].currentMove)) { sq prevMoveSq = cTypes.GetToCasilla(ss[ssPos - 1].currentMove); Countermoves.Fill(pos.GetPieza(prevMoveSq), prevMoveSq, move); } if (cTypes.is_ok_move(ss[ssPos - 2].currentMove) && ss[ssPos - 1].currentMove == ss[ssPos - 1].ttMove) { sq prevOwnMoveSq = cTypes.GetToCasilla(ss[ssPos - 2].currentMove); Followupmoves.Fill(pos.GetPieza(prevOwnMoveSq), prevOwnMoveSq, move); } }
//----------------------------------------------------------------------------------------------- public val KQKR(cPosicion pos) { color colr = m_cFuerte==pos.ColorMueve() ? cColor.BLANCO : cColor.NEGRO; val result = cValoresJuego.TABLAS; if(SetConjuntoPiezasPosicion(pos)) { ProbeResultType pr = cTablaFinales.Probe(whitePieceSquares, blackPieceSquares, whiteTypesSquares, blackTypesSquares, colr, enPassantSquare); if(pr.found) { if(pr.stm==MateResult.MATE_NEGRAS||pr.stm==MateResult.MATE_BLANCAS) { if (m_cFuerte==pos.ColorMueve()) result=(cValoresJuego.MATE-pr.ply); else result=-cValoresJuego.MATE+pr.ply; } } } return result; /*sq winnerKSq = pos.GetRey(m_cFuerte); sq loserKSq = pos.GetRey(m_cDebil); val result = cValoresJuego.DAMA_FINAL - cValoresJuego.TORRE_FINAL + m_lstValorBorde[loserKSq] + m_lstValorCerrado[cBitBoard.Distancia(winnerKSq, loserKSq)]; return m_cFuerte == pos.ColorMueve() ? result : -result;*/ }
public static void id_loop(cPosicion pos) { cStackMov[] stack = new cStackMov[cSearch.MAX_PLY_PLUS_6]; int ss = 2; ply depth; val bestValue, alpha, beta, delta; for (int i = 0; i < cSearch.MAX_PLY_PLUS_6; i++) stack[i] = new cStackMov(); stack[ss - 1].currentMove = cMovType.MOV_NULO; depth = 0; BestMoveChanges = 0; bestValue = delta = alpha = -cValoresJuego.INFINITO; beta = cValoresJuego.INFINITO; cMotor.m_TablaHash.NewIteraccion(); History.Clear(); Gains.Clear(); Countermoves.Clear(); Followupmoves.Clear(); MultiPV = cMotor.m_mapConfig["MultiPV"].Get(); MultiPV = Math.Min(MultiPV, RootMoves.Count); while (++depth <= cSearch.MAX_PLY && !Signals.STOP && (0 == Limits.depth || depth <= Limits.depth)) { BestMoveChanges *= 0.5; for (int i = 0; i < RootMoves.Count; ++i) RootMoves[i].m_LastVal = RootMoves[i].m_nVal; for (PVIdx = 0; PVIdx < MultiPV && !Signals.STOP; ++PVIdx) { if (depth >= 5) { delta = 16; alpha = Math.Max(RootMoves[PVIdx].m_LastVal - delta, -cValoresJuego.INFINITO); beta = Math.Min(RootMoves[PVIdx].m_LastVal + delta, cValoresJuego.INFINITO); } while (true) { bestValue = search(pos, stack, ss, alpha, beta, depth * cPly.ONE_PLY, false, cTipoNodo.RAIZ, false); cRaizMov.Ordenar(RootMoves, PVIdx, RootMoves.Count); for (int i = 0; i <= PVIdx; ++i) RootMoves[i].insert_pv_in_tt(pos); if (Signals.STOP) break; if ((bestValue <= alpha || bestValue >= beta)/* && (cReloj.Now() - SearchTime) > 1000*/) cMotor.m_Consola.PrintLine(uci_pv(pos, depth, alpha, beta), AccionConsola.ATOMIC); if (bestValue <= alpha) { alpha = Math.Max(bestValue - delta, -cValoresJuego.INFINITO); Signals.FAILED = true; Signals.STOP_ON_PONDER = false; } else if (bestValue >= beta) beta = Math.Min(bestValue + delta, cValoresJuego.INFINITO); else break; delta += delta / 2; } cRaizMov.Ordenar(RootMoves, 0, PVIdx + 1); //if ((PVIdx + 1 == MultiPV && MultiPV > 1) || (cReloj.Now() - SearchTime) > 1000) cMotor.m_Consola.PrintLine(uci_pv(pos, depth, alpha, beta), AccionConsola.ATOMIC); } if (Limits.mate != 0 && bestValue >= cValoresJuego.MATE_MAXIMO && cValoresJuego.MATE - bestValue <= 2 * Limits.mate) Signals.STOP = true; if (Limits.ControlDeTiempoDefinido() && !Signals.STOP && !Signals.STOP_ON_PONDER) { if (depth > 10 && depth < 50 && MultiPV == 1) TimeMgr.Inestabilidad(BestMoveChanges); if (RootMoves.Count == 1 || cReloj.Now() - SearchTime > TimeMgr.Disponible()) { if (Limits.ponder != 0) Signals.STOP_ON_PONDER = true; else Signals.STOP = true; } } } }
//----------------------------------------------------------------------------------------------- public factor KQKRPs(cPosicion pos) { sq kingSq = pos.GetRey(m_cDebil); sq nCasillaTorre = pos.GetList(m_cDebil, cPieza.TORRE)[0]; if (cTypes.FilaProxima(m_cDebil, kingSq) <= FILA.F2 && cTypes.FilaProxima(m_cDebil, pos.GetRey(m_cFuerte)) >= FILA.F4 && cTypes.FilaProxima(m_cDebil, nCasillaTorre) == FILA.F3 && (pos.PiezasColor(m_cDebil, cPieza.PEON) & pos.attacks_from_square_piecetype(kingSq, cPieza.REY) & pos.AtaquesDePeon(nCasillaTorre, m_cFuerte)) != 0) return cFactorEscala.TABLAS; return cFactorEscala.NAN; }
public static val search(cPosicion pos, cStackMov[] ss, int ssPos, val alpha, val beta, ply depth, bool cutNode, NodeType NT, bool SpNode) { bool RootNode = (NT == cTipoNodo.RAIZ); bool PvNode = (NT == cTipoNodo.PV || NT == cTipoNodo.RAIZ); mov[] quietsSearched = new mov[64]; cPosInfo st = new cPosInfo(); cTablaHashStruct tte; cSplitPoint splitPoint = null; hash posKey = 0; mov ttMove, move, excludedMove, bestMove; ply ext, newDepth, predictedDepth; val bestValue, value, ttValue, eval, nullValue, futilityValue; bool inCheck, givesCheck, pvMove, singularExtensionNode, improving; bool captureOrPromotion, dangerous, doFullDepthSearch; int moveCount = 0, quietCount = 0; cThread thisThread = pos.ThreadActive(); inCheck = pos.Jaques() != 0; if (SpNode) { splitPoint = ss[ssPos].splitPoint; bestMove = splitPoint.bestMove; bestValue = splitPoint.bestValue; tte = null; ttMove = excludedMove = cMovType.MOV_NAN; ttValue = cValoresJuego.NAN; goto moves_loop; } moveCount = quietCount = 0; bestValue = -cValoresJuego.INFINITO; ss[ssPos].currentMove = ss[ssPos].ttMove = ss[ssPos + 1].excludedMove = bestMove = cMovType.MOV_NAN; ss[ssPos].ply = ss[ssPos - 1].ply + 1; ss[ssPos + 1].skipNullMove = 0; ss[ssPos + 1].reduction = cPly.DEPTH_ZERO; ss[ssPos + 2].killers0 = ss[ssPos + 2].killers1 = cMovType.MOV_NAN; if (PvNode && thisThread.m_nMaxPly < ss[ssPos].ply) thisThread.m_nMaxPly = ss[ssPos].ply; if (!RootNode) { if (Signals.STOP || pos.IsTablas() || ss[ssPos].ply > cSearch.MAX_PLY) return ss[ssPos].ply > cSearch.MAX_PLY && !inCheck ? cEval.Eval(pos) : DrawValue[pos.ColorMueve()]; alpha = Math.Max(cTypes.MateEnVs(ss[ssPos].ply), alpha); beta = Math.Min(cTypes.MateEn(ss[ssPos].ply + 1), beta); if (alpha >= beta) return alpha; } excludedMove = ss[ssPos].excludedMove; posKey = excludedMove != 0 ? pos.GetClaveHashExclusion() : pos.ClaveHash(); tte = cMotor.m_TablaHash.Buscar(posKey); ss[ssPos].ttMove = ttMove = RootNode ? RootMoves[PVIdx].m_PV[0] : tte != null ? tte.GetMove() : cMovType.MOV_NAN; ttValue = (tte != null) ? value_from_tt(tte.GetValue(), ss[ssPos].ply) : cValoresJuego.NAN; if (!RootNode && tte != null && tte.GetDepth() >= depth && 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; if (ttValue >= beta && ttMove != 0 && !pos.IsCapturaOrPromocion(ttMove) && !inCheck) update_stats(pos, ss, ssPos, ttMove, depth, null, 0); return ttValue; } if (inCheck) { ss[ssPos].staticEval = eval = cValoresJuego.NAN; goto moves_loop; } else if (tte != null) { if ((ss[ssPos].staticEval = eval = tte.GetValueEval()) == cValoresJuego.NAN) eval = ss[ssPos].staticEval = cEval.Eval(pos); if (ttValue != cValoresJuego.NAN) if ((tte.GetBound() & (ttValue > eval ? cBordes.BOUND_LOWER : cBordes.BOUND_UPPER)) != 0) eval = ttValue; } else { eval = ss[ssPos].staticEval = cEval.Eval(pos); cMotor.m_TablaHash.Save(posKey, cValoresJuego.NAN, cBordes.BOUND_NONE, cPly.DEPTH_NONE, cMovType.MOV_NAN, ss[ssPos].staticEval); } if (0 == pos.GetTipoPiezaCapturada() && ss[ssPos].staticEval != cValoresJuego.NAN && ss[ssPos - 1].staticEval != cValoresJuego.NAN && (move = ss[ssPos - 1].currentMove) != cMovType.MOV_NULO && cTypes.TipoMovimiento(move) == cMovType.NORMAL) { sq to = cTypes.GetToCasilla(move); Gains.Fill(pos.GetPieza(to), to, -ss[ssPos - 1].staticEval - ss[ssPos].staticEval); } if (!PvNode && depth < 4 * cPly.ONE_PLY && eval + razor_margin(depth) <= beta && ttMove == cMovType.MOV_NAN && Math.Abs(beta) < cValoresJuego.MATE_MAXIMO && !pos.IsPeonOn7(pos.ColorMueve()) ) { if (depth <= cPly.ONE_PLY && eval + razor_margin(3 * cPly.ONE_PLY) <= alpha) return qsearch(pos, ss, ssPos, alpha, beta, cPly.DEPTH_ZERO, cTipoNodo.NO_PV, false); val ralpha = alpha - razor_margin(depth); val v = qsearch(pos, ss, ssPos, ralpha, ralpha + 1, cPly.DEPTH_ZERO, cTipoNodo.NO_PV, false); if (v <= ralpha) return v; } if (!PvNode && 0 == ss[ssPos].skipNullMove && depth < 7 * cPly.ONE_PLY && eval - futility_margin(depth) >= beta && Math.Abs(beta) < cValoresJuego.MATE_MAXIMO && Math.Abs(eval) < cValoresJuego.GANA && pos.MaterialPieza(pos.ColorMueve()) != 0) return eval - futility_margin(depth); if (!PvNode && 0 == ss[ssPos].skipNullMove && depth >= 2 * cPly.ONE_PLY && eval >= beta && Math.Abs(beta) < cValoresJuego.MATE_MAXIMO && pos.MaterialPieza(pos.ColorMueve()) != 0) { ss[ssPos].currentMove = cMovType.MOV_NULO; ply R = 3 * cPly.ONE_PLY + depth / 4 + (eval - beta) / cValoresJuego.PEON_MJ * cPly.ONE_PLY; pos.DoNullMov(st); ss[ssPos + 1].skipNullMove = 1; nullValue = depth - R < cPly.ONE_PLY ? -qsearch(pos, ss, ssPos + 1, -beta, -beta + 1, cPly.DEPTH_ZERO, cTipoNodo.NO_PV, false) : -search(pos, ss, ssPos + 1, -beta, -beta + 1, depth - R, !cutNode, cTipoNodo.NO_PV, false); ss[ssPos + 1].skipNullMove = 0; pos.undo_null_move(); if (nullValue >= beta) { if (nullValue >= cValoresJuego.MATE_MAXIMO) nullValue = beta; if (depth < 12 * cPly.ONE_PLY) return nullValue; ss[ssPos].skipNullMove = 1; val v = depth - R < cPly.ONE_PLY ? qsearch(pos, ss, ssPos, beta - 1, beta, cPly.DEPTH_ZERO, cTipoNodo.NO_PV, false) : search(pos, ss, ssPos, beta - 1, beta, depth - R, false, cTipoNodo.NO_PV, false); ss[ssPos].skipNullMove = 0; if (v >= beta) return nullValue; } } if (!PvNode && depth >= 5 * cPly.ONE_PLY && 0 == ss[ssPos].skipNullMove && Math.Abs(beta) < cValoresJuego.MATE_MAXIMO) { val rbeta = Math.Min(beta + 200, cValoresJuego.INFINITO); ply rdepth = depth - 4 * cPly.ONE_PLY; cMovOrder mp2 = new cMovOrder(pos, ttMove, History, pos.GetTipoPiezaCapturada()); cInfoJaque ci2 = new cInfoJaque(pos); while ((move = mp2.SiguienteMovimientoEnFalso()) != cMovType.MOV_NAN) if (pos.IsLegalMov(move, ci2.m_Clavadas)) { ss[ssPos].currentMove = move; pos.DoMov(move, st, ci2, pos.IsJaque(move, ci2)); value = -search(pos, ss, ssPos + 1, -rbeta, -rbeta + 1, rdepth, !cutNode, cTipoNodo.NO_PV, false); pos.DesMov(move); if (value >= rbeta) return value; } } if (depth >= (PvNode ? 5 * cPly.ONE_PLY : 8 * cPly.ONE_PLY) && 0 == ttMove && (PvNode || (ss[ssPos].staticEval + 256 >= beta))) { ply d = depth - 2 * cPly.ONE_PLY - (PvNode ? cPly.DEPTH_ZERO : depth / 4); ss[ssPos].skipNullMove = 1; search(pos, ss, ssPos, alpha, beta, d, true, PvNode ? cTipoNodo.PV : cTipoNodo.NO_PV, false); ss[ssPos].skipNullMove = 0; tte = cMotor.m_TablaHash.Buscar(posKey); ttMove = (tte != null) ? tte.GetMove() : cMovType.MOV_NAN; } moves_loop: sq prevMoveSq = cTypes.GetToCasilla(ss[ssPos - 1].currentMove); mov[] countermoves = { Countermoves[pos.GetPieza(prevMoveSq)][prevMoveSq].m_Key1, Countermoves[pos.GetPieza(prevMoveSq)][prevMoveSq].m_Key2 }; sq prevOwnMoveSq = cTypes.GetToCasilla(ss[ssPos - 2].currentMove); mov[] followupmoves = {Followupmoves[pos.GetPieza(prevOwnMoveSq)][prevOwnMoveSq].m_Key1, Followupmoves[pos.GetPieza(prevOwnMoveSq)][prevOwnMoveSq].m_Key2 }; cMovOrder mp = new cMovOrder(pos, ttMove, depth, History, countermoves, followupmoves, ss[ssPos]); cInfoJaque ci = new cInfoJaque(pos); value = bestValue; improving = ss[ssPos].staticEval >= ss[ssPos - 2].staticEval || ss[ssPos].staticEval == cValoresJuego.NAN || ss[ssPos - 2].staticEval == cValoresJuego.NAN; singularExtensionNode = !RootNode && !SpNode && depth >= 8 * cPly.ONE_PLY && ttMove != cMovType.MOV_NAN && 0 == excludedMove && (tte.GetBound() & cBordes.BOUND_LOWER) != 0 && tte.GetDepth() >= depth - 3 * cPly.ONE_PLY; while ((move = (SpNode ? mp.SiguienteMovimiento() : mp.SiguienteMovimientoEnFalso())) != cMovType.MOV_NAN) { if (move == excludedMove) continue; if (RootNode && (Buscar(RootMoves, PVIdx, RootMoves.Count, move) == -1)) continue; if (SpNode) { if (!pos.IsLegalMov(move, ci.m_Clavadas)) continue; moveCount = ++splitPoint.moveCount; splitPoint.mutex.Liberar(); } else ++moveCount; if (RootNode) { Signals.FIRST_MOVE = (moveCount == 1); } ext = cPly.DEPTH_ZERO; captureOrPromotion = pos.IsCapturaOrPromocion(move); 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); dangerous = givesCheck || cTypes.TipoMovimiento(move) != cMovType.NORMAL || pos.IsPeonAvanzado(move); if (givesCheck && pos.SEEReducido(move) >= cValoresJuego.CERO) ext = cPly.ONE_PLY; if (singularExtensionNode && move == ttMove && 0 == ext && pos.IsLegalMov(move, ci.m_Clavadas) && Math.Abs(ttValue) < cValoresJuego.GANA) { val rBeta = ttValue - depth; ss[ssPos].excludedMove = move; ss[ssPos].skipNullMove = 1; value = search(pos, ss, ssPos, rBeta - 1, rBeta, depth / 2, cutNode, cTipoNodo.NO_PV, false); ss[ssPos].skipNullMove = 0; ss[ssPos].excludedMove = cMovType.MOV_NAN; if (value < rBeta) ext = cPly.ONE_PLY; } newDepth = depth - cPly.ONE_PLY + ext; if (!PvNode && !captureOrPromotion && !inCheck && !dangerous && bestValue > cValoresJuego.MATE_MAXIMO_VS) { if (depth < 16 * cPly.ONE_PLY && moveCount >= FutilityMoveCounts[improving ? 1 : 0][depth]) { if (SpNode) splitPoint.mutex.Bloquear(); continue; } predictedDepth = newDepth - reduction(improving ? 1 : 0, depth, moveCount, PvNode ? 1 : 0); if (predictedDepth < 7 * cPly.ONE_PLY) { futilityValue = ss[ssPos].staticEval + futility_margin(predictedDepth) + 128 + Gains[pos.GetPiezaMovida(move)][cTypes.GetToCasilla(move)]; if (futilityValue <= alpha) { bestValue = Math.Max(bestValue, futilityValue); if (SpNode) { splitPoint.mutex.Bloquear(); if (bestValue > splitPoint.bestValue) splitPoint.bestValue = bestValue; } continue; } } if (predictedDepth < 4 * cPly.ONE_PLY && pos.SEEReducido(move) < cValoresJuego.CERO) { if (SpNode) splitPoint.mutex.Bloquear(); continue; } } if (!RootNode && !SpNode && !pos.IsLegalMov(move, ci.m_Clavadas)) { moveCount--; continue; } pvMove = PvNode && moveCount == 1; ss[ssPos].currentMove = move; if (!SpNode && !captureOrPromotion && quietCount < 64) quietsSearched[quietCount++] = move; pos.DoMov(move, st, ci, givesCheck); if (depth >= 3 * cPly.ONE_PLY && !pvMove && !captureOrPromotion && move != ttMove && move != ss[ssPos].killers0 && move != ss[ssPos].killers1) { ss[ssPos].reduction = reduction(improving ? 1 : 0, depth, moveCount, PvNode ? 1 : 0); if (!PvNode && cutNode) ss[ssPos].reduction += cPly.ONE_PLY; else if (History[pos.GetPieza(cTypes.GetToCasilla(move))][cTypes.GetToCasilla(move)] < 0) ss[ssPos].reduction += cPly.ONE_PLY / 2; if (move == countermoves[0] || move == countermoves[1]) ss[ssPos].reduction = Math.Max(cPly.DEPTH_ZERO, ss[ssPos].reduction - cPly.ONE_PLY); ply d = Math.Max(newDepth - ss[ssPos].reduction, cPly.ONE_PLY); if (SpNode) alpha = splitPoint.alpha; value = -search(pos, ss, ssPos + 1, -(alpha + 1), -alpha, d, true, cTipoNodo.NO_PV, false); if (value > alpha && ss[ssPos].reduction >= 4 * cPly.ONE_PLY) { ply d2 = Math.Max(newDepth - 2 * cPly.ONE_PLY, cPly.ONE_PLY); value = -search(pos, ss, ssPos + 1, -(alpha + 1), -alpha, d2, true, cTipoNodo.NO_PV, false); } doFullDepthSearch = (value > alpha && ss[ssPos].reduction != cPly.DEPTH_ZERO); ss[ssPos].reduction = cPly.DEPTH_ZERO; } else doFullDepthSearch = !pvMove; if (doFullDepthSearch) { if (SpNode) alpha = splitPoint.alpha; value = newDepth < cPly.ONE_PLY ? givesCheck ? -qsearch(pos, ss, ssPos + 1, -(alpha + 1), -alpha, cPly.DEPTH_ZERO, cTipoNodo.NO_PV, true) : -qsearch(pos, ss, ssPos + 1, -(alpha + 1), -alpha, cPly.DEPTH_ZERO, cTipoNodo.NO_PV, false) : -search(pos, ss, ssPos + 1, -(alpha + 1), -alpha, newDepth, !cutNode, cTipoNodo.NO_PV, false); } if (PvNode && (pvMove || (value > alpha && (RootNode || value < beta)))) value = newDepth < cPly.ONE_PLY ? givesCheck ? -qsearch(pos, ss, ssPos + 1, -beta, -alpha, cPly.DEPTH_ZERO, cTipoNodo.PV, true) : -qsearch(pos, ss, ssPos + 1, -beta, -alpha, cPly.DEPTH_ZERO, cTipoNodo.PV, false) : -search(pos, ss, ssPos + 1, -beta, -alpha, newDepth, false, cTipoNodo.PV, false); pos.DesMov(move); if (SpNode) { splitPoint.mutex.Bloquear(); bestValue = splitPoint.bestValue; alpha = splitPoint.alpha; } if (Signals.STOP || thisThread.IsCorte()) return cValoresJuego.CERO; if (RootNode) { int rmPos = Buscar(RootMoves, 0, RootMoves.Count, move); cRaizMov rm = RootMoves[rmPos]; if (pvMove || value > alpha) { rm.m_nVal = value; rm.extract_pv_from_tt(pos); if (!pvMove) ++BestMoveChanges; } else rm.m_nVal = -cValoresJuego.INFINITO; } if (value > bestValue) { bestValue = SpNode ? splitPoint.bestValue = value : value; if (value > alpha) { bestMove = SpNode ? splitPoint.bestMove = move : move; if (PvNode && value < beta) alpha = SpNode ? splitPoint.alpha = value : value; else { if (SpNode) splitPoint.m_bCorte = true; break; } } } if (!SpNode && cMotor.m_Threads.Count >= 2 && depth >= cMotor.m_Threads.minimumSplitDepth && (null == thisThread.m_SplitPointActivo || !thisThread.m_SplitPointActivo.allSlavesSearching) && thisThread.m_nSplitPointSize < cThreadBase.MAX_SPLITPOINTS_PER_THREAD) { thisThread.Split(pos, ss, ssPos, alpha, beta, ref bestValue, ref bestMove, depth, moveCount, mp, NT, cutNode); if (Signals.STOP || thisThread.IsCorte()) return cValoresJuego.CERO; if (bestValue >= beta) break; } } if (SpNode) return bestValue; if (0 == moveCount) bestValue = excludedMove != 0 ? alpha : inCheck ? cTypes.MateEnVs(ss[ssPos].ply) : DrawValue[pos.ColorMueve()]; else if (bestValue >= beta && !pos.IsCapturaOrPromocion(bestMove) && !inCheck) update_stats(pos, ss, ssPos, bestMove, depth, quietsSearched, quietCount - 1); cMotor.m_TablaHash.Save(posKey, value_to_tt(bestValue, ss[ssPos].ply), bestValue >= beta ? cBordes.BOUND_LOWER : PvNode && bestMove != 0 ? cBordes.BOUND_EXACT : cBordes.BOUND_UPPER, depth, bestMove, ss[ssPos].staticEval); return bestValue; }
//----------------------------------------------------------------------------------------------- public val KRKB(cPosicion pos) { color colr = m_cFuerte==pos.ColorMueve() ? cColor.BLANCO : cColor.NEGRO; val result = cValoresJuego.TABLAS; if(SetConjuntoPiezasPosicion(pos)) { ProbeResultType pr = cTablaFinales.Probe(whitePieceSquares, blackPieceSquares, whiteTypesSquares, blackTypesSquares, colr, enPassantSquare); if(pr.found) { if(pr.stm==MateResult.MATE_NEGRAS||pr.stm==MateResult.MATE_BLANCAS) { if(m_cFuerte==pos.ColorMueve()) result=(cValoresJuego.MATE-pr.ply); else result=-cValoresJuego.MATE+pr.ply; } } } return result; //val result = (m_lstValorBorde[pos.GetRey(m_cDebil)]); //return m_cFuerte == pos.ColorMueve() ? result : -result; }
//------------------------------------------------------------------------------------ public static hash PolyglotKey(cPosicion posicion) { hash key = 0; bitbrd bitBoard = posicion.Piezas(); while (bitBoard != 0) { sq s = cBitBoard.GetLSB(ref bitBoard); pieza pc = posicion.GetPieza(s); int pieceOfs = 2 * (cTypes.TipoPieza(pc) - 1) + ((cTypes.GetColor(pc) == cColor.BLANCO) ? 1 : 0); key ^= PG[nCasillaPeon + (64 * pieceOfs + s)]; } bitBoard = (ulong)posicion.PosibleEnrocar(cEnroque.CUALQUIER_ENROQUE); while (bitBoard != 0) key ^= PG[m_nEnroque + cBitBoard.GetLSB(ref bitBoard)]; if (posicion.CasillaEnPaso() != cCasilla.NONE) key ^= PG[m_nEnPaso + cTypes.Columna(posicion.CasillaEnPaso())]; if (posicion.ColorMueve() == cColor.BLANCO) key ^= PG[m_nTurno + 0]; return key; }
//----------------------------------------------------------------------------------------------- public val KRKN(cPosicion pos) { sq nCasillaReyNegro = pos.GetRey(m_cDebil); sq nCasillaCaballo = pos.GetList(m_cDebil, cPieza.CABALLO)[0]; val result = (m_lstValorBorde[nCasillaReyNegro] + m_lstValorLejania[cBitBoard.Distancia(nCasillaReyNegro, nCasillaCaballo)]); return m_cFuerte == pos.ColorMueve() ? result : -result; }
//--------------------------------------------------------------------------------------------- public static void Test() { cControlReloj limits = new cControlReloj(); List<string> posicionesFEN = new List<string>(); m_mapConfig["Hash"].setCurrentValue("128"); m_TablaHash.Clear(); m_mapConfig["Threads"].setCurrentValue("8"); //-- Tiempo en milisegundos limits.movetime = 1000 * 10; posicionesFEN.AddRange(Defaults); Int64 nodes = 0; Stack<cPosInfo> st = new Stack<cPosInfo>(); long elapsed = cReloj.Now(); for (int i = 0; i < posicionesFEN.Count; ++i) { cPosicion posicion = new cPosicion(posicionesFEN[i], m_mapConfig["UCI_Chess960"].Get() != 0 ? true : false, m_Threads.Principal()); m_Consola.Print(cTypes.LF + (i + 1).ToString() + "/" + posicionesFEN.Count.ToString() + ": ", AccionConsola.NADA); m_Consola.Print(posicionesFEN[i], AccionConsola.NADA); m_Consola.Print(cTypes.LF, AccionConsola.NADA); m_Threads.Analizando(posicion, limits, st); m_Threads.WaitAnalizando(); nodes += (Int64)cSearch.RootPos.GetNodos(); } elapsed = cReloj.Now() - elapsed + 1; m_Consola.Print(cTypes.LF + "===========================", AccionConsola.NADA); m_Consola.Print(cTypes.LF + "Tiempo transcurrido: " + elapsed.ToString(), AccionConsola.NADA); m_Consola.Print(cTypes.LF + "Nodos analizados : " + nodes.ToString(), AccionConsola.NADA); }
//----------------------------------------------------------------------------------------------- public val KRKP(cPosicion pos) { val result = 0; sq nCasillaReyBlanco = cTypes.CasillaProxima(m_cFuerte, pos.GetRey(m_cFuerte)); sq nCasillaReyNegro = cTypes.CasillaProxima(m_cFuerte, pos.GetRey(m_cDebil)); sq nCasillaTorre = cTypes.CasillaProxima(m_cFuerte, pos.GetList(m_cFuerte, cPieza.TORRE)[0]); sq nCasillaPeon = cTypes.CasillaProxima(m_cFuerte, pos.GetList(m_cDebil, cPieza.PEON)[0]); sq nCasillaCoronacion = cTypes.CreaCasilla(cTypes.Columna(nCasillaPeon), FILA.F1); if (nCasillaReyBlanco < nCasillaPeon && cTypes.Columna(nCasillaReyBlanco) == cTypes.Columna(nCasillaPeon)) result = cValoresJuego.TORRE_FINAL - (cBitBoard.Distancia(nCasillaReyBlanco, nCasillaPeon)); else if (cBitBoard.Distancia(nCasillaReyNegro, nCasillaPeon) >= 3 + ((pos.ColorMueve() == m_cDebil) ? 1 : 0) && cBitBoard.Distancia(nCasillaReyNegro, nCasillaTorre) >= 3) result = cValoresJuego.TORRE_FINAL - (cBitBoard.Distancia(nCasillaReyBlanco, nCasillaPeon)); else if (cTypes.Fila(nCasillaReyNegro) <= FILA.F3 && cBitBoard.Distancia(nCasillaReyNegro, nCasillaPeon) == 1 && cTypes.Fila(nCasillaReyBlanco) >= FILA.F4 && cBitBoard.Distancia(nCasillaReyBlanco, nCasillaPeon) > 2 + ((pos.ColorMueve() == m_cFuerte) ? 1 : 0)) result = 80 - 8 * cBitBoard.Distancia(nCasillaReyBlanco, nCasillaPeon); else result = (val)(200) - 8 * (cBitBoard.Distancia(nCasillaReyBlanco, nCasillaPeon + cCasilla.SUR) - cBitBoard.Distancia(nCasillaReyNegro, nCasillaPeon + cCasilla.SUR) - cBitBoard.Distancia(nCasillaPeon, nCasillaCoronacion)); return m_cFuerte == pos.ColorMueve() ? result : -result; }