diff --git a/.github/workflows/hexchess-board-pages.yml b/.github/workflows/hexchess-board-pages.yml new file mode 100644 index 00000000..deb5fc56 --- /dev/null +++ b/.github/workflows/hexchess-board-pages.yml @@ -0,0 +1,56 @@ +name: Deploy Hexchess Board Client + +on: + workflow_dispatch: + push: + branches: + - main + paths: + - 'hexchess-board/**' + - '.github/workflows/hexchess-board-pages.yml' + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: hexchess-board-pages + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Prepare static site + env: + PYENGINE2_BASE_URL: ${{ vars.PYENGINE2_BASE_URL }} + run: | + mkdir -p _site + cp -R hexchess-board/. _site/ + ENGINE_URL_JSON=$(node -e "console.log(JSON.stringify(process.env.PYENGINE2_BASE_URL || ''))") + cat > _site/app-config.js < = { - 'rust-worker': 4, + 'rust-worker': null, 'python-api': null, 'cyengine-api': null, } @@ -49,8 +49,7 @@ function timeoutMsFor(kind: EngineKind, options: EvaluateOptions) { return 120000 } - const depth = Math.max(1, options.depth) - return Math.max(120000, depth * 120000) + return null } export function useEngine() { diff --git a/engine/index.ts b/engine/index.ts index a4e9b359..04df7396 100644 --- a/engine/index.ts +++ b/engine/index.ts @@ -4,7 +4,7 @@ export interface EvaluateOptions { } export interface WorkerCommandOptions { - timeoutMs?: number + timeoutMs?: number | null } export interface SearchMetrics { @@ -44,7 +44,7 @@ export function execute = {}>( worker: Worker, command: string, options: Record = {}, - timeoutMs = 120000, + timeoutMs: number | null = 120000, ) { const id = crypto.randomUUID() @@ -53,9 +53,11 @@ export function execute = {}>( messageListener: (evt: MessageEvent) => void, errorListener: (evt: ErrorEvent) => void, messageErrorListener: (evt: MessageEvent) => void, - timeoutId: ReturnType, + timeoutId: ReturnType | null, ) => { - clearTimeout(timeoutId) + if (timeoutId !== null) { + clearTimeout(timeoutId) + } worker.removeEventListener('message', messageListener) worker.removeEventListener('error', errorListener) worker.removeEventListener('messageerror', messageErrorListener) @@ -95,10 +97,12 @@ export function execute = {}>( reject(new Error(`Engine worker message error while running ${command}`)) } - const timeoutId = setTimeout(() => { - cleanup(messageListener, errorListener, messageErrorListener, timeoutId) - reject(new Error(`Engine command timed out after ${timeoutMs}ms: ${command}`)) - }, timeoutMs) + const timeoutId = timeoutMs === null + ? null + : setTimeout(() => { + cleanup(messageListener, errorListener, messageErrorListener, timeoutId) + reject(new Error(`Engine command timed out after ${timeoutMs}ms: ${command}`)) + }, timeoutMs) worker.addEventListener('message', messageListener) worker.addEventListener('error', errorListener) diff --git a/hexchess-board/README.md b/hexchess-board/README.md new file mode 100644 index 00000000..9405948c --- /dev/null +++ b/hexchess-board/README.md @@ -0,0 +1,82 @@ +# hexchess-board client + +Do not open `index.html` directly via `file://`. + +Modern browsers block JavaScript ES module loading from `file://` origins (`origin null`), which is why you see CORS errors for `app.js`. + +Use a local HTTP server instead. + +## Windows PowerShell + +From repo root: + +```powershell +./hexchess-board/start-server.ps1 +``` + +Then open: + +- http://127.0.0.1:4175/index.html + +## Alternative (manual) + +```powershell +cd hexchess-board +python -m http.server 4175 --bind 127.0.0.1 +``` + +Open the same URL above. + +## Engine Selection + +The game setup now supports these engine-side values: + +- `pyengine2` +- `pyrustengine` + +Local defaults: + +- `pyengine2` -> `http://127.0.0.1:8000` +- `pyrustengine` -> `http://127.0.0.1:8081` + +If `app-config.js` provides a global `engineUrl`, that override is used for any selected engine. If it provides an `engineUrls` object, the client uses the matching per-engine base URL. + +## pyengine2 + +Start pyengine2 separately: + +```powershell +python -m uvicorn pyengine2.main:app --reload --host 127.0.0.1 --port 8000 +``` + +When the selected engine is `pyengine2`, the board client also sends earlier game positions together with the current FEN on each evaluation request. That lets `pyengine2` recognize threefold-repetition lines from the current game history instead of treating every request as a completely fresh position. + +## pyrustengine + +Start pyrustengine separately: + +```powershell +python -m pyrustengine +``` + +## GitHub Pages Engine URL Configuration + +The client loads runtime config from `app-config.js`. + +For GitHub Pages deploys, the workflow [.github/workflows/hexchess-board-pages.yml](../.github/workflows/hexchess-board-pages.yml) +injects a repository variable into that file. + +1. In GitHub, open repository `Settings` -> `Secrets and variables` -> `Actions` -> `Variables`. +2. Create a variable named `PYENGINE2_BASE_URL`. +3. Set it to your HTTPS engine endpoint, for example: + +```text +https://your-pyengine2.example.com +``` + +4. Run or let the `Deploy Hexchess Board Client` workflow run on `main`. + +Notes: + +- If `PYENGINE2_BASE_URL` is empty, GitHub Pages builds with an empty global engine URL and local defaults are used outside GitHub Pages. +- The UI also stores the last entered engine URL in localStorage. diff --git a/hexchess-board/app-config.js b/hexchess-board/app-config.js new file mode 100644 index 00000000..431231af --- /dev/null +++ b/hexchess-board/app-config.js @@ -0,0 +1,12 @@ +window.HEXCHESS_CONFIG = { + // Optional global override for any engine selection. + // Example: "https://pyengine2.example.com" + engineUrl: "", + + // Optional per-engine overrides. + // Example: + // engineUrls: { + // pyengine2: "https://pyengine2.example.com", + // pyrustengine: "https://pyrustengine.example.com", + // }, +} diff --git a/hexchess-board/app.js b/hexchess-board/app.js new file mode 100644 index 00000000..ebfea19c --- /dev/null +++ b/hexchess-board/app.js @@ -0,0 +1,899 @@ +import './vendor/hexchess-board/hexchess-board.js' +import { Hexchess, San, positions } from './vendor/hexchess/index.mjs' +import YAML from './vendor/yaml/browser/index.js' + +const BOARD_COLUMNS = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L'] + +function rowsForColumn(column) { + switch (column) { + case 'A': + case 'L': + return 6 + case 'B': + case 'K': + return 7 + case 'C': + case 'I': + return 8 + case 'D': + case 'H': + return 9 + case 'E': + case 'G': + return 10 + case 'F': + return 11 + default: + throw new Error(`Unsupported column: ${column}`) + } +} + +function compressFenColumn(source) { + let result = '' + let blanks = 0 + + for (const char of source) { + if (char === '1') { + blanks += 1 + } else { + if (blanks > 0) { + result += String(blanks) + blanks = 0 + } + result += char + } + } + + if (blanks > 0) { + result += String(blanks) + } + + return result || '1' +} + +function squareNameFromPosition(positionName) { + const column = positionName[0].toUpperCase() + const row = positionName.slice(1) + return `${column}${row}` +} + +function toBoardComponentFen(game) { + const squareToPiece = Object.create(null) + + for (let i = 0; i < positions.length; i += 1) { + const piece = game.board[i] + if (!piece) { + continue + } + + squareToPiece[squareNameFromPosition(positions[i])] = piece + } + + const columns = [] + for (const column of BOARD_COLUMNS) { + const rows = rowsForColumn(column) + let raw = '' + + for (let row = 1; row <= rows; row += 1) { + const square = `${column}${row}` + raw += squareToPiece[square] || '1' + } + + columns.push(compressFenColumn(raw)) + } + + return columns.join('/') +} + +const boardEl = document.getElementById('board') +const engineUrlEl = document.getElementById('engine-url') +const engineDepthEl = document.getElementById('engine-depth') +const whiteSideEl = document.getElementById('white-side') +const blackSideEl = document.getElementById('black-side') +const statusEl = document.getElementById('status') +const historyEl = document.getElementById('history') +const historySummaryEl = document.getElementById('history-summary') +const loadInputEl = document.getElementById('load-input') + +const pingBtn = document.getElementById('ping') +const playEngineBtn = document.getElementById('play-engine') +const toggleMatchBtn = document.getElementById('toggle-match') +const flipBtn = document.getElementById('flip') +const flipTopPiecesBtn = document.getElementById('flip-top-pieces') +const resetBtn = document.getElementById('reset') +const saveBtn = document.getElementById('save') +const loadBtn = document.getElementById('load') +const navStartBtn = document.getElementById('nav-start') +const navBackBtn = document.getElementById('nav-back') +const navForwardBtn = document.getElementById('nav-forward') +const navEndBtn = document.getElementById('nav-end') + +const START_FEN = Hexchess.init().toString() +const ENGINE_TYPES = ['pyengine2', 'pyrustengine'] +const DEFAULT_LOCAL_ENGINE_URLS = { + pyengine2: 'http://127.0.0.1:8000', + pyrustengine: 'http://127.0.0.1:8081', +} +const ENGINE_URL_STORAGE_KEY = 'hexchess-board.engine-url' + +let startFen = START_FEN +let moveHistory = [] +let historyIndex = 0 +let evaluation = null +let currentGame = Hexchess.parse(startFen) +let matchToken = 0 +let isBusy = false +let suppressBoardMoveEvent = false +let flipTopPiecesEnabled = false + +function updatePieceRotationMode() { + boardEl.rotateTopPieces = flipTopPiecesEnabled + boardEl.rotateBlackPieces = flipTopPiecesEnabled + if (typeof boardEl.requestUpdate === 'function') { + boardEl.requestUpdate('rotateTopPieces') + } + if (typeof boardEl.resize === 'function') { + boardEl.resize() + } + if (flipTopPiecesBtn) { + flipTopPiecesBtn.textContent = `Flip Top Pieces: ${flipTopPiecesEnabled ? 'On' : 'Off'}` + } +} + +function toggleBlackPieceRotationMode() { + flipTopPiecesEnabled = !flipTopPiecesEnabled + updatePieceRotationMode() +} + +function setStatus(message, isError = false) { + statusEl.textContent = message + if (isError) { + statusEl.style.background = '#fde8e8' + statusEl.style.borderColor = '#f7b6b6' + statusEl.style.color = '#6a1212' + } else { + statusEl.style.background = '#d5ece7' + statusEl.style.borderColor = '#bddcd4' + statusEl.style.color = '#0d453c' + } +} + +function sanitizeEngineUrl(raw) { + return raw.trim().replace(/\/$/, '') +} + +function isEngineType(value) { + return ENGINE_TYPES.includes(value) +} + +function getSideValue(turn) { + return turn === 'w' ? whiteSideEl.value : blackSideEl.value +} + +function getTurnEngineType(turn) { + const value = getSideValue(turn) + return isEngineType(value) ? value : null +} + +function isEngineMoveSource(value) { + return isEngineType(value) +} + +function getRuntimeGlobalEngineUrl() { + const configured = window?.HEXCHESS_CONFIG?.engineUrl + if (typeof configured !== 'string') { + return null + } + + const sanitized = sanitizeEngineUrl(configured) + return sanitized.length > 0 ? sanitized : null +} + +function getRuntimeEngineUrl(engineType) { + const engineUrls = window?.HEXCHESS_CONFIG?.engineUrls + if (engineUrls && typeof engineUrls === 'object') { + const configured = engineUrls[engineType] + if (typeof configured === 'string') { + const sanitized = sanitizeEngineUrl(configured) + if (sanitized.length > 0) { + return sanitized + } + } + } + + return getRuntimeGlobalEngineUrl() +} + +function getStoredEngineUrl() { + try { + const stored = localStorage.getItem(ENGINE_URL_STORAGE_KEY) + if (!stored) { + return null + } + + const sanitized = sanitizeEngineUrl(stored) + return sanitized.length > 0 ? sanitized : null + } catch { + return null + } +} + +function isGitHubPagesHost() { + return typeof window !== 'undefined' && window.location.hostname.endsWith('github.io') +} + +function resolveInitialEngineUrl() { + const runtime = getRuntimeGlobalEngineUrl() + if (runtime) { + return runtime + } + + const stored = getStoredEngineUrl() + if (stored) { + return stored + } + + return '' +} + +function persistEngineUrl(value) { + try { + const sanitized = sanitizeEngineUrl(value) + if (sanitized.length === 0) { + localStorage.removeItem(ENGINE_URL_STORAGE_KEY) + return + } + + localStorage.setItem(ENGINE_URL_STORAGE_KEY, sanitized) + } catch { + // Ignore storage errors in restricted environments. + } +} + +function getEngineDepth() { + const depth = Number(engineDepthEl.value) + if (!Number.isInteger(depth) || depth < 1) { + return 1 + } + + return Math.min(depth, 8) +} + +function sideIsEngine(turn) { + return getTurnEngineType(turn) !== null +} + +function getPreferredEngineType() { + return getTurnEngineType(currentGame.turn) || getTurnEngineType('w') || getTurnEngineType('b') || ENGINE_TYPES[0] +} + +function engineSourceTag(source) { + return isEngineMoveSource(source) + ? `[${source}]` + : '' +} + +function resolveEngineUrl(engineType) { + const explicit = sanitizeEngineUrl(engineUrlEl.value) + if (explicit) { + return explicit + } + + const runtime = getRuntimeEngineUrl(engineType) + if (runtime) { + return runtime + } + + if (isGitHubPagesHost()) { + return '' + } + + return DEFAULT_LOCAL_ENGINE_URLS[engineType] || '' +} + +function boardMoveToSan(boardMove) { + const from = String(boardMove.from || '').toLowerCase() + const to = String(boardMove.to || '').toLowerCase() + const promotion = boardMove.promotion ? String(boardMove.promotion).toLowerCase() : '' + + if (!from || !to) { + throw new Error('Board move is missing from/to squares.') + } + + return `${from}${to}${promotion}` +} + +function boardMoveStringToSan(moveString) { + const source = String(moveString || '').trim() + const match = source.match(/^([A-L](?:10|11|[1-9]))(?:-|x)([A-L](?:10|11|[1-9]))(?:[pPnNqQrRbB])?(?:\$)?(?:=([QqRrBbNn]))?$/) + + if (!match) { + throw new Error(`Invalid board move string: ${source}`) + } + + const from = match[1].toLowerCase() + const to = match[2].toLowerCase() + const promotion = match[3] ? match[3].toLowerCase() : '' + + return `${from}${to}${promotion}` +} + +function parseEngineSan(source) { + const match = String(source).trim().match(/^([a-l](?:10|11|[1-9]))([a-l](?:10|11|[1-9]))([nbrq])?$/i) + if (!match) { + throw new Error(`Invalid engine SAN: ${source}`) + } + + return { + from: match[1].toUpperCase(), + to: match[2].toUpperCase(), + promotion: match[3] ? match[3].toUpperCase() : null, + } +} + +function groupedMoves() { + const rows = [] + for (let i = 0; i < moveHistory.length; i += 2) { + rows.push({ + number: Math.floor(i / 2) + 1, + white: moveHistory[i] || null, + black: moveHistory[i + 1] || null, + whiteIndex: i + 1, + blackIndex: i + 2, + }) + } + return rows +} + +function renderHistory() { + const rows = groupedMoves() + if (rows.length === 0) { + historyEl.innerHTML = '
No moves recorded yet.
' + } else { + const html = [ + '', + '', + '', + ] + + for (const row of rows) { + const white = row.white + const black = row.black + + html.push('') + html.push(``) + + if (white) { + const activeClass = historyIndex === row.whiteIndex ? 'active' : '' + const details = white.evaluations != null && white.duration != null + ? ` (${white.evaluations.toLocaleString()} evals, ${Math.round(white.duration)}ms)` + : '' + const source = engineSourceTag(white.source) + html.push(``) + } else { + html.push('') + } + + if (black) { + const activeClass = historyIndex === row.blackIndex ? 'active' : '' + const details = black.evaluations != null && black.duration != null + ? ` (${black.evaluations.toLocaleString()} evals, ${Math.round(black.duration)}ms)` + : '' + const source = engineSourceTag(black.source) + html.push(``) + } else { + html.push('') + } + + html.push('') + } + + html.push('
#WhiteBlack
${row.number}${source}${details}${source}${details}
') + historyEl.innerHTML = html.join('') + } + + historySummaryEl.textContent = `Move ${historyIndex} / ${moveHistory.length}` + + navStartBtn.disabled = historyIndex === 0 + navBackBtn.disabled = historyIndex === 0 + navForwardBtn.disabled = historyIndex >= moveHistory.length + navEndBtn.disabled = historyIndex >= moveHistory.length +} + +function rebuildGameTo(index) { + const game = Hexchess.parse(startFen) + for (let i = 0; i < index; i += 1) { + game.applyMove(moveHistory[i].san) + } + return game +} + +function applySanToBoard(san) { + const parsed = parseEngineSan(san) + const moved = boardEl.move(parsed.from, parsed.to) + if (!moved) { + throw new Error(`Board rejected move: ${san}`) + } + + if (parsed.promotion) { + const promoted = boardEl.promote(parsed.promotion) + if (!promoted) { + throw new Error(`Board rejected promotion: ${san}`) + } + } +} + +function sanToBoardMove(san) { + const parsed = parseEngineSan(san) + return { + from: parsed.from, + to: parsed.to, + promotion: parsed.promotion, + } +} + +function syncBoardToHistory(index) { + const baseGame = Hexchess.parse(startFen) + const boardFen = toBoardComponentFen(baseGame) + const boardTurn = baseGame.turn === 'b' ? 'black' : 'white' + + boardEl.stopCustomEvents() + suppressBoardMoveEvent = true + + try { + // Hard reset internal widget state (captured pieces, score, move stack). + if (typeof boardEl.reset === 'function') { + boardEl.reset() + } + boardEl.setAttribute('board', boardFen) + boardEl.setAttribute('turn', boardTurn) + boardEl.setAttribute('moves', '') + boardEl.unfreeze() + boardEl.moves = moveHistory.slice(0, index).map((entry) => sanToBoardMove(entry.san)) + if (index > 0) { + boardEl.fastForwardAll() + } + } finally { + suppressBoardMoveEvent = false + boardEl.restartCustomEvents() + } +} + +function jumpTo(index) { + const clamped = Math.max(0, Math.min(index, moveHistory.length)) + const previousIndex = historyIndex + + if (clamped !== previousIndex) { + boardEl.stopCustomEvents() + suppressBoardMoveEvent = true + + try { + const steps = clamped - previousIndex + if (steps > 0) { + for (let i = 0; i < steps; i += 1) { + boardEl.fastForward() + } + } else { + for (let i = 0; i < Math.abs(steps); i += 1) { + boardEl.rewind() + } + } + } catch { + // Fallback to full sync if relative navigation fails for any reason. + syncBoardToHistory(clamped) + } finally { + suppressBoardMoveEvent = false + boardEl.restartCustomEvents() + } + } + + historyIndex = clamped + currentGame = rebuildGameTo(historyIndex) + renderHistory() +} + +function appendMove(san, meta = {}) { + if (historyIndex < moveHistory.length) { + moveHistory = moveHistory.slice(0, historyIndex) + } + + const snapshotBefore = currentGame.toString() + currentGame.applyMove(san) + + moveHistory.push({ + san, + source: meta.source || 'manual', + beforeFen: snapshotBefore, + evaluations: meta.evaluations ?? null, + duration: meta.duration ?? null, + metrics: meta.metrics ?? null, + }) + + historyIndex = moveHistory.length + renderHistory() +} + +function currentPositionHistory() { + return moveHistory + .slice(0, historyIndex) + .map((entry) => entry.beforeFen) + .filter((fen) => typeof fen === 'string' && fen.length > 0) +} + +function setBusy(nextBusy) { + isBusy = nextBusy + playEngineBtn.disabled = nextBusy + pingBtn.disabled = nextBusy + toggleMatchBtn.disabled = false +} + +async function executeEngine(engineType, command, options = {}) { + const engineUrl = resolveEngineUrl(engineType) + if (!engineUrl) { + throw new Error(`Engine URL is required for ${engineType}.`) + } + + const response = await fetch(`${engineUrl}/execute`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ command, options }), + }) + + if (!response.ok) { + const body = await response.text() + throw new Error(`Engine request failed (${response.status}): ${body}`) + } + + return response.json() +} + +async function pingEngine() { + setBusy(true) + try { + const engineType = getPreferredEngineType() + const data = await executeEngine(engineType, 'hexchess/ping', {}) + setStatus(`${engineType} is reachable. Timestamp: ${data.response?.now ?? 'n/a'}`) + } catch (error) { + setStatus(String(error.message || error), true) + } finally { + setBusy(false) + } +} + +async function playEngineMove() { + if (isBusy) { + return false + } + + const turn = currentGame.turn + const engineType = getTurnEngineType(turn) + if (!engineType) { + setStatus(`Turn ${turn === 'w' ? 'white' : 'black'} is set to Human.`) + return false + } + + setBusy(true) + + try { + const startedAt = performance.now() + const data = await executeEngine(engineType, 'hexchess/evaluate', { + depth: getEngineDepth(), + position: currentGame.toString(), + positionHistory: currentPositionHistory(), + diagnostics: true, + }) + const duration = performance.now() - startedAt + + const best = data.response?.sans?.[0] + if (!best || !best.san) { + setStatus('Engine returned no legal moves.') + return false + } + + boardEl.stopCustomEvents() + suppressBoardMoveEvent = true + try { + applySanToBoard(best.san) + } finally { + suppressBoardMoveEvent = false + boardEl.restartCustomEvents() + } + + appendMove(best.san, { + source: engineType, + evaluations: data.response?.evaluations ?? null, + duration, + metrics: data.response?.metrics ?? null, + }) + + evaluation = data.response + setStatus(`${engineType} played ${best.san} (${Math.round(duration)}ms).`) + return true + } catch (error) { + setStatus(String(error.message || error), true) + return false + } finally { + setBusy(false) + } +} + +async function maybeAutoPlayEngineTurn() { + if (isBusy) { + return + } + + if (historyIndex !== moveHistory.length) { + return + } + + if (!sideIsEngine(currentGame.turn)) { + return + } + + await playEngineMove() +} + +async function runMatchLoop() { + const token = ++matchToken + toggleMatchBtn.textContent = 'Stop Match' + setStatus('Engine match started.') + + for (let ply = 0; ply < 400; ply += 1) { + if (token !== matchToken) { + return + } + + if (!sideIsEngine(currentGame.turn)) { + setStatus('Match paused because current side is Human.') + return + } + + if (currentGame.isCheckmate() || currentGame.isStalemate()) { + setStatus('Game over detected.') + return + } + + const moved = await playEngineMove() + if (!moved) { + return + } + } +} + +function stopMatch() { + matchToken += 1 + toggleMatchBtn.textContent = 'Start Match' +} + +function resetGame() { + stopMatch() + startFen = START_FEN + moveHistory = [] + historyIndex = 0 + evaluation = null + currentGame = Hexchess.parse(startFen) + syncBoardToHistory(historyIndex) + renderHistory() + setStatus('Reset to initial position.') +} + +function saveGame() { + const payload = { + version: 1, + startFen, + historyIndex, + engineUrl: sanitizeEngineUrl(engineUrlEl.value), + whiteSide: whiteSideEl.value, + blackSide: blackSideEl.value, + depth: getEngineDepth(), + moves: moveHistory, + evaluation, + } + + const yaml = YAML.stringify(payload) + const blob = new Blob([yaml], { type: 'application/yaml' }) + const url = URL.createObjectURL(blob) + const anchor = document.createElement('a') + const stamp = new Date().toISOString().replace(/[:.]/g, '-') + + anchor.href = url + anchor.download = `hexchess-game-${stamp}.yaml` + document.body.appendChild(anchor) + anchor.click() + document.body.removeChild(anchor) + URL.revokeObjectURL(url) + + setStatus('Saved game to YAML.') +} + +function isLoadedMove(item) { + return item && typeof item.san === 'string' +} + +async function loadGameFile(file) { + const raw = await file.text() + const parsed = YAML.parse(raw) + + if (!parsed || parsed.version !== 1 || typeof parsed.startFen !== 'string' || !Array.isArray(parsed.moves)) { + throw new Error('Invalid game file format.') + } + + if (!parsed.moves.every(isLoadedMove)) { + throw new Error('Invalid moves in saved file.') + } + + const loadedMoves = parsed.moves.map((move) => ({ + san: String(move.san), + source: isEngineMoveSource(move.source) ? String(move.source) : 'manual', + beforeFen: typeof move.beforeFen === 'string' ? move.beforeFen : null, + evaluations: Number.isFinite(move.evaluations) ? move.evaluations : null, + duration: Number.isFinite(move.duration) ? move.duration : null, + metrics: move.metrics && typeof move.metrics === 'object' ? move.metrics : null, + })) + + let preview = Hexchess.parse(parsed.startFen) + for (const move of loadedMoves) { + preview.applyMove(move.san) + } + + startFen = parsed.startFen + moveHistory = loadedMoves + historyIndex = Number.isInteger(parsed.historyIndex) + ? Math.max(0, Math.min(parsed.historyIndex, moveHistory.length)) + : moveHistory.length + + if (typeof parsed.engineUrl === 'string' && parsed.engineUrl.trim()) { + engineUrlEl.value = sanitizeEngineUrl(parsed.engineUrl) + } + + if (parsed.whiteSide === 'human' || isEngineType(parsed.whiteSide)) { + whiteSideEl.value = parsed.whiteSide + } + + if (parsed.blackSide === 'human' || isEngineType(parsed.blackSide)) { + blackSideEl.value = parsed.blackSide + } + + if (Number.isInteger(parsed.depth) && parsed.depth > 0) { + engineDepthEl.value = String(Math.min(parsed.depth, 8)) + } + + currentGame = rebuildGameTo(historyIndex) + syncBoardToHistory(historyIndex) + renderHistory() + setStatus(`Loaded ${moveHistory.length} moves from file.`) +} + +boardEl.addEventListener('move', (event) => { + if (suppressBoardMoveEvent) { + return + } + + try { + let san = null + const moveString = event?.detail?.move + + if (typeof moveString === 'string' && moveString.length > 0) { + san = boardMoveStringToSan(moveString) + } else { + const latest = Array.isArray(boardEl.moves) ? boardEl.moves[boardEl.moves.length - 1] : null + if (!latest) { + return + } + san = boardMoveToSan(latest) + } + + appendMove(san, { source: 'manual' }) + void maybeAutoPlayEngineTurn() + } catch (error) { + setStatus(String(error.message || error), true) + } +}) + +boardEl.addEventListener('gameover', (event) => { + const outcome = event?.detail?.outcome || 'unknown' + setStatus(`Game over: ${outcome}`) + stopMatch() +}) + +historyEl.addEventListener('click', (event) => { + const target = event.target + if (!(target instanceof HTMLElement)) { + return + } + + const jump = target.getAttribute('data-jump') + if (!jump) { + return + } + + const index = Number(jump) + if (!Number.isFinite(index)) { + return + } + + jumpTo(index) +}) + +pingBtn.addEventListener('click', () => { + void pingEngine() +}) + +playEngineBtn.addEventListener('click', () => { + void playEngineMove() +}) + +toggleMatchBtn.addEventListener('click', () => { + if (toggleMatchBtn.textContent === 'Stop Match') { + stopMatch() + setStatus('Engine match stopped.') + return + } + + void runMatchLoop().finally(() => { + stopMatch() + }) +}) + +flipBtn.addEventListener('click', () => { + boardEl.flip() +}) + +flipTopPiecesBtn?.addEventListener('click', () => { + toggleBlackPieceRotationMode() +}) + +resetBtn.addEventListener('click', () => { + resetGame() +}) + +saveBtn.addEventListener('click', () => { + saveGame() +}) + +loadBtn.addEventListener('click', () => { + loadInputEl.click() +}) + +loadInputEl.addEventListener('change', async () => { + const file = loadInputEl.files && loadInputEl.files[0] + if (!file) { + return + } + + try { + await loadGameFile(file) + } catch (error) { + setStatus(String(error.message || error), true) + } finally { + loadInputEl.value = '' + } +}) + +navStartBtn.addEventListener('click', () => jumpTo(0)) +navBackBtn.addEventListener('click', () => jumpTo(historyIndex - 1)) +navForwardBtn.addEventListener('click', () => jumpTo(historyIndex + 1)) +navEndBtn.addEventListener('click', () => jumpTo(moveHistory.length)) + +whiteSideEl.addEventListener('change', () => { + stopMatch() + void maybeAutoPlayEngineTurn() +}) + +blackSideEl.addEventListener('change', () => { + stopMatch() + void maybeAutoPlayEngineTurn() +}) + +engineDepthEl.addEventListener('change', () => { + const depth = getEngineDepth() + engineDepthEl.value = String(depth) +}) + +resetGame() +updatePieceRotationMode() +engineUrlEl.value = resolveInitialEngineUrl() +engineUrlEl.addEventListener('change', () => { + persistEngineUrl(engineUrlEl.value) +}) +setStatus('Ready. Configure sides and play.') diff --git a/hexchess-board/favicon.svg b/hexchess-board/favicon.svg new file mode 100644 index 00000000..6576df55 --- /dev/null +++ b/hexchess-board/favicon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/hexchess-board/index.html b/hexchess-board/index.html new file mode 100644 index 00000000..20b3bfd6 --- /dev/null +++ b/hexchess-board/index.html @@ -0,0 +1,83 @@ + + + + + + Hexagonal chess (engine powered) + + + + +
+
+

Hexagonal chess (engine powered)

+

Client based on hexchess-board.

+

Engines: pyengine2 and pyrustengine from hexchess

+
+ +
+ + + + + + + + +
+ + + + + + +
+ +
Ready.
+
+ +
+ +
+ +
+
+ Game Log + +
+ +
+ + + + + + + +
+ +
+
+
+ + + + + diff --git a/hexchess-board/start-server.ps1 b/hexchess-board/start-server.ps1 new file mode 100644 index 00000000..5c23ce37 --- /dev/null +++ b/hexchess-board/start-server.ps1 @@ -0,0 +1,11 @@ +$ErrorActionPreference = 'Stop' + +$root = Split-Path -Parent $MyInvocation.MyCommand.Path +Set-Location $root + +$port = 4175 + +Write-Host "Serving hexchess-board on http://127.0.0.1:$port/index.html" +Write-Host "Press Ctrl+C to stop." + +python -m http.server $port --bind 127.0.0.1 diff --git a/hexchess-board/styles.css b/hexchess-board/styles.css new file mode 100644 index 00000000..2dedab5b --- /dev/null +++ b/hexchess-board/styles.css @@ -0,0 +1,185 @@ +:root { + color-scheme: light; + --bg: #f2f6f8; + --panel: #ffffff; + --text: #142027; + --muted: #51606b; + --accent: #146356; + --accent-soft: #d5ece7; + --border: #d5dfe4; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + color: var(--text); + background: + radial-gradient(circle at 15% 20%, #d6ebe5 0%, transparent 28%), + radial-gradient(circle at 85% 10%, #e8f1f5 0%, transparent 32%), + linear-gradient(180deg, #f8fbfc 0%, var(--bg) 100%); +} + +code { + font-family: Consolas, "Courier New", monospace; +} + +.app { + max-width: 1100px; + margin: 0 auto; + padding: 1rem; + display: grid; + gap: 1rem; +} + +.panel { + border: 1px solid var(--border); + border-radius: 12px; + background: var(--panel); + padding: 0.9rem; + box-shadow: 0 8px 24px rgba(11, 35, 45, 0.08); +} + +h1 { + margin: 0; + font-size: 1.35rem; +} + +.muted { + color: var(--muted); +} + +.controls-grid { + display: grid; + gap: 0.75rem; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); +} + +label { + display: grid; + gap: 0.3rem; + font-size: 0.92rem; +} + +input, +select, +button { + border: 1px solid var(--border); + border-radius: 8px; + font: inherit; +} + +input, +select { + background: #fff; + padding: 0.45rem 0.55rem; +} + +button { + background: #fff; + cursor: pointer; + padding: 0.45rem 0.7rem; +} + +button:hover { + border-color: #b4c4cc; +} + +button:disabled { + cursor: not-allowed; + opacity: 0.55; +} + +.buttons-row { + grid-column: 1 / -1; + display: flex; + flex-wrap: wrap; + gap: 0.45rem; +} + +.status { + grid-column: 1 / -1; + background: var(--accent-soft); + border: 1px solid #bddcd4; + color: #0d453c; + border-radius: 8px; + padding: 0.45rem 0.6rem; + font-size: 0.9rem; +} + +.board-wrap { + overflow: hidden; +} + +hexchess-board { + display: block; + width: min(88vmin, 820px); + height: min(88vmin, 820px); + margin: 0 auto; +} + +.toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.5rem; + margin-bottom: 0.6rem; +} + +.history { + border: 1px solid var(--border); + border-radius: 8px; + max-height: 270px; + overflow: auto; +} + +.history table { + width: 100%; + border-collapse: collapse; + font-size: 0.9rem; +} + +.history th, +.history td { + padding: 0.45rem 0.5rem; + border-bottom: 1px solid var(--border); + text-align: left; + vertical-align: top; +} + +.history tr.active { + background: #f4faf8; +} + +.history button { + padding: 0.2rem 0.42rem; + background: transparent; + border: 1px solid transparent; +} + +.history button:hover { + border-color: #c4d4dc; +} + +.engine-tag { + color: var(--accent); + font-size: 0.8rem; + margin-left: 0.35rem; +} + +@media (max-width: 700px) { + .toolbar { + flex-direction: column; + align-items: flex-start; + } + + hexchess-board { + width: 96vw; + height: 96vw; + max-width: 96vw; + max-height: 96vw; + } +} diff --git a/pyengine2/README.md b/pyengine2/README.md index 06414052..96e7c0cb 100644 --- a/pyengine2/README.md +++ b/pyengine2/README.md @@ -60,6 +60,8 @@ Useful endpoints: The API wrapper delegates engine work to `execute_command(...)` in [pyengine2/native_engine.py](pyengine2/native_engine.py). +For `hexchess/evaluate`, callers may optionally provide `options.positionHistory` as a list of earlier FEN strings from the same game. `pyengine2` uses that prior-position history to score threefold-repetition lines as draws instead of treating them as ordinary fresh positions. + ### Run the benchmark suite Search benchmarks: @@ -98,6 +100,24 @@ Stage 1 baseline suite with YAML report output: python pyengine2/benchmark.py --suite stage1-baseline --output results/2.1.003/stage1-baseline.yaml ``` +Harvested diagnostic suite with engine counters enabled: + +```powershell +python pyengine2/benchmark.py --suite harvested-diagnostics --diagnostics --output results/2.1.003/harvested-diagnostics.yaml +``` + +Historical harvested diagnostic suite for the March 24 and March 26 positions: + +```powershell +python pyengine2/benchmark.py --suite harvested-history-diagnostics --diagnostics --output results/2.1.003/harvested-history-diagnostics.yaml +``` + +Clean search-comparison suite for keep-or-revert decisions on search changes: + +```powershell +python pyengine2/benchmark.py --suite clean-search-comparison --output results/2.1.003/clean-search-comparison.yaml +``` + Saved game analysis: ```powershell @@ -125,13 +145,19 @@ This suite reruns the current Stage 1 comparison set in one command: - qsearch-heavy search at depths 4 and 5 - opening baseline at depths 4 and 5 +The harvested diagnostic suite is separate on purpose. It samples the March 29 harvested stress positions for TT-heavy, qsearch-heavy, wide-root, node-heavy, and low-throughput behavior at depth 3 with single-run diagnostics, so those cases stay easy to rerun without changing the official clean baseline. + +The historical harvested diagnostic suite extends that same depth-3 single-run diagnostic pass across the March 24 and March 26 harvested positions, so the full harvested corpus can be rerun with two commands instead of one large ad hoc filter list. + +The clean search-comparison suite is the search-only keep-or-revert set. It keeps the Stage 1 baseline intact, but adds the March 29 TT-heavy position alongside the existing clean comparison cases so search regressions are less likely to hide behind opening-only or qsearch-only behavior. + When `--output` is provided, the benchmark runner writes a YAML report for either a suite run or a regular filtered benchmark run. This is intended for versioned baseline snapshots under `results//`. The benchmark runner currently supports these benchmark features: - filtered runs by benchmark name with `--filter` - four measurement modes: `search`, `moves`, `tactical-moves`, and `eval` -- predefined Stage 1 suite execution with `--suite stage1-baseline` +- predefined suite execution with `--suite stage1-baseline`, `--suite clean-search-comparison`, `--suite harvested-diagnostics`, or `--suite harvested-history-diagnostics` - YAML report output for suite and non-suite runs with `--output` - search summaries that include top moves and engine metrics in the saved YAML output - a benchmark corpus that can be extended manually or by harvested-game extraction diff --git a/pyengine2/analyze_game.py b/pyengine2/analyze_game.py index 602cfbd3..7b9ff819 100644 --- a/pyengine2/analyze_game.py +++ b/pyengine2/analyze_game.py @@ -29,7 +29,23 @@ 'ttHits', 'ttCutoffs', 'betaCutoffs', + 'negamaxTtHits', + 'quiescenceTtHits', + 'negamaxTtCutoffs', + 'quiescenceTtCutoffs', + 'negamaxBetaCutoffs', + 'quiescenceBetaCutoffs', + 'qsearchStandPatCutoffs', + 'qsearchDeltaPruneChecks', + 'qsearchDeltaPruneSkips', + 'qsearchNodesWithMoves', + 'qsearchGeneratedMoves', + 'pvsResearches', + 'negamaxFrontierFutilityChecks', + 'negamaxFrontierFutilitySkips', 'ttEntries', + 'nullMoveAttempts', + 'nullMoveCutoffs', ) TAG_PRIORITY = ( 'tt-heavy', diff --git a/pyengine2/benchmark.py b/pyengine2/benchmark.py index 5a737294..c4c8a9bd 100644 --- a/pyengine2/benchmark.py +++ b/pyengine2/benchmark.py @@ -26,6 +26,41 @@ {'mode': 'search', 'filter': 'initial-position', 'depths': [4, 5], 'repeat': 3}, ) +HARVESTED_DIAGNOSTIC_SUITE = ( + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260329-210806-ply-014-tt-heavy', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260329-210806-ply-020-qsearch-heavy', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260329-210806-ply-058-wide-root', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260329-210806-ply-042-node-heavy', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260329-210806-ply-028-low-throughput', 'depths': [3], 'repeat': 1}, +) + +HARVESTED_HISTORY_DIAGNOSTIC_SUITE = ( + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260324-175232-ply-018-tt-heavy', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260324-175232-ply-024-wide-root', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260324-175232-ply-004-node-heavy', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260324-175232-ply-074-low-throughput', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260324-175232-ply-010-node-heavy', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260326-173542-ply-032-tt-heavy', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260326-173542-ply-012-qsearch-heavy', 'depths': [3], 'repeat': 1}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260326-173542-ply-048-wide-root', 'depths': [3], 'repeat': 1}, +) + +CLEAN_SEARCH_COMPARISON_SUITE = ( + {'mode': 'search', 'filter': 'tt-transposition-midgame', 'depths': [4, 5], 'repeat': 3}, + {'mode': 'search', 'filter': 'capture-storm-qsearch', 'depths': [4, 5], 'repeat': 3}, + {'mode': 'search', 'filter': 'initial-position', 'depths': [4, 5], 'repeat': 3}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy', 'depths': [3], 'repeat': 3}, + {'mode': 'search', 'filter': 'harvested-hexchess-game-20260329-210806-ply-014-tt-heavy', 'depths': [3], 'repeat': 1}, +) + +BENCHMARK_SUITES: dict[str, tuple[dict[str, Any], ...]] = { + 'stage1-baseline': STAGE1_BASELINE_SUITE, + 'harvested-diagnostics': HARVESTED_DIAGNOSTIC_SUITE, + 'harvested-history-diagnostics': HARVESTED_HISTORY_DIAGNOSTIC_SUITE, + 'clean-search-comparison': CLEAN_SEARCH_COMPARISON_SUITE, +} + @dataclass(frozen=True, slots=True) class BenchmarkCase: @@ -80,7 +115,7 @@ def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description='Run pyengine2 search benchmarks.') parser.add_argument('--file', type=Path, default=DEFAULT_BENCHMARK_FILE, help='Benchmark YAML file') parser.add_argument('--output', type=Path, help='Optional YAML report output path') - parser.add_argument('--suite', choices=('stage1-baseline',), help='Run a predefined benchmark suite') + parser.add_argument('--suite', choices=tuple(BENCHMARK_SUITES), help='Run a predefined benchmark suite') parser.add_argument( '--mode', choices=('search', 'moves', 'tactical-moves', 'eval'), @@ -91,6 +126,7 @@ def parse_args() -> argparse.Namespace: parser.add_argument('--repeat', type=int, default=3, help='Runs per benchmark/depth') parser.add_argument('--filter', dest='name_filter', default='', help='Only run benchmark names containing this text') parser.add_argument('--top', type=int, default=3, help='How many top moves to display') + parser.add_argument('--diagnostics', action='store_true', help='Enable extra diagnostic search counters in benchmark reports') return parser.parse_args() @@ -98,7 +134,7 @@ def median_ms(values: list[float]) -> float: return statistics.median(values) * 1000.0 -def run_search_case(case: BenchmarkCase, depth: int, repeat: int) -> dict[str, Any]: +def run_search_case(case: BenchmarkCase, depth: int, repeat: int, diagnostics: bool) -> dict[str, Any]: durations: list[float] = [] evaluations: list[int] = [] result: dict[str, Any] | None = None @@ -106,7 +142,7 @@ def run_search_case(case: BenchmarkCase, depth: int, repeat: int) -> dict[str, A for _ in range(repeat): position = case.create_position() started_at = time.perf_counter() - result = search(position, depth) + result = search(position, depth, diagnostics=diagnostics) durations.append(time.perf_counter() - started_at) evaluations.append(int(result['evaluations'])) @@ -282,16 +318,18 @@ def print_eval_summary(summary: dict[str, Any]) -> None: def run_suite(args: argparse.Namespace, cases: list[BenchmarkCase]) -> int: - if args.suite != 'stage1-baseline': + if args.suite not in BENCHMARK_SUITES: raise ValueError(f'Unsupported suite: {args.suite}') + suite_definition = BENCHMARK_SUITES[args.suite] + print(f'Benchmark file: {args.file}') print(f'Suite: {args.suite} | pyengine2 version: {PYENGINE2_VERSION}') print() suite_entries: list[dict[str, Any]] = [] - for entry in STAGE1_BASELINE_SUITE: + for entry in suite_definition: mode = entry['mode'] name_filter = str(entry['filter']) selected_cases = [case for case in cases if name_filter in case.name.lower()] @@ -331,7 +369,7 @@ def run_suite(args: argparse.Namespace, cases: list[BenchmarkCase]) -> int: if mode == 'search': summaries: list[dict[str, Any]] = [] for depth in entry['depths']: - summary = run_search_case(case, depth, repeat) + summary = run_search_case(case, depth, repeat, args.diagnostics) print_search_summary(summary, args.top) summaries.append(summary_report_data(summary, args.top)) case_entry['summaries'] = summaries @@ -361,6 +399,7 @@ def run_suite(args: argparse.Namespace, cases: list[BenchmarkCase]) -> int: 'benchmarkFile': str(args.file), 'generatedAt': datetime.now(timezone.utc).isoformat(), 'topCount': args.top, + 'diagnostics': bool(args.diagnostics), 'entries': suite_entries, }, ) @@ -408,7 +447,7 @@ def main() -> int: if args.mode == 'search': summaries: list[dict[str, Any]] = [] for depth in args.depths: - summary = run_search_case(case, depth, args.repeat) + summary = run_search_case(case, depth, args.repeat, args.diagnostics) print_search_summary(summary, args.top) summaries.append(summary_report_data(summary, args.top)) case_entry['summaries'] = summaries @@ -435,6 +474,7 @@ def main() -> int: 'mode': args.mode, 'repeat': args.repeat, 'topCount': args.top, + 'diagnostics': bool(args.diagnostics), 'cases': report_cases, } if args.mode == 'search': diff --git a/pyengine2/benchmark/benchmarks.yaml b/pyengine2/benchmark/benchmarks.yaml index cdd98de8..ca0a0c04 100644 --- a/pyengine2/benchmark/benchmarks.yaml +++ b/pyengine2/benchmark/benchmarks.yaml @@ -118,3 +118,68 @@ benchmarks: notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 10 (b5 k7k5). tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. wallMs=97689.2, negamaxNodes=921501, quiescenceNodes=2646313, ttHits=548905, movegenCalls=1773051.' +- name: harvested-hexchess-game-20260326-173542-ply-032-tt-heavy + category: harvested + fen: 1/qbk/5/r4b1/p1pp1pbrp/11/2p8/3R4p2/5K1PPP1/2P8/1P1N1B1NR1Q b - 2 16 + notes: 'Harvested from hexchess-game-20260326-173542.yaml before ply 32 (b16 i4k3). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=100537.7, negamaxNodes=1314268, quiescenceNodes=2290113, ttHits=610384, + movegenCalls=1959062.' +- name: harvested-hexchess-game-20260326-173542-ply-012-qsearch-heavy + category: harvested + fen: b/qbk/2b1n/r2n3/pppppp1rp/11/3PP1P1p2/11/4BB1PP2/2P8/1PRNQBKNRP1 b d4 0 6 + notes: 'Harvested from hexchess-game-20260326-173542.yaml before ply 12 (b6 f8e5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=106783.5, negamaxNodes=845527, quiescenceNodes=2326002, ttHits=364240, + movegenCalls=1969314.' +- name: harvested-hexchess-game-20260326-173542-ply-048-wide-root + category: harvested + fen: 1/1qk/5/r6/p1p2pbrp/3b7/2pb1N5/6R4/4p2PPp1/2P2K5/1P3B1NR1Q b - 3 24 + notes: 'Harvested from hexchess-game-20260326-173542.yaml before ply 48 (b24 h7f5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy, + wide-root. wallMs=80029.6, negamaxNodes=1155468, quiescenceNodes=1692986, ttHits=438005, + movegenCalls=1501474.' +- name: harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + category: harvested + fen: b/qbk/n1b1n/r5r/p2ppp2p/3p7/2pPP1PP3/2P5p2/5B5/3Q1B2P2/1PRN1BKNRP1 b h4 0 7 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 14 (b7 k7k5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=486507.1, negamaxNodes=849351, quiescenceNodes=16278157, ttHits=1192920, + movegenCalls=9117488.' +- name: harvested-hexchess-game-20260329-210806-ply-020-qsearch-heavy + category: harvested + fen: b/qbk/n1b1n/r6/p2ppp1r1/11/2p1P1PP1p1/2P5p2/4BB3P1/3Q4P2/1PRN1BKNR2 b k2 0 + 10 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 20 (b10 f11k3). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=74173.1, + negamaxNodes=611349, quiescenceNodes=2680684, ttHits=283244, movegenCalls=1546842.' +- name: harvested-hexchess-game-20260329-210806-ply-058-wide-root + category: harvested + fen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r5p2/Q8p1/3R4P2/3N2BKN2 b - 5 29 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 58 (b29 i4i3). + tags: wide-root. wallMs=34068.7, negamaxNodes=519873, quiescenceNodes=888734, + ttHits=160009, movegenCalls=604623.' +- name: harvested-hexchess-game-20260329-210806-ply-042-node-heavy + category: harvested + fen: 1/q1k/1rb1n/7/3ppp1r1/3b7/2Q3PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 b - 7 21 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 42 (b21 e9c7). + tags: node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. wallMs=68709.9, + negamaxNodes=699350, quiescenceNodes=2098881, ttHits=404581, movegenCalls=1147819.' +- name: harvested-hexchess-game-20260329-210806-ply-028-low-throughput + category: harvested + fen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p3PP1p1/2P3Qnp2/4BB3N1/8P2/1PRN1BK1R2 b - 3 14 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 28 (b14 h4i1). + tags: low-throughput. wallMs=44083.7, negamaxNodes=651597, quiescenceNodes=891456, + ttHits=198530, movegenCalls=608259.' +- name: harvested-hexchess-game-20260329-210806-ply-008-slow-search + category: harvested + fen: b/qbk/n1b1n/r5r/pppppp2p/11/4P1P1p2/2P8/3P1B1P3/5B2P2/1PRNQBKNRP1 b c3 0 4 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 8 (b4 c7c5). + tags: slow-search, movegen-heavy, pruning-heavy. wallMs=75414.7, negamaxNodes=635323, + quiescenceNodes=1851437, ttHits=246345, movegenCalls=1097512.' +- name: harvested-hexchess-game-20260329-210806-ply-034-interesting + category: harvested + fen: 1/qbk/2b1n/r6/3ppp1r1/11/2B3PP1p1/1pP3Q1p2/5B5/3R4P2/1P1N1BK1N2 b - 0 17 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 34 (b17 b4c4). + tags: interesting. wallMs=42174.5, negamaxNodes=469413, quiescenceNodes=1555830, + ttHits=211732, movegenCalls=890113.' diff --git a/pyengine2/design-ideas.txt b/pyengine2/design/1-initial-design-ideas.txt similarity index 100% rename from pyengine2/design-ideas.txt rename to pyengine2/design/1-initial-design-ideas.txt diff --git a/pyengine2/design/2-data-structures.txt b/pyengine2/design/2-data-structures.txt new file mode 100644 index 00000000..17ee6fb0 --- /dev/null +++ b/pyengine2/design/2-data-structures.txt @@ -0,0 +1,401 @@ +Question: +Before continuing with further tuning, are we good with the core data-structure(s) and associated computation actions. +Is there anything elese or differnt that could be done to speed up even more? + +I’m checking a few exact anchors in the engine so the answer is tied to the current implementation rather than a generic optimization list. + +Searched for regex `class SearchState|class Hexchess|def _compute_legal_context|def optimize_tactical_moves|def quiescence\(|def make_move_unsafe|def position_key` (`**/pyengine2/native_engine.py`), 7 results + +Searched for regex `quiescenceNodes|tacticalMovegenCalls|legalContextCalls|ttHits|ttCutoffs` (`**/results/2.1.003/stage1-baseline.yaml`), 30 results + +Short answer: the core data structures are good enough for Stage 1, but they are not the final ceiling. + +What is already solid +- The board and piece state are already in the right shape for a Python engine: + - numeric board state and synchronized masks in native_engine.py + - reusable search scratch state in native_engine.py + - Zobrist position keying in native_engine.py + - integer move ordering in native_engine.py +- Those are not “toy” structures. They are the right base for continued tuning. +- The benchmark data also says the engine is mostly losing time in repeated search work, not because the board representation is fundamentally wrong: + - opening depth 5 still shows very high quiescence, tactical movegen, and legal-context counts in stage1-baseline.yaml + - TT is already active and useful in the same baseline in stage1-baseline.yaml + +What is not yet ideal +- The expensive parts now are mostly Python object and control overhead around the core structures: + - full legal-context rebuilds in native_engine.py + - move undo tuple creation in native_engine.py + - dictionary-based TT entries around native_engine.py + - per-node sorting and move scoring in native_engine.py +- That is why the last two experiments failed: + - they changed the movegen path, but replaced one form of overhead with another + - they did not reduce total Python work enough on the broad baseline + +My assessment +- For Stage 1: yes, the core structures are good enough to keep. +- For larger speedups beyond the current incremental slices: yes, there are still different things worth doing. + +Best “different” things that could speed it up more +1. Replace the transposition table dict with a fixed-size array-backed TT +- This is the biggest structural candidate still available in pure Python. +- Right now TT is a Python dict mapping key to tuple entries. +- A fixed-size TT with direct index masking and overwrite policy would cut: + - dict hash overhead + - tuple churn + - allocation pressure +- This is the first thing I would look at if you want a more structural Stage 1.5 improvement. + +2. Replace undo tuples with reusable per-ply undo storage +- native_engine.py creates undo tuples constantly. +- A reusable per-ply undo stack or packed list-based undo record would likely help more than another movegen micro-optimization. +- This is lower risk than a whole new legality path and attacks a very hot make/unmake loop. + +3. Split qsearch TT policy from full-search TT policy +- Not a whole new structure, but a different use of the current one. +- Qsearch may benefit from: + - shallower or separate replacement policy + - cheaper entry payload + - avoiding some storage on low-value nodes +- That could reduce common-path TT overhead without weakening full-search reuse. + +4. Introduce a compact no-pin/no-check legal-context representation +- Not the failed sparse-reset experiment. +- A more promising version is to change the representation itself: + - fast sentinel for no pins + - sparse pinned-piece map only when needed +- The current full mask representation in native_engine.py is convenient but still heavy. + +5. Reduce sorting frequency in qsearch +- native_engine.py sorts every tactical move list. +- If lists are often very small, a manual best-first selection or one-pass TT/promotion/capture bucketing may beat full sort. +- This is smaller than the TT and undo ideas, but still plausible. + +What I would not change yet +- I would not replace the board representation. +- I would not replace piece masks. +- I would not move away from packed move codes. +- I would not add more complicated pseudo-legal qsearch generation after the last failed experiment. +- Those are not the weak point right now. + +Priority order from here +1. Array-backed transposition table +2. Reusable undo storage +3. Narrow TT/qsearch policy tuning +4. Legal-context representation refinement +5. Qsearch move ordering simplification + +So, are we good with the current core data structures? +- Yes for Stage 1 continuation. +- No if the question is “is this the maximum speed we can get in pure Python?” + +The biggest remaining upside is not a new board model. It is reducing Python-level overhead around TT, undo records, and repeated qsearch control work. + +If you want, I can continue with one of these two next: +1. inspect the current TT usage and propose a minimal fixed-size array TT design for pyengine2 +2. inspect make/unmake and propose a reusable undo-record design that fits the current search stack + +-------------------------------------------- +This was tried: + +1. Replace the transposition table dict with a fixed-size array-backed TT +There was no improvement + +2. Replace undo tuples with reusable per-ply undo storage +There was no improvement + +Conclusion: +give up on: + +fixed-size array TT as the default next experiment +reusable per-ply undo storage as the default next experiment + +---------------------------------------------- +recommendation to continue from here: + +Freeze the current board, mask, and move-code model. +Treat large core data-structure rewrites as low priority unless a new measurement strongly points there. +Continue only with targeted changes in these areas: +qsearch move ordering without full sort +compact no-pin or no-check legal-context fast representation +split TT policy for qsearch versus full search +selective instrumentation to find the next dominant common-path branch cost + +Next experiments: next step in one of two directions: + +inspect qsearch ordering and propose a no-full-sort tactical ordering path +inspect legal-context construction and propose a compact fast path for the common no-pin case + + +---------------------------------------------- +qsearch ordering inspection + +Current path in native_engine.py: +- _fill_current_moves(..., tactical_only=True) builds the full tactical list first +- optimize_tactical_moves(...) computes a Python score for every move and then calls list.sort(...) +- quiescence(...) applies delta pruning only after that full sort + +What this means: +- qsearch pays full scoring and Timsort cost even when: + - the TT move cuts off immediately + - the first winning capture cuts off immediately + - several tail moves would later be skipped by delta pruning anyway +- This is a bad fit for qsearch, where the practical goal is usually to find one good tactical move early, not to perfectly rank the full list + +Recommended no-full-sort path: +Replace full tactical sorting with an in-place front-priority pass. + +Proposed shape: +1. Keep tactical generation unchanged. +2. Replace optimize_tactical_moves(...) with a helper that only promotes a small front segment. +3. Priority order for that front segment: + - TT move first, if present + - promotion moves next, ordered by existing promotion bonus + - clearly good captures next, using the current MVV-LVA-style score + - leave the remaining tail unsorted +4. Run quiescence over: + - the promoted front segment first + - then the unsorted tail in generated order + +Why this is the right tradeoff: +- avoids scoring every move just to feed Timsort +- avoids extra temporary bucket lists +- keeps the current move generator and legality path unchanged +- still preserves the main value of move ordering in qsearch: getting TT move / promotions / best captures to the front quickly + +Concrete implementation sketch: +- Add a small helper like promote_tactical_front(hexchess, moves, tt_move) -> int +- It does a single scan over moves and swaps a few selected moves into the first slots +- Suggested front classes: + - slot 0: TT move + - next slots: promotions + - next slots: captures with non-negative tactical score +- The function returns front_count +- quiescence(...) searches moves[0:front_count] first, then moves[front_count:] + +Important constraint: +- Do not add reusable per-node bucket arrays for this first version +- The last undo-storage experiment showed that extra Python-side buffer traffic can erase the expected gain +- The first attempt here should therefore prefer a minimal in-place promotion strategy over more bookkeeping-heavy classification + +Expected upside: +- best case: faster qsearch on nodes where cutoff happens in the first one or two tactical moves +- neutral case: no regression on positions where tactical lists are already tiny +- main risk: if too many qsearch nodes need deep tail search, partial ordering may lose enough cutoff quality to cancel the saved sort cost + +Recommended experiment order: +1. promote TT move + promotions only, leave all captures otherwise unsorted +2. if that is neutral or positive, extend front promotion to include one or two best non-losing captures +3. stop if broad benchmarks regress, especially initial-position and tt-transposition-midgame + + +Result: +- Tried the first no-full-sort qsearch ordering slice by promoting: + - TT move first + - promotions next + - one best non-losing capture after promotions +- Broad benchmarks regressed, so this exact partial-ordering path should be treated as rejected: + - capture-storm-qsearch: slower + - tt-transposition-midgame: slower + - initial-position: slower + - harvested qsearch-heavy: slower +- Conclusion: the saved sort work did not make up for the weaker cutoff quality from the partially unsorted tail. + +---------------------------------------------------- +Best next step from here: + +Inspect legal-context construction for a compact common-case no-pin fast path +Inspect narrower qsearch TT policy differences without changing the main tactical ordering path + + +---------------------------------------------------- +legal-context no-pin inspection + +Current path in native_engine.py: +- _compute_legal_context(...) resets all 91 pin masks to ALL_PIN_MASKS on every call +- this happens even on common no-pin paths +- _fill_current_moves(...) already has a fast branch for check_count == 0 and not has_pins + +Proposed fast path that was tried: +- defer pin-mask materialization until the first actual pin is found +- return the shared ALL_PIN_MASKS sentinel when no pins are present instead of rewriting the reusable pin-mask buffer + +Why it looked plausible: +- legal-context is called at every move-generation node +- the common no-pin path should avoid 91 Python writes per call if possible +- it keeps board model, move generation, and legality semantics unchanged + +Result: +- Broad benchmarks still regressed overall, so this exact deferred-materialization path should also be treated as rejected: + - capture-storm-qsearch: slightly slower + - tt-transposition-midgame: slower + - initial-position: slower overall + - harvested qsearch-heavy: still slower than baseline +- Conclusion: skipping the default pin-mask rewrite did not save enough to offset the extra control-path cost and the change did not improve the broad Stage 1 profile. + +Updated conclusion: +- preserve the current legal-context representation for now +- do not revisit this exact no-pin deferred pin-mask materialization variant as a first-line optimization +- the next best target is now narrower qsearch TT policy tuning rather than another common-path representation rewrite + +---------------------------------------------- +Next step then +reduce qsearch TT storage aggressiveness +reduce qsearch TT entry payload or replacement frequency + + +---------------------------------------------- +qsearch TT policy inspection + +First narrow slice tried: +- keep full-search TT behavior unchanged +- in quiescence only, reduce storage aggressiveness by: + - keeping lower-bound entries + - skipping upper-bound entries + - skipping stand-pat-only exact entries without a best move + +Why it looked plausible: +- qsearch creates a large number of shallow TT entries +- some of those entries may carry little move-order value but still cost dict writes and replacement churn +- this was a much narrower experiment than replacing the TT itself + +Result: +- Broad benchmarks regressed again, so this qsearch TT-storage slice should also be treated as rejected: + - capture-storm-qsearch: slower and more evals + - tt-transposition-midgame: slower and more evals + - initial-position: slower and more evals + - harvested qsearch-heavy: slower and more evals +- Conclusion: reducing qsearch TT writes in this way weakened reuse more than it reduced overhead. + +Updated conclusion: +- preserve the current qsearch TT storage policy for now +- do not revisit this specific “skip upper / stand-pat-only exact qsearch stores” variant as a first-line optimization +- Stage 1 structural pure-Python tuning is now showing a consistent pattern of broad regressions across all recent rewrite-style experiments + +---------------------------------------------------------------------- + +General conclusion: accept that further speed gains likely need a non-Python escape hatch for the hottest paths + +The present structure is: Present pyengine2 data-structure design, as it stands now: + +**Core Shape** +- The engine is centered on a numeric, search-oriented core in native_engine.py. +- Board state is a fixed-size 91-square array of integer piece codes, not SAN strings or object-heavy piece instances. +- That board is kept in sync with bitmask-style occupancy state: + - per-piece masks + - per-color masks +- King locations are cached directly on the position object, so king lookup is constant-time rather than scanned from the board state. See native_engine.py and native_engine.py. + +**Move Representation** +- Internal moves are packed integers, not objects. Encoding and decoding helpers live in native_engine.py. +- SAN is used as a thin interface layer only. The San dataclass exists mainly as an adapter between human-readable move strings and packed move codes. See native_engine.py. +- Public move APIs remain string-friendly, but the search path stays integer-based. + +**Precomputed Board Data** +- Geometry and attack support are heavily precomputed: + - board graph + - ray masks + - ray attack tables + - king masks + - knight masks + - pawn attack tables +- Those tables are constructed once and then reused throughout move generation and legality checks. The main table builders are in native_engine.py. +- This is one of the strongest current design choices. The engine is not spending its time rediscovering board structure on every node. + +**Position Object** +- The position container is the Hexchess class in native_engine.py. +- It owns: + - board array + - piece masks + - color masks + - en passant square + - side to move + - halfmove and fullmove counters + - cached king squares + - Zobrist hash +- The Zobrist key is maintained incrementally during make and unmake, and exposed through position_key in native_engine.py. + +**Search Scratch State** +- Search scratch data lives in SearchState in native_engine.py. +- It currently uses: + - reusable per-ply move buffers + - reusable per-ply pin-mask buffers + - fixed-size history score array indexed by packed move code + - per-ply killer move slots + - counters for nodes, movegen calls, TT hits, TT cutoffs, and beta cutoffs +- This is the current low-allocation search scratch design. The earlier attempts to replace more pieces of the hot path with extra reusable structures did not help on benchmarks. + +**Move Generation** +- The main fast move-generation entry point is native_engine.py. +- Generation is specialized by piece type rather than routed through a generic polymorphic layer. +- There are two main paths: + - full legal move generation + - tactical-only move generation for qsearch +- The common fast branch already exists for the simple case of no check and no pins, which lets generation skip some of the more restrictive filtering logic after legal-context computation. + +**Legal Context Representation** +- Legal context is computed in native_engine.py. +- The representation currently returns: + - king square + - check count + - evasion mask + - full pin-mask array + - has-pins flag +- This is still a full-mask representation, not a sparse pinned-piece map. +- That design is heavier than ideal, but the attempted no-pin deferred-materialization variant also regressed, so the present implementation stays in place. + +**Make and Unmake** +- Move application remains tuple-based through make_move_unsafe and unmake_move in native_engine.py and native_engine.py. +- The undo record is a compact tuple of prior state needed to reverse the move. +- Search-only reusable undo storage was tried and rejected. The current tuple-based path is therefore still the chosen implementation. + +**Move Ordering** +- Full-search ordering is handled by optimize_for_branch_pruning in native_engine.py. +- Qsearch tactical ordering is handled by optimize_tactical_moves in native_engine.py. +- Current ordering uses: + - TT move promotion + - history scores + - killer moves + - MVV-LVA-style tactical scoring + - promotion bonuses + - Python list sort for the tactical list +- The attempted no-full-sort tactical front-promotion path regressed, so full tactical sorting remains the present design. + +**Transposition Table** +- The TT is still a normal Python dictionary keyed by Zobrist hash. +- Entries are stored as tuples containing depth, flag, value, and best move. The store helper is in native_engine.py. +- TT reuse is active in both qsearch and full negamax. See native_engine.py and native_engine.py. +- Both the fixed-size array-backed TT and the narrower qsearch-only reduced-store policy were tested and rejected. + +**Search Structure** +- Qsearch lives in native_engine.py. +- Full search lives in native_engine.py. +- Root search lives in native_engine.py. +- The algorithmic structure is: + - negamax + - alpha-beta pruning + - PVS-style narrow re-search for later siblings + - qsearch + - TT reuse + - conservative qsearch delta pruning + +**Current Design Verdict** +- The present data-structure design is stable and internally coherent. +- The board model, occupancy masks, packed moves, cached king squares, precomputed geometry, and reusable search scratch are the right foundation for this Python engine. +- The repeated failed experiments now strongly suggest that broad pure-Python structural rewrites are no longer the productive direction for Stage 1. +- In practical terms, the current design frontier is documented in 2-data-structures.txt and summarized operationally in memories/repo/pyengine2-stage1.md. + +Conlusion of experiments to 'improve' the data structures: Shortest summary: +- Keep the current board, masks, packed moves, TT dict, tuple undo, and full tactical sort. +- The engine’s current bottlenecks are now more about Python execution cost in repeated search work than about obviously wrong underlying data structures. + +----------------------------------------------------------------------- +the sensible directions are now: + +do a tighter measurement pass on specific branches or counters before changing code again +switch from speed-only structural tuning to algorithmic search improvements +continuation in: 3-algorithmic-search-improvements + +---------------------------------------------------------------------- + + + diff --git a/pyengine2/design/3-algorithmic-search-improvements.txt b/pyengine2/design/3-algorithmic-search-improvements.txt new file mode 100644 index 00000000..a847443a --- /dev/null +++ b/pyengine2/design/3-algorithmic-search-improvements.txt @@ -0,0 +1,245 @@ +measurement pass on specific branches and counters + +What was added: +- split TT hits and TT cutoffs into negamax and quiescence counts +- split beta cutoffs into negamax and quiescence counts +- added qsearch stand-pat cutoff count +- added qsearch delta-prune checks and skips +- added qsearch nodes-with-moves and total generated tactical moves +- added PVS re-search count + +Focused measurement summary from the current tree: +- PVS re-searches are rare relative to negamax node volume + - initial-position depth 5: 2,286 re-searches across 572,449 negamax nodes + - tt-transposition-midgame depth 5: 124 re-searches across 161,851 negamax nodes +- TT reuse is already materially important in both full search and qsearch + - initial-position depth 5: 119,781 negamax TT hits and 77,033 qsearch TT hits + - tt-transposition-midgame depth 5: 47,257 negamax TT hits and 4,107 qsearch TT hits +- qsearch still dominates the broad baseline work profile + - initial-position depth 5: 1,082,998 qsearch nodes vs 572,449 negamax nodes + - harvested qsearch-heavy depth 3: 47,719 qsearch nodes vs 12,374 negamax nodes +- A large share of qsearch ends at cheap stand-pat or qsearch beta-cutoff decisions + - initial-position depth 5: 373,425 stand-pat cutoffs and 262,245 qsearch beta cutoffs + - harvested qsearch-heavy depth 3: 16,389 stand-pat cutoffs and 13,118 qsearch beta cutoffs +- Delta pruning is highly effective when it activates, but it activates on a relatively small subset of qsearch work + - initial-position depth 5: 62,952 checks, 58,130 skips + - tt-transposition-midgame depth 5: 9,825 checks, 7,650 skips + - harvested qsearch-heavy depth 3: 596 checks, 535 skips +- Tactical lists are usually small enough that sorting itself is not the dominant problem + - capture-storm-qsearch depth 5: 1,051 tactical moves across 1,036 qsearch nodes with moves + - initial-position depth 5: 1,257,887 tactical moves across 528,843 qsearch nodes with moves, about 2.4 per node + +What this means: +- move-order micro-structure is not the best next target +- PVS behavior is not the main bottleneck +- reducing TT storage is the wrong direction because reuse is still paying for itself +- the best algorithmic opportunity is to reduce how often search falls into expensive qsearch work, or to make more qsearch nodes terminate on static bounds sooner + +Best algorithmic next step: +- target qsearch entry and pruning policy, not structure +- the first candidate should be a measured algorithmic pruning change such as: + - frontier futility pruning at shallow negamax depths before entering qsearch, or + - a broader but still conservative qsearch delta-pruning activation rule + +Recommended order from here: +1. prototype a conservative frontier futility pruning rule for depth-1 non-check nodes +2. if that is not broad-positive, test a measured expansion of qsearch delta-prune activation +3. only after those, consider larger algorithmic pruning families such as null-move pruning or late-move reductions + +Result of the first algorithmic slice: +- Implemented a conservative frontier futility rule in negamax for depth-1 non-check nodes only +- The rule only considers later quiet moves after earlier ordering work has already happened +- It never prunes the TT move and never prunes tactical moves +- The final version uses lazy setup so the check test and stand-pat eval are only computed when a later quiet move actually becomes eligible for pruning + +Refined benchmark outcome versus the measurement baseline: +- capture-storm-qsearch: depth 4 improved from 360.2 ms to 341.8 ms, depth 5 regressed slightly from 1125.8 ms to 1129.2 ms +- tt-transposition-midgame: depth 4 improved from 1208.9 ms to 866.4 ms, depth 5 improved from 5336.4 ms to 4924.0 ms +- initial-position: depth 4 improved from 7157.6 ms to 7093.9 ms, depth 5 improved from 45708.9 ms to 45558.1 ms +- harvested-qsearch-heavy: depth 2 improved from 135.8 ms to 125.4 ms, depth 3 improved from 1536.8 ms to 1433.6 ms + +Interpretation: +- This is broad-positive enough to keep provisionally in the tree +- The one regression is small and isolated to capture-storm depth 5 +- The biggest gains appear in the TT-heavy middlegame case, where the rule removes a large number of late quiet branches before they feed more search and qsearch work +- The harvested qsearch-heavy case saw zero actual frontier-futility skips, but the lazy setup kept overhead low enough that the case still improved + +Recommended next step from this point: +1. keep the lazy frontier futility rule in place +2. rerun a clean non-instrumented speed pass before promoting it into any formal baseline +3. continue with the next measured algorithmic slice, most likely a conservative expansion of qsearch delta-prune activation + +Result of the next measured qsearch slice: +- Tried a conservative expansion of qsearch delta-prune activation only +- The per-move prune rule was left unchanged +- Only the activation gate was widened from stand-pat plus rook value plus check value to stand-pat plus bishop value plus check value + +Outcome versus the current frontier-futility measurement tree: +- capture-storm-qsearch: slower at both depths + - depth 4: 341.8 ms to 353.2 ms + - depth 5: 1129.2 ms to 1149.4 ms +- tt-transposition-midgame: mixed and not strong enough to save the change + - depth 4: 866.4 ms to 868.8 ms + - depth 5: 4924.0 ms to 4860.8 ms +- initial-position: slower at both depths + - depth 4: 7093.9 ms to 7155.0 ms + - depth 5: 45558.1 ms to 45649.7 ms +- harvested-qsearch-heavy: slower at both depths + - depth 2: 125.4 ms to 135.7 ms + - depth 3: 1433.6 ms to 1591.6 ms + +Interpretation: +- The wider gate did increase delta-prune checks substantially +- But the added control-path work was not paid back by enough extra useful skips on the broad benchmark set +- This exact activation-threshold expansion should be treated as rejected and reverted + +Updated direction from here: +1. keep lazy frontier futility as the last broad-positive change +2. stop widening qsearch delta-prune activation by threshold alone +3. if continuing algorithmic pruning work, move to a different family such as a conservative null-move pruning experiment rather than another small qsearch gate expansion + +Benchmark-control improvement completed: +- search() now supports an explicit diagnostics toggle +- benchmark.py defaults to clean search runs with only the stable metric set +- benchmark.py --diagnostics enables the extra branch and cutoff counters for measurement runs +- this keeps clean speed decisions and instrumented diagnosis on the same codepath without forcing both to pay for the extra hot-path counter updates + +Result of the first conservative null-move slice: +- Added a reversible null-move path that changes only turn, en-passant state, clocks, and zobrist hash +- Added hard gates before trying null move: + - depth at least 3 below the root negamax frame + - not in check + - side to move has non-pawn material + - static eval already at or above beta +- Used a null-window verification search with reduction 2 + +Diagnostic measurement outcome versus the frontier-futility tree: +- capture-storm-qsearch: + - depth 4: unchanged in practice and null move inactive + - depth 5: improved from 1129.2 ms to 729.5 ms with 755 attempts and 677 cutoffs +- tt-transposition-midgame: + - depth 4: unchanged in practice and null move inactive + - depth 5: improved from 4924.0 ms to 3998.3 ms with 1184 attempts and 501 cutoffs +- initial-position: + - depth 4: unchanged in practice and null move inactive + - depth 5: improved from 45558.1 ms to 29571.1 ms with 1692 attempts and 1383 cutoffs +- harvested-qsearch-heavy: + - depth 2 and depth 3: null move inactive because the depth gate is not reached + +Clean Stage 1 suite outcome versus the official baseline: +- tt-transposition-midgame: + - depth 4: 1147.8 ms to 854.1 ms + - depth 5: 5108.5 ms to 3950.3 ms +- capture-storm-qsearch: + - depth 4: effectively unchanged at 346.7 ms to 347.1 ms + - depth 5: 1077.5 ms to 710.6 ms +- initial-position: + - depth 4: slightly slower at 6778.4 ms to 6930.6 ms + - depth 5: 42528.3 ms to 29446.7 ms + +Keep decision: +- Keep this null-move slice provisionally in the tree +- The clean benchmark set is strongly positive overall +- One shallow opening case remains slightly slower, but the depth-5 search cases improved enough to justify keeping the feature +- The harvested case was rerun in clean mode after an apparent slowdown and the repeat result returned to the prior no-null range, so that earlier harvested regression should be treated as timing noise rather than a stable blocker + +Sequential clean validation follow-up: +- A parallel clean rerun was discarded because it was contaminated by benchmark contention on the same machine +- A sequential repeat-5 opening check and a second sequential full Stage 1 suite both confirmed the null-move depth-5 gains +- The validated clean baseline snapshot for future comparisons is now results/2.1.003/stage1-baseline-null-move.yaml + +Sequential clean Stage 1 validation versus the previous official baseline: +- tt-transposition-midgame: + - depth 4: 1147.8 ms to 862.7 ms + - depth 5: 5108.5 ms to 3891.1 ms +- capture-storm-qsearch: + - depth 4: 346.7 ms to 335.9 ms + - depth 5: 1077.5 ms to 701.8 ms +- initial-position: + - depth 4: 6778.4 ms to 6955.0 ms + - depth 5: 42528.3 ms to 28935.7 ms + +Interpretation after sequential validation: +- The shallow opening slowdown remains small but real enough to keep watching +- It is not caused by null move itself at depth 4, because the current null-move depth gate does not activate on the depth-4 search profile +- Future tuning should therefore avoid treating the depth-4 opening number as a null-move gating problem + +Follow-up on the remaining initial-position depth-4 regression: +- Disabling frontier futility made the opening case worse, so frontier futility is helping rather than causing the remaining slowdown +- Keeping frontier futility enabled while temporarily disabling null move produced essentially the same initial-position depth-4 timing as the full tree, which confirms the remaining depth-4 gap is not a null-move activation effect + +Rejected clean-recursion split experiment: +- Tried splitting search recursion into a clean path with no diagnostic-counter branches and a separate diagnostic path with the extra counters +- Result: + - initial-position depth 4 improved slightly from about 7075.6 ms to about 6970.2 ms on repeat-5 clean runs + - but initial-position depth 5 regressed badly from about 29183.8 ms to about 35876.8 ms with identical node counts and identical search-shape metrics +- Conclusion: + - this split-recursion approach is rejected and reverted + - the slowdown was interpreter overhead from the refactor itself, not a search improvement + - the remaining shallow opening regression is therefore still unresolved, but it is now better bounded: it is not due to frontier futility and not due to null-move activation at depth 4 + +Repository hygiene follow-up: +- Cleaned out the temporary isolation artifacts from the opening-regression investigation +- Cleaned out the non-canonical null-move validation snapshots and ad hoc clean harvested comparator reruns +- The promoted clean reference point remains results/2.1.003/stage1-baseline-null-move.yaml +- The measurement history and source saved-game logs were left intact + +Next optimization pass: depth-0 non-check leaf fast path +- Found a hot-path ordering problem in negamax: + - depth-0 nodes were still building a full legal move list before returning to qsearch + - that full move generation is only needed at depth 0 when the side to move is in check, so non-check leaves were paying avoidable overhead +- Kept the existing mate and stalemate handling for checked leaf nodes +- Changed the leaf path so depth-0 non-check nodes jump straight into quiescence without first calling full legal move generation + +Clean benchmark outcome versus the promoted baseline: +- tt-transposition-midgame: + - depth 4: 862.7 ms to 554.5 ms + - depth 5: 3891.1 ms to 2788.2 ms +- capture-storm-qsearch: + - depth 4: 335.9 ms to 213.2 ms + - depth 5: 701.8 ms to 511.3 ms +- initial-position: + - depth 4: 6955.0 ms to 3202.6 ms + - depth 5: 28935.7 ms to 21863.1 ms +- harvested-qsearch-heavy standing check: + - depth 2: about 126.6 ms to 54.6 ms + - depth 3: about 1483.8 ms to 1227.8 ms + +Interpretation: +- This is a clear keep +- The gain is broad rather than case-specific, which matches the code path: depth-0 non-check leaves occur everywhere in the tree +- The especially large opening improvement supports the earlier suspicion that too much work was still happening before qsearch on shallow frontier nodes +- The null-move and frontier-futility decisions remain unchanged; this slice removes unrelated leaf overhead beneath those already-kept features + +Diagnostic follow-up after promoting the leaf fast path: +- Wrote a new clean baseline snapshot to results/2.1.003/stage1-baseline-leaf-fastpath.yaml +- Refreshed the four diagnostic reports on the current tree: + - results/2.1.003/measurement-capture-storm-qsearch-leaf-fastpath.yaml + - results/2.1.003/measurement-tt-transposition-midgame-leaf-fastpath.yaml + - results/2.1.003/measurement-initial-position-leaf-fastpath.yaml + - results/2.1.003/measurement-harvested-qsearch-heavy-leaf-fastpath.yaml + +What the refreshed diagnostics say: +- The leaf-path win came from removing wasted full move-generation and legal-context work, not from changing the search shape + - node counts, TT counts, beta cutoffs, null-move counts, and qsearch counters stayed effectively the same + - movegenCalls and legalContextCalls dropped sharply because non-check depth-0 leaves no longer build full legal move lists before entering qsearch +- qsearch is still the dominant cost center on the broad search cases even after that fix + - initial-position depth 5: 691,299 qsearch nodes vs 391,552 negamax nodes + - harvested qsearch-heavy depth 3: 47,719 qsearch nodes vs 12,374 negamax nodes +- Tactical lists are still small on average + - initial-position depth 5: 775,113 tactical moves across 324,483 qsearch nodes with moves, about 2.4 per node + - harvested qsearch-heavy depth 3: 67,578 tactical moves across 23,997 qsearch nodes with moves, about 2.8 per node +- Null move remains a strong depth-5 contributor where it is active + - initial-position depth 5: 1,692 attempts and 1,383 cutoffs + - tt-transposition-midgame depth 5: 1,184 attempts and 501 cutoffs + - capture-storm-qsearch depth 5: 755 attempts and 677 cutoffs + +Updated direction from here: +1. preserve the new leaf fast path as part of the official comparison tree +2. stop looking for more full-search leaf overhead in negamax; the obvious waste there is already removed +3. focus the next measurement-guided experiment on non-check qsearch node cost, especially the legal-context and tactical-generation work that still sits behind stand-pat survival + +------------------------------------------------ + + + diff --git a/pyengine2/design/4-benchmark-strategy.txt b/pyengine2/design/4-benchmark-strategy.txt new file mode 100644 index 00000000..f2157caa --- /dev/null +++ b/pyengine2/design/4-benchmark-strategy.txt @@ -0,0 +1,172 @@ +benchmark strategy + +Goal: +- separate speed benchmarking from diagnostic measurement +- keep performance decisions clean +- use instrumented runs to choose the next experiment, not to declare a new speed baseline + +Core rule: +- clean speed runs answer: faster or slower? +- instrumented measurement runs answer: why is it faster or slower? + +1. clean speed baseline track + +Purpose: +- decide whether a code change stays or is reverted +- maintain the official Stage 1 comparison baseline + +Rules: +- use the normal engine path with no extra diagnostic counters beyond the stable metrics already used in baseline reports +- use benchmark.py without --diagnostics for clean speed runs +- compare candidate changes only against the official speed baseline from results/2.1.003/stage1-baseline-leaf-fastpath.yaml +- only clean speed runs may justify updating the baseline +- do not run clean speed benchmarks in parallel with other benchmarks on the same machine; use sequential runs only + +Primary cases for keep-or-revert decisions: +- initial-position +- tt-transposition-midgame +- capture-storm-qsearch +- harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy +- harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + +Interpretation: +- if a change is not broadly positive on this set, revert it +- narrow wins are not enough if opening or TT-sensitive cases regress + +Current clean comparison suite: +- python pyengine2/benchmark.py --suite clean-search-comparison --output results/2.1.003/clean-search-comparison.yaml + +2. diagnostic measurement track + +Purpose: +- identify the next likely optimization target before changing code +- explain why a kept change helped or hurt + +Rules: +- use the instrumented engine build with extra counters +- use benchmark.py with --diagnostics for measurement runs +- use the harvested-diagnostics suite for quick reruns of the March 29 harvested stress set +- use the harvested-history-diagnostics suite for the March 24 and March 26 harvested positions +- do not treat the wall-clock results from these runs as the official speed baseline +- use these runs for branch ratios, cutoff composition, and relative behavior only + +Current measurement reports: +- results/2.1.003/measurement-capture-storm-qsearch-leaf-fastpath.yaml +- results/2.1.003/measurement-tt-transposition-midgame-leaf-fastpath.yaml +- results/2.1.003/measurement-initial-position-leaf-fastpath.yaml +- results/2.1.003/measurement-harvested-qsearch-heavy-leaf-fastpath.yaml + +Current diagnostic suite: +- python pyengine2/benchmark.py --suite harvested-diagnostics --diagnostics --output results/2.1.003/harvested-diagnostics-20260329.yaml +- python pyengine2/benchmark.py --suite harvested-history-diagnostics --diagnostics --output results/2.1.003/harvested-history-diagnostics-20260329.yaml + +Current fine-grained counters: +- negamaxTtHits +- quiescenceTtHits +- negamaxTtCutoffs +- quiescenceTtCutoffs +- negamaxBetaCutoffs +- quiescenceBetaCutoffs +- qsearchStandPatCutoffs +- qsearchDeltaPruneChecks +- qsearchDeltaPruneSkips +- qsearchNodesWithMoves +- qsearchGeneratedMoves +- pvsResearches + +3. ratios to inspect in measurement runs + +These ratios are more useful than raw totals alone: + +- qsearch share: + - quiescenceNodes / max(negamaxNodes, 1) + +- TT usefulness split: + - negamaxTtCutoffs / max(negamaxTtHits, 1) + - quiescenceTtCutoffs / max(quiescenceTtHits, 1) + +- qsearch stand-pat dominance: + - qsearchStandPatCutoffs / max(quiescenceNodes, 1) + +- qsearch beta-cutoff dominance: + - quiescenceBetaCutoffs / max(quiescenceNodes, 1) + +- delta-prune effectiveness: + - qsearchDeltaPruneSkips / max(qsearchDeltaPruneChecks, 1) + +- tactical list pressure: + - qsearchGeneratedMoves / max(qsearchNodesWithMoves, 1) + +- PVS overhead: + - pvsResearches / max(negamaxNodes, 1) + +4. present measurement conclusions + +The current instrumented runs say: + +- the new official baseline removed a large amount of wasted full move generation at depth-0 non-check leaves + - node counts stayed the same, but movegenCalls and legalContextCalls dropped sharply on all search cases + +- PVS is not the main bottleneck + - re-search frequency is low relative to negamax node count + +- TT reuse is still valuable + - reducing TT storage or reuse has been a losing direction + +- qsearch still dominates broad search cost + - especially in opening and harvested qsearch-heavy positions even after the depth-0 leaf fast path + - initial-position depth 5 is still about 691k qsearch nodes versus about 392k negamax nodes + - harvested qsearch-heavy depth 3 is still about 47.7k qsearch nodes versus about 12.4k negamax nodes + +- many qsearch nodes terminate cheaply + - stand-pat cutoffs and qsearch beta cutoffs are both large + +- delta pruning is effective when it activates + - but it activates on only a subset of qsearch work + +- tactical list sizes are often small + - so tactical sorting micro-structure is not the main benchmark problem + +Implication: +- the next improvements should target qsearch-side cost, not another full-search structural rewrite +- the biggest obvious full-search leaf overhead has already been removed +- the remaining likely wins are in how expensive non-check qsearch nodes are to enter and process + +5. benchmark workflow for future experiments + +Use this loop for every future search experiment: + +1. use the current measurement reports to pick one narrow target +2. implement one change only +3. run regression tests +4. run the clean speed benchmark set +5. keep or revert based only on the clean speed run +6. if the change is promising, run the diagnostic measurement track +7. confirm the expected mechanism from ratios and branch counts + +This avoids using instrumented timing noise as a performance decision tool. + +6. benchmark interpretation policy + +Clean speed run: +- authoritative for faster or slower decisions + +Instrumented measurement run: +- authoritative for branch ratios and search-shape interpretation +- not authoritative for declaring a new speed baseline + +7. next algorithmic search target + +Based on the current measurements, the first algorithmic search experiments should be: + +1. inspect and measure non-check qsearch node cost, especially legal-context and tactical move generation work after stand-pat survives +2. if a narrow common path is visible there, prototype one qsearch-only fast path and judge it only on the clean comparison set + +Only after that should larger pruning families be reconsidered, such as: +- deeper null-move tuning +- late-move reductions + +Short version: +- use clean benchmarks to decide +- use measurement benchmarks to understand +- do not mix those two jobs in the same baseline conversation diff --git a/pyengine2/main.py b/pyengine2/main.py index 8314ebab..6152eb12 100644 --- a/pyengine2/main.py +++ b/pyengine2/main.py @@ -44,6 +44,10 @@ class ExecuteFailure(BaseModel): app.add_middleware( CORSMiddleware, allow_origins=[ + "http://localhost:4173", + "http://127.0.0.1:4173", + "http://localhost:4175", + "http://127.0.0.1:4175", "http://localhost:5173", "http://127.0.0.1:5173", ], diff --git a/pyengine2/native_engine.py b/pyengine2/native_engine.py index d962b749..c1d7e0fa 100644 --- a/pyengine2/native_engine.py +++ b/pyengine2/native_engine.py @@ -575,6 +575,7 @@ def __str__(self) -> str: MoveUndo = tuple[int, int, int, int, int, int, int, int, int, int, int] +NullMoveUndo = tuple[int, int, int, int, int] LegalContext = tuple[int, int, int, list[int], bool] RayScanEntry = tuple[int, int, int] @@ -594,6 +595,7 @@ class EvalOptions: @dataclass(slots=True) class SearchState: + diagnostics_enabled: bool move_buffers: list[list[int]] pin_mask_buffers: list[list[int]] killer_primary: list[int] @@ -607,8 +609,25 @@ class SearchState: tt_hits: int tt_cutoffs: int beta_cutoffs: int - - def __init__(self) -> None: + negamax_tt_hits: int + quiescence_tt_hits: int + negamax_tt_cutoffs: int + quiescence_tt_cutoffs: int + negamax_beta_cutoffs: int + quiescence_beta_cutoffs: int + qsearch_stand_pat_cutoffs: int + qsearch_delta_prune_checks: int + qsearch_delta_prune_skips: int + qsearch_nodes_with_moves: int + qsearch_generated_moves: int + pvs_researches: int + negamax_frontier_futility_checks: int + negamax_frontier_futility_skips: int + null_move_attempts: int + null_move_cutoffs: int + + def __init__(self, diagnostics_enabled: bool = True) -> None: + self.diagnostics_enabled = diagnostics_enabled self.move_buffers = [] self.pin_mask_buffers = [] self.killer_primary = [] @@ -622,6 +641,22 @@ def __init__(self) -> None: self.tt_hits = 0 self.tt_cutoffs = 0 self.beta_cutoffs = 0 + self.negamax_tt_hits = 0 + self.quiescence_tt_hits = 0 + self.negamax_tt_cutoffs = 0 + self.quiescence_tt_cutoffs = 0 + self.negamax_beta_cutoffs = 0 + self.quiescence_beta_cutoffs = 0 + self.qsearch_stand_pat_cutoffs = 0 + self.qsearch_delta_prune_checks = 0 + self.qsearch_delta_prune_skips = 0 + self.qsearch_nodes_with_moves = 0 + self.qsearch_generated_moves = 0 + self.pvs_researches = 0 + self.negamax_frontier_futility_checks = 0 + self.negamax_frontier_futility_skips = 0 + self.null_move_attempts = 0 + self.null_move_cutoffs = 0 def buffer_for(self, ply: int) -> list[int]: while len(self.move_buffers) <= ply: @@ -649,7 +684,7 @@ def record_killer(self, ply: int, move_code: int) -> None: self.killer_secondary[ply] = first if first != move_code else second def metrics_dict(self, root_moves: int, wall_ms: float, evaluations: int, tt_entries: int) -> dict[str, int | float]: - return { + metrics: dict[str, int | float] = { 'wallMs': wall_ms, 'evalsPerMs': evaluations / wall_ms if wall_ms > 0 else 0.0, 'rootMoves': root_moves, @@ -663,6 +698,28 @@ def metrics_dict(self, root_moves: int, wall_ms: float, evaluations: int, tt_ent 'betaCutoffs': self.beta_cutoffs, 'ttEntries': tt_entries, } + if self.diagnostics_enabled: + metrics.update( + { + 'negamaxTtHits': self.negamax_tt_hits, + 'quiescenceTtHits': self.quiescence_tt_hits, + 'negamaxTtCutoffs': self.negamax_tt_cutoffs, + 'quiescenceTtCutoffs': self.quiescence_tt_cutoffs, + 'negamaxBetaCutoffs': self.negamax_beta_cutoffs, + 'quiescenceBetaCutoffs': self.quiescence_beta_cutoffs, + 'qsearchStandPatCutoffs': self.qsearch_stand_pat_cutoffs, + 'qsearchDeltaPruneChecks': self.qsearch_delta_prune_checks, + 'qsearchDeltaPruneSkips': self.qsearch_delta_prune_skips, + 'qsearchNodesWithMoves': self.qsearch_nodes_with_moves, + 'qsearchGeneratedMoves': self.qsearch_generated_moves, + 'pvsResearches': self.pvs_researches, + 'negamaxFrontierFutilityChecks': self.negamax_frontier_futility_checks, + 'negamaxFrontierFutilitySkips': self.negamax_frontier_futility_skips, + 'nullMoveAttempts': self.null_move_attempts, + 'nullMoveCutoffs': self.null_move_cutoffs, + } + ) + return metrics @dataclass(slots=True) @@ -1630,6 +1687,35 @@ def unmake_move(self, undo: MoveUndo) -> None: self.black_king = previous_black_king self.zobrist_hash = previous_hash + def make_null_move(self) -> NullMoveUndo: + previous_ep = self.ep + previous_turn = self.turn + previous_halfmove = self.halfmove + previous_fullmove = self.fullmove + previous_hash = self.zobrist_hash + + if self.ep != -1: + self.zobrist_hash ^= ZOBRIST_EP[self.ep] + self.ep = -1 + + self.halfmove += 1 + if self.turn == BLACK: + self.fullmove += 1 + self.turn = WHITE + else: + self.turn = BLACK + self.zobrist_hash ^= ZOBRIST_TURN + + return previous_ep, previous_turn, previous_halfmove, previous_fullmove, previous_hash + + def unmake_null_move(self, undo: NullMoveUndo) -> None: + previous_ep, previous_turn, previous_halfmove, previous_fullmove, previous_hash = undo + self.ep = previous_ep + self.turn = previous_turn + self.halfmove = previous_halfmove + self.fullmove = previous_fullmove + self.zobrist_hash = previous_hash + def to_string(self) -> str: en_passant = '-' if self.ep == -1 else POSITIONS[self.ep] return f'{stringify_board(self.board)} {_color_to_char(self.turn)} {en_passant} {self.halfmove} {self.fullmove}' @@ -1703,6 +1789,29 @@ def static_eval_for_turn(hexchess: Hexchess, options: EvalOptions) -> float: TranspositionEntry = tuple[int, str, float, int | None] +RepetitionCounts = dict[int, int] + + +def _build_repetition_counts(position_history: list[str] | None) -> RepetitionCounts: + counts: RepetitionCounts = {} + if position_history is None: + return counts + for fen in position_history: + key = Hexchess.parse(fen).position_key() + counts[key] = counts.get(key, 0) + 1 + return counts + + +def _push_repetition_count(repetition_counts: RepetitionCounts, key: int) -> None: + repetition_counts[key] = repetition_counts.get(key, 0) + 1 + + +def _pop_repetition_count(repetition_counts: RepetitionCounts, key: int) -> None: + count = repetition_counts.get(key, 0) + if count <= 1: + repetition_counts.pop(key, None) + return + repetition_counts[key] = count - 1 def _is_tactical_move(hexchess: Hexchess, move_code: int) -> bool: @@ -1769,6 +1878,12 @@ def _passes_qsearch_delta_prune( return stand_pat + optimistic_gain + delta_margin > alpha +def _has_non_pawn_material(hexchess: Hexchess, color: int) -> bool: + if color == WHITE: + return any(hexchess.piece_masks[piece] for piece in (WR, WN, WB, WQ)) + return any(hexchess.piece_masks[piece] for piece in (BR, BN, BB, BQ)) + + def _promote_move_to_front(moves: list[int], prioritized_move: int | None) -> None: if prioritized_move is None or len(moves) < 2: return @@ -1868,6 +1983,7 @@ def quiescence( hexchess: Hexchess, state: SearchState, table: dict[int, TranspositionEntry], + repetition_counts: RepetitionCounts, ply: int, alpha: float, beta: float, @@ -1877,64 +1993,91 @@ def quiescence( state.quiescence_nodes += 1 alpha_orig = alpha key = hexchess.position_key() - entry = table.get(key) - tt_move = entry[3] if entry is not None else None - if entry is not None: - state.tt_hits += 1 - entry_depth, flag, value, _ = entry - if entry_depth >= 0: - if flag == 'exact': - state.tt_cutoffs += 1 - return value - if flag == 'lower' and value >= beta: - state.tt_cutoffs += 1 - return value - if flag == 'upper' and value <= alpha: - state.tt_cutoffs += 1 - return value - - evaluations[0] += 1 - stand_pat = static_eval_for_turn(hexchess, options) - if stand_pat >= beta: - store_transposition_entry(table, key, 0, 'lower', stand_pat, tt_move) - return stand_pat - if stand_pat > alpha: - alpha = stand_pat - tactical_moves = hexchess._fill_current_moves(state.buffer_for(ply), tactical_only=True, pin_masks=state.pin_masks_for(ply), stats=state) - if not tactical_moves: - return stand_pat - optimize_tactical_moves(hexchess, tactical_moves, tt_move) - value = stand_pat - best_move: int | None = None - delta_prune_active = alpha > stand_pat + options.rook_value + options.check_value - in_check = hexchess.is_check() if delta_prune_active else False - for move_code in tactical_moves: - if delta_prune_active and not in_check and not _passes_qsearch_delta_prune(hexchess, move_code, stand_pat, alpha, tt_move, options): - continue - undo = hexchess.make_move_unsafe(move_code) - child_value = -quiescence(hexchess, state, table, ply + 1, -beta, -alpha, evaluations, options) - hexchess.unmake_move(undo) - if child_value >= beta: - state.beta_cutoffs += 1 - store_transposition_entry(table, key, 0, 'lower', child_value, move_code) - return child_value - if child_value > value: - value = child_value - best_move = move_code - if child_value > alpha: - alpha = child_value - flag = 'exact' - if value <= alpha_orig: - flag = 'upper' - elif value >= beta: - flag = 'lower' - store_transposition_entry(table, key, 0, flag, value, best_move) - return value + if repetition_counts.get(key, 0) >= 2: + return 0.0 + _push_repetition_count(repetition_counts, key) + try: + entry = table.get(key) + tt_move = entry[3] if entry is not None else None + if entry is not None: + state.tt_hits += 1 + if state.diagnostics_enabled: + state.quiescence_tt_hits += 1 + entry_depth, flag, value, _ = entry + if entry_depth >= 0: + if flag == 'exact': + state.tt_cutoffs += 1 + if state.diagnostics_enabled: + state.quiescence_tt_cutoffs += 1 + return value + if flag == 'lower' and value >= beta: + state.tt_cutoffs += 1 + if state.diagnostics_enabled: + state.quiescence_tt_cutoffs += 1 + return value + if flag == 'upper' and value <= alpha: + state.tt_cutoffs += 1 + if state.diagnostics_enabled: + state.quiescence_tt_cutoffs += 1 + return value + + evaluations[0] += 1 + stand_pat = static_eval_for_turn(hexchess, options) + if stand_pat >= beta: + if state.diagnostics_enabled: + state.qsearch_stand_pat_cutoffs += 1 + store_transposition_entry(table, key, 0, 'lower', stand_pat, tt_move) + return stand_pat + if stand_pat > alpha: + alpha = stand_pat + tactical_moves = hexchess._fill_current_moves(state.buffer_for(ply), tactical_only=True, pin_masks=state.pin_masks_for(ply), stats=state) + if not tactical_moves: + return stand_pat + if state.diagnostics_enabled: + state.qsearch_nodes_with_moves += 1 + state.qsearch_generated_moves += len(tactical_moves) + optimize_tactical_moves(hexchess, tactical_moves, tt_move) + value = stand_pat + best_move: int | None = None + delta_prune_active = alpha > stand_pat + options.rook_value + options.check_value + in_check = hexchess.is_check() if delta_prune_active else False + for move_code in tactical_moves: + if delta_prune_active and not in_check: + if state.diagnostics_enabled: + state.qsearch_delta_prune_checks += 1 + if not _passes_qsearch_delta_prune(hexchess, move_code, stand_pat, alpha, tt_move, options): + if state.diagnostics_enabled: + state.qsearch_delta_prune_skips += 1 + continue + undo = hexchess.make_move_unsafe(move_code) + child_value = -quiescence(hexchess, state, table, repetition_counts, ply + 1, -beta, -alpha, evaluations, options) + hexchess.unmake_move(undo) + if child_value >= beta: + state.beta_cutoffs += 1 + if state.diagnostics_enabled: + state.quiescence_beta_cutoffs += 1 + store_transposition_entry(table, key, 0, 'lower', child_value, move_code) + return child_value + if child_value > value: + value = child_value + best_move = move_code + if child_value > alpha: + alpha = child_value + flag = 'exact' + if value <= alpha_orig: + flag = 'upper' + elif value >= beta: + flag = 'lower' + store_transposition_entry(table, key, 0, flag, value, best_move) + return value + finally: + _pop_repetition_count(repetition_counts, key) def negamax( state: SearchState, table: dict[int, TranspositionEntry], + repetition_counts: RepetitionCounts, hexchess: Hexchess, depth: int, ply: int, @@ -1943,80 +2086,165 @@ def negamax( evaluations: list[int], options: EvalOptions, ) -> float: + null_move_reduction = 2 state.negamax_nodes += 1 alpha_orig = alpha key = hexchess.position_key() - entry = table.get(key) - tt_move = entry[3] if entry is not None else None - if entry is not None: - state.tt_hits += 1 - entry_depth, flag, value, _ = entry - if entry_depth >= depth: - if flag == 'exact': - state.tt_cutoffs += 1 - return value - if flag == 'lower' and value >= beta: - state.tt_cutoffs += 1 - return value - if flag == 'upper' and value <= alpha: - state.tt_cutoffs += 1 - return value - current_moves = hexchess._fill_current_moves(state.buffer_for(ply), tactical_only=False, pin_masks=state.pin_masks_for(ply), stats=state) - if not current_moves: - evaluations[0] += 1 - if hexchess.is_check(): - return options.checkmate_value if hexchess.turn == WHITE else -options.checkmate_value - return options.stalemate_value if hexchess.turn == WHITE else -options.stalemate_value - if depth == 0: - return quiescence(hexchess, state, table, ply, alpha, beta, evaluations, options) - optimize_for_branch_pruning(hexchess, current_moves, ply, state, tt_move) - value = float('-inf') - best_move: int | None = None - for move_index, move_code in enumerate(current_moves): - undo = hexchess.make_move_unsafe(move_code) - if move_index == 0: - child_value = -negamax(state, table, hexchess, depth - 1, ply + 1, -beta, -alpha, evaluations, options) - else: - child_value = -negamax(state, table, hexchess, depth - 1, ply + 1, -alpha - 1, -alpha, evaluations, options) - if child_value > alpha and child_value < beta: - child_value = -negamax(state, table, hexchess, depth - 1, ply + 1, -beta, -alpha, evaluations, options) - hexchess.unmake_move(undo) - if child_value > value: - value = child_value - best_move = move_code - alpha = max(alpha, value) - if alpha >= beta: - state.beta_cutoffs += 1 - if not _is_tactical_move(hexchess, move_code): - state.record_killer(ply, move_code) - state.history_scores[move_code] += depth * depth - best_move = move_code - break - flag = 'exact' - if value <= alpha_orig: - flag = 'upper' - elif value >= beta: - flag = 'lower' - store_transposition_entry(table, key, depth, flag, value, best_move) - return value - - -def search(hexchess: Hexchess, depth: int, options: EvalOptions | None = None) -> dict[str, object]: + if repetition_counts.get(key, 0) >= 2: + return 0.0 + _push_repetition_count(repetition_counts, key) + try: + in_check = False + entry = table.get(key) + tt_move = entry[3] if entry is not None else None + if entry is not None: + state.tt_hits += 1 + if state.diagnostics_enabled: + state.negamax_tt_hits += 1 + entry_depth, flag, value, _ = entry + if entry_depth >= depth: + if flag == 'exact': + state.tt_cutoffs += 1 + if state.diagnostics_enabled: + state.negamax_tt_cutoffs += 1 + return value + if flag == 'lower' and value >= beta: + state.tt_cutoffs += 1 + if state.diagnostics_enabled: + state.negamax_tt_cutoffs += 1 + return value + if flag == 'upper' and value <= alpha: + state.tt_cutoffs += 1 + if state.diagnostics_enabled: + state.negamax_tt_cutoffs += 1 + return value + if depth >= null_move_reduction + 1 or depth == 0: + in_check = hexchess.is_check() + if depth == 0 and not in_check: + return quiescence(hexchess, state, table, repetition_counts, ply, alpha, beta, evaluations, options) + if depth >= null_move_reduction + 1 and beta != float('inf') and not in_check and _has_non_pawn_material(hexchess, hexchess.turn): + static_eval = static_eval_for_turn(hexchess, options) + if static_eval >= beta: + if state.diagnostics_enabled: + state.null_move_attempts += 1 + undo = hexchess.make_null_move() + null_value = -negamax( + state, + table, + repetition_counts, + hexchess, + depth - null_move_reduction - 1, + ply + 1, + -beta, + -beta + 1, + evaluations, + options, + ) + hexchess.unmake_null_move(undo) + if null_value >= beta: + if state.diagnostics_enabled: + state.null_move_cutoffs += 1 + return null_value + current_moves = hexchess._fill_current_moves(state.buffer_for(ply), tactical_only=False, pin_masks=state.pin_masks_for(ply), stats=state) + if not current_moves: + evaluations[0] += 1 + if in_check or hexchess.is_check(): + return options.checkmate_value if hexchess.turn == WHITE else -options.checkmate_value + return options.stalemate_value if hexchess.turn == WHITE else -options.stalemate_value + if depth <= 0: + return quiescence(hexchess, state, table, repetition_counts, ply, alpha, beta, evaluations, options) + optimize_for_branch_pruning(hexchess, current_moves, ply, state, tt_move) + frontier_futility_enabled = depth == 1 + frontier_futility_checked = False + frontier_futility_ready = False + frontier_stand_pat = 0.0 + frontier_margin = options.rook_value + options.check_value + value = float('-inf') + best_move: int | None = None + for move_index, move_code in enumerate(current_moves): + if ( + frontier_futility_enabled + and move_index > 0 + and move_code != tt_move + and not _is_tactical_move(hexchess, move_code) + ): + if not frontier_futility_checked: + frontier_futility_checked = True + if not in_check: + in_check = hexchess.is_check() + if not in_check: + frontier_stand_pat = static_eval_for_turn(hexchess, options) + frontier_futility_ready = True + if frontier_futility_ready: + if state.diagnostics_enabled: + state.negamax_frontier_futility_checks += 1 + if alpha >= frontier_stand_pat + frontier_margin: + if state.diagnostics_enabled: + state.negamax_frontier_futility_skips += 1 + continue + undo = hexchess.make_move_unsafe(move_code) + if move_index == 0: + child_value = -negamax(state, table, repetition_counts, hexchess, depth - 1, ply + 1, -beta, -alpha, evaluations, options) + else: + child_value = -negamax(state, table, repetition_counts, hexchess, depth - 1, ply + 1, -alpha - 1, -alpha, evaluations, options) + if child_value > alpha and child_value < beta: + if state.diagnostics_enabled: + state.pvs_researches += 1 + child_value = -negamax(state, table, repetition_counts, hexchess, depth - 1, ply + 1, -beta, -alpha, evaluations, options) + hexchess.unmake_move(undo) + if child_value > value: + value = child_value + best_move = move_code + alpha = max(alpha, value) + if alpha >= beta: + state.beta_cutoffs += 1 + if state.diagnostics_enabled: + state.negamax_beta_cutoffs += 1 + if not _is_tactical_move(hexchess, move_code): + state.record_killer(ply, move_code) + state.history_scores[move_code] += depth * depth + best_move = move_code + break + flag = 'exact' + if value <= alpha_orig: + flag = 'upper' + elif value >= beta: + flag = 'lower' + store_transposition_entry(table, key, depth, flag, value, best_move) + return value + finally: + _pop_repetition_count(repetition_counts, key) + + +def search( + hexchess: Hexchess, + depth: int, + options: EvalOptions | None = None, + *, + diagnostics: bool = True, + position_history: list[str] | None = None, +) -> dict[str, object]: if depth < 1: error(f'invalid depth: {depth}') started_at = time.perf_counter() + root_key = hexchess.position_key() evaluation_options = options or EvalOptions() table: dict[int, TranspositionEntry] = {} + repetition_counts = _build_repetition_counts(position_history) evaluations = [0] - state = SearchState() + state = SearchState(diagnostics_enabled=diagnostics) sans: list[dict[str, object]] = [] root_moves = hexchess._fill_current_moves(state.buffer_for(0), tactical_only=False, pin_masks=state.pin_masks_for(0), stats=state) optimize_for_branch_pruning(hexchess, root_moves, 0, state) - for move_code in root_moves: - undo = hexchess.make_move_unsafe(move_code) - score = negamax(state, table, hexchess, depth - 1, 1, float('-inf'), float('inf'), evaluations, evaluation_options) - hexchess.unmake_move(undo) - sans.append({'san': str(San.from_code(move_code)), 'score': score}) + _push_repetition_count(repetition_counts, root_key) + try: + for move_code in root_moves: + undo = hexchess.make_move_unsafe(move_code) + score = negamax(state, table, repetition_counts, hexchess, depth - 1, 1, float('-inf'), float('inf'), evaluations, evaluation_options) + hexchess.unmake_move(undo) + sans.append({'san': str(San.from_code(move_code)), 'score': score}) + finally: + _pop_repetition_count(repetition_counts, root_key) sans.sort(key=lambda item: item['score']) wall_ms = (time.perf_counter() - started_at) * 1000.0 return { @@ -2038,9 +2266,16 @@ def execute_command(command: str, options: dict[str, object] | None = None) -> d if command == 'hexchess/evaluate': position = command_options.get('position') depth = command_options.get('depth') + position_history = command_options.get('positionHistory') if not isinstance(position, str): error('invalid position: expected string') if not isinstance(depth, int): error('invalid depth: expected integer') - return search(Hexchess.parse(position), depth) + if position_history is not None: + if not isinstance(position_history, list) or any(not isinstance(item, str) for item in position_history): + error('invalid positionHistory: expected list of strings') + diagnostics = command_options.get('diagnostics', True) + if not isinstance(diagnostics, bool): + error('invalid diagnostics: expected boolean') + return search(Hexchess.parse(position), depth, diagnostics=diagnostics, position_history=position_history) error(f'Unknown engine command: {command}') \ No newline at end of file diff --git a/pyengine2/test_native_engine.py b/pyengine2/test_native_engine.py index ddd762ca..f2b6509e 100644 --- a/pyengine2/test_native_engine.py +++ b/pyengine2/test_native_engine.py @@ -2,7 +2,7 @@ import unittest -from pyengine2.native_engine import CHAR_TO_PIECE, EvalOptions, Hexchess, INITIAL_POSITION, San, _passes_qsearch_delta_prune, create_board, evaluate, index, search, stringify_board +from pyengine2.native_engine import CHAR_TO_PIECE, EvalOptions, Hexchess, INITIAL_POSITION, San, _passes_qsearch_delta_prune, create_board, evaluate, execute_command, index, search, stringify_board def build_position(turn: str, pieces: dict[str, str], ep: str = '-') -> Hexchess: @@ -43,6 +43,60 @@ def test_initial_position_depth_one_search(self) -> None: self.assertEqual(result['depth'], 1) self.assertGreaterEqual(result['evaluations'], 51) self.assertIn(result['sans'][0]['san'], {'d3d5', 'h3h5', 'c2c4', 'i2i4', 'b1b3', 'k1k3'}) + metrics = result['metrics'] + self.assertIn('negamaxTtHits', metrics) + self.assertIn('quiescenceTtHits', metrics) + self.assertIn('qsearchDeltaPruneSkips', metrics) + self.assertIn('qsearchStandPatCutoffs', metrics) + self.assertIn('pvsResearches', metrics) + self.assertIn('negamaxFrontierFutilitySkips', metrics) + self.assertIn('nullMoveCutoffs', metrics) + + def test_search_without_diagnostics_omits_extra_metrics(self) -> None: + result = search(Hexchess(INITIAL_POSITION), 1, diagnostics=False) + + metrics = result['metrics'] + self.assertIn('ttHits', metrics) + self.assertIn('ttCutoffs', metrics) + self.assertIn('betaCutoffs', metrics) + self.assertNotIn('negamaxTtHits', metrics) + self.assertNotIn('qsearchDeltaPruneSkips', metrics) + self.assertNotIn('negamaxFrontierFutilitySkips', metrics) + self.assertNotIn('nullMoveCutoffs', metrics) + + def test_execute_command_rejects_invalid_position_history(self) -> None: + with self.assertRaisesRegex(ValueError, 'invalid positionHistory'): + execute_command('hexchess/evaluate', {'position': INITIAL_POSITION, 'depth': 1, 'positionHistory': ['ok', 123]}) + + def test_search_avoids_third_repetition_from_game_history(self) -> None: + position = Hexchess.parse('1/3/1k3/7/1Kr1p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 11 50') + prior_positions = [ + '1/3/1k3/7/2r1p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 4 46', + '1/3/rk3/7/4p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 5 47', + '1/3/rk3/7/1K2p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 6 47', + '1/3/1k3/7/1Kr1p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 7 48', + '1/3/1k3/7/2r1p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 8 48', + '1/3/rk3/7/4p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 9 49', + '1/3/rk3/7/1K2p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 10 49', + ] + + without_history = search(position.clone(), 4, diagnostics=False) + with_history = search(position.clone(), 4, diagnostics=False, position_history=prior_positions) + + self.assertEqual(without_history['sans'][0]['san'], 'c7a6') + self.assertEqual(with_history['sans'][0]['san'], 'c7b6') + self.assertEqual(with_history['sans'][1], {'san': 'c7a6', 'score': 0.0}) + + def test_null_move_restores_position_and_hash(self) -> None: + position = Hexchess(INITIAL_POSITION) + before = position.to_string() + before_hash = position.position_key() + + undo = position.make_null_move() + position.unmake_null_move(undo) + + self.assertEqual(position.to_string(), before) + self.assertEqual(position.position_key(), before_hash) def test_evaluate_prefers_safe_queen(self) -> None: safe = build_position('w', {'f1': 'K', 'f11': 'k', 'g5': 'Q', 'g7': 'p'}) diff --git a/pyrustengine/Cargo.lock b/pyrustengine/Cargo.lock new file mode 100644 index 00000000..08180c47 --- /dev/null +++ b/pyrustengine/Cargo.lock @@ -0,0 +1,342 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "engine_macros" +version = "0.0.1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "hexchess" +version = "2.5.1" +dependencies = [ + "hexchess_macros", + "serde", + "serde_yaml", +] + +[[package]] +name = "hexchess_engine" +version = "0.0.1" +dependencies = [ + "console_error_panic_hook", + "engine_macros", + "hexchess", + "hexchess_macros", + "serde", + "tsify", + "wasm-bindgen", +] + +[[package]] +name = "hexchess_macros" +version = "2.5.1" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "hexchess_pyrustengine" +version = "0.1.0" +dependencies = [ + "hexchess", + "hexchess_engine", + "serde_json", +] + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4c90f45aa2e6eacbe8645f77fdea542ac97a494bcd117a67df9ff4d611f995" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tsify" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec5505497c87f1c050b4392d3f11b49a04537fcb9dc0da57bc0af168a6331f2" +dependencies = [ + "gloo-utils", + "serde", + "serde_json", + "tsify-macros", + "wasm-bindgen", +] + +[[package]] +name = "tsify-macros" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc2c44dc9fe4baf55b88e032621b7a11b215a1f0a7de8d0aa04367207d915bc" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "wasm-bindgen" +version = "0.2.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6523d69017b7633e396a89c5efab138161ed5aafcbc8d3e5c5a42ae38f50495a" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3a6c758eb2f701ed3d052ff5737f5bfe6614326ea7f3bbac7156192dc32e67" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921de2737904886b52bcbb237301552d05969a6f9c40d261eb0533c8b055fedf" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a93e946af942b58934c604527337bad9ae33ba1d5c6900bbb41c2c07c2364a93" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84cde8507f4d7cfcb1185b8cb5890c494ffea65edbe1ba82cfd63661c805ed94" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/pyrustengine/Cargo.toml b/pyrustengine/Cargo.toml new file mode 100644 index 00000000..4d88c94f --- /dev/null +++ b/pyrustengine/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "hexchess_pyrustengine" +version = "0.1.0" +edition = "2021" + +[lib] +name = "hexchess_pyrustengine" +crate-type = ["cdylib"] + +[dependencies] +engine = { package = "hexchess_engine", path = "../engine" } +hexchess = { path = "../rust" } +serde_json = "1.0" diff --git a/pyrustengine/README.md b/pyrustengine/README.md new file mode 100644 index 00000000..c75a4107 --- /dev/null +++ b/pyrustengine/README.md @@ -0,0 +1,79 @@ +# pyrustengine + +`pyrustengine` is a Python FastAPI wrapper around the existing Rust search engine in [engine](../engine). + +It uses a small native Rust FFI bridge in this directory so Python can call the same `hexchess/evaluate` command without going through the browser-only WASM worker. + +## Install + +```powershell +python -m venv .venv +.venv\Scripts\activate +pip install -r pyrustengine/requirements.txt +``` + +Rust and Cargo must also be installed because the wrapper builds the bridge library on first use. + +## Run + +The wrapper defaults to port `8081`. + +Run these commands from the repository root: + +```powershell +python -m pyrustengine +``` + +Equivalent explicit command: + +```powershell +python -m uvicorn pyrustengine.main:app --host 127.0.0.1 --port 8081 +``` + +If your current working directory is already [pyrustengine](g:/work/Training/hexchess/pyrustengine), use the local module form instead: + +```powershell +python -m uvicorn main:app --host 127.0.0.1 --port 8081 +``` + +You can override the bind port with `PYRUSTENGINE_PORT`. + +## API + +### `GET /health` + +Returns: + +```json +{ "status": "ok" } +``` + +### `GET /hexchess/ping` + +Returns the standard engine envelope with a timestamp payload. + +### `POST /execute` + +Request: + +```json +{ + "id": "optional-id", + "command": "hexchess/evaluate", + "options": { + "depth": 2, + "position": "b/qbk/n1b1n/r5r/ppppppppp/11/5P5/4P1P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 1" + } +} +``` + +Supported commands: + +- `hexchess/ping` +- `hexchess/evaluate` + +## Notes + +- The Rust bridge is built from [pyrustengine/Cargo.toml](g:/work/Training/hexchess/pyrustengine/Cargo.toml). +- The bridge will auto-build in release mode if the native library is missing. +- Set `PYRUSTENGINE_LIBRARY` to point at a prebuilt bridge library if you do not want auto-build behavior. diff --git a/pyrustengine/__init__.py b/pyrustengine/__init__.py new file mode 100644 index 00000000..67c8c76f --- /dev/null +++ b/pyrustengine/__init__.py @@ -0,0 +1,5 @@ +from pyrustengine.main import app +from pyrustengine.native_engine import NativeEngineError, execute_command + + +__all__ = ["NativeEngineError", "app", "execute_command"] diff --git a/pyrustengine/__main__.py b/pyrustengine/__main__.py new file mode 100644 index 00000000..23f4236f --- /dev/null +++ b/pyrustengine/__main__.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +import os + +import uvicorn + + +def main() -> None: + host = os.getenv("PYRUSTENGINE_HOST", "127.0.0.1") + port = int(os.getenv("PYRUSTENGINE_PORT", "8081")) + reload_enabled = os.getenv("PYRUSTENGINE_RELOAD", "false").lower() in {"1", "true", "yes", "on"} + + uvicorn.run("pyrustengine.main:app", host=host, port=port, reload=reload_enabled) + + +if __name__ == "__main__": + main() diff --git a/pyrustengine/main.py b/pyrustengine/main.py new file mode 100644 index 00000000..02a015fb --- /dev/null +++ b/pyrustengine/main.py @@ -0,0 +1,94 @@ +from __future__ import annotations + +from typing import Any + +from fastapi import FastAPI, HTTPException +from fastapi.middleware.cors import CORSMiddleware +from pydantic import BaseModel, ConfigDict, Field + +try: + from pyrustengine.native_engine import NativeEngineError, execute_command +except ModuleNotFoundError: + from native_engine import NativeEngineError, execute_command + + +class EngineError(BaseModel): + message: str + + +class ExecuteRequest(BaseModel): + model_config = ConfigDict(extra="allow") + + command: str + options: dict[str, Any] = Field(default_factory=dict) + id: str | None = None + + +class ExecuteResponse(BaseModel): + model_config = ConfigDict(extra="allow") + + command: str + options: dict[str, Any] + response: dict[str, Any] + id: str | None = None + + +class ExecuteFailure(BaseModel): + model_config = ConfigDict(extra="allow") + + id: str | None = None + options: dict[str, Any] = Field(default_factory=dict) + error: EngineError + + +app = FastAPI(title="hexchess pyrustengine", version="0.1.0") + +app.add_middleware( + CORSMiddleware, + allow_origins=[ + "http://localhost:4173", + "http://127.0.0.1:4173", + "http://localhost:4175", + "http://127.0.0.1:4175", + "http://localhost:5173", + "http://127.0.0.1:5173", + ], + allow_credentials=False, + allow_methods=["*"], + allow_headers=["*"], +) + + +@app.get("/health") +async def health() -> dict[str, str]: + return {"status": "ok"} + + +@app.post("/execute", response_model=ExecuteResponse) +async def execute(payload: ExecuteRequest) -> ExecuteResponse: + try: + response = execute_command(payload.command, payload.options) + except NativeEngineError as exc: + error = ExecuteFailure( + id=payload.id, + options=payload.options, + error=EngineError(message=str(exc)), + ) + raise HTTPException(status_code=400, detail=error.model_dump()) from exc + + return ExecuteResponse( + id=payload.id, + command=payload.command, + options=payload.options, + response=response, + ) + + +@app.get("/hexchess/ping") +async def ping() -> ExecuteResponse: + response = execute_command("hexchess/ping", {}) + return ExecuteResponse( + command="hexchess/ping", + options={}, + response=response, + ) diff --git a/pyrustengine/native_engine.py b/pyrustengine/native_engine.py new file mode 100644 index 00000000..c520ddc6 --- /dev/null +++ b/pyrustengine/native_engine.py @@ -0,0 +1,137 @@ +from __future__ import annotations + +import ctypes +import json +import os +import subprocess +import sys +from pathlib import Path +from threading import Lock +from typing import Any + + +class NativeEngineError(ValueError): + pass + + +PACKAGE_DIR = Path(__file__).resolve().parent +REPO_ROOT = PACKAGE_DIR.parent +LIBRARY_ENV_VAR = "PYRUSTENGINE_LIBRARY" +_LIBRARY_LOCK = Lock() +_LIBRARY_HANDLE: ctypes.CDLL | None = None + + +def error(message: str) -> None: + raise NativeEngineError(f"[hexchess error] {message}") + + +def execute_command(command: str, options: dict[str, Any] | None = None) -> dict[str, Any]: + library = _load_library() + command_bytes = command.encode("utf-8") + options_bytes = json.dumps(options or {}, separators=(",", ":")).encode("utf-8") + payload_ptr = library.hexchess_engine_execute(command_bytes, options_bytes) + + if not payload_ptr: + error("rust engine returned an empty response") + + try: + payload_raw = ctypes.string_at(payload_ptr).decode("utf-8") + finally: + library.hexchess_engine_string_free(payload_ptr) + + try: + payload = json.loads(payload_raw) + except json.JSONDecodeError as exc: + error(f"failed to decode rust engine response: {exc}") + + if not payload.get("ok"): + message = payload.get("error", {}).get("message", "unknown engine error") + error(str(message)) + + response = payload.get("response") + if not isinstance(response, dict): + error("rust engine returned an invalid response payload") + + return response + + +def _load_library() -> ctypes.CDLL: + global _LIBRARY_HANDLE + + if _LIBRARY_HANDLE is not None: + return _LIBRARY_HANDLE + + with _LIBRARY_LOCK: + if _LIBRARY_HANDLE is not None: + return _LIBRARY_HANDLE + + library_path = _resolve_library_path() + handle = ctypes.CDLL(str(library_path)) + handle.hexchess_engine_execute.argtypes = [ctypes.c_char_p, ctypes.c_char_p] + handle.hexchess_engine_execute.restype = ctypes.c_void_p + handle.hexchess_engine_string_free.argtypes = [ctypes.c_void_p] + handle.hexchess_engine_string_free.restype = None + _LIBRARY_HANDLE = handle + + return _LIBRARY_HANDLE + + +def _resolve_library_path() -> Path: + override = os.getenv(LIBRARY_ENV_VAR) + if override: + library_path = Path(override).expanduser().resolve() + if not library_path.exists(): + error(f"configured rust engine library does not exist: {library_path}") + return library_path + + candidates = _library_candidates() + for candidate in candidates: + if candidate.exists(): + return candidate + + _build_library() + + for candidate in candidates: + if candidate.exists(): + return candidate + + searched_paths = ", ".join(str(path) for path in candidates) + error(f"rust engine library was not found after build. searched: {searched_paths}") + raise AssertionError("unreachable") + + +def _build_library() -> None: + command = ["cargo", "build", "--release", "--manifest-path", str(PACKAGE_DIR / "Cargo.toml")] + + try: + subprocess.run( + command, + cwd=str(REPO_ROOT), + check=True, + capture_output=True, + text=True, + ) + except FileNotFoundError as exc: + error("cargo is required to build the Rust bridge, but it was not found on PATH") + raise exc + except subprocess.CalledProcessError as exc: + stderr = exc.stderr.strip() + stdout = exc.stdout.strip() + details = stderr or stdout or str(exc) + error(f"failed to build Rust bridge: {details}") + + +def _library_candidates() -> list[Path]: + library_name = _library_filename() + return [ + PACKAGE_DIR / "target" / "release" / library_name, + PACKAGE_DIR / "target" / "debug" / library_name, + ] + + +def _library_filename() -> str: + if sys.platform == "win32": + return "hexchess_pyrustengine.dll" + if sys.platform == "darwin": + return "libhexchess_pyrustengine.dylib" + return "libhexchess_pyrustengine.so" diff --git a/pyrustengine/requirements.txt b/pyrustengine/requirements.txt new file mode 100644 index 00000000..07e9aa13 --- /dev/null +++ b/pyrustengine/requirements.txt @@ -0,0 +1,2 @@ +fastapi==0.116.1 +uvicorn==0.35.0 diff --git a/pyrustengine/src/lib.rs b/pyrustengine/src/lib.rs new file mode 100644 index 00000000..497b82fb --- /dev/null +++ b/pyrustengine/src/lib.rs @@ -0,0 +1,147 @@ +use engine::negamax; +use engine::structs::EvalOptions; +use hexchess::Hexchess; +use serde_json::{json, Value}; +use std::ffi::{c_char, CStr, CString}; +use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::time::{SystemTime, UNIX_EPOCH}; + +#[no_mangle] +pub extern "C" fn hexchess_engine_execute( + command: *const c_char, + options_json: *const c_char, +) -> *mut c_char { + let payload = match catch_unwind(AssertUnwindSafe(|| execute_ffi(command, options_json))) { + Ok(payload) => payload, + Err(_) => json!({ + "ok": false, + "error": { + "message": "Rust engine panicked while handling the command" + } + }), + }; + + json_to_c_string(payload) +} + +#[no_mangle] +pub extern "C" fn hexchess_engine_string_free(value: *mut c_char) { + if value.is_null() { + return; + } + + unsafe { + let _ = CString::from_raw(value); + } +} + +fn execute_ffi(command: *const c_char, options_json: *const c_char) -> Value { + let command = match read_c_string(command) { + Ok(value) => value, + Err(message) => return error_payload(&message), + }; + + let options_json = match read_c_string(options_json) { + Ok(value) => value, + Err(message) => return error_payload(&message), + }; + + match execute_command(&command, &options_json) { + Ok(response) => json!({ + "ok": true, + "response": response, + }), + Err(message) => error_payload(&message), + } +} + +fn execute_command(command: &str, options_json: &str) -> Result { + let options = parse_options(options_json)?; + + match command { + "hexchess/ping" => Ok(json!({ + "now": current_timestamp_millis(), + })), + "hexchess/evaluate" => evaluate(&options), + _ => Err(format!("Unknown engine command: {}", command)), + } +} + +fn evaluate(options: &Value) -> Result { + let position = options + .get("position") + .and_then(Value::as_str) + .ok_or_else(|| "invalid position: expected string".to_string())?; + + let depth = options + .get("depth") + .and_then(Value::as_u64) + .ok_or_else(|| "invalid depth: expected integer".to_string())?; + + if depth > u8::MAX as u64 { + return Err(format!("invalid depth: expected integer <= {}", u8::MAX)); + } + + let hexchess = Hexchess::parse(position).map_err(|message| format!("invalid position: {}", message))?; + let response = negamax::search(&hexchess, depth as u8, &EvalOptions::default()); + + serde_json::to_value(response).map_err(|message| format!("failed to serialize response: {}", message)) +} + +fn parse_options(source: &str) -> Result { + if source.trim().is_empty() { + return Ok(json!({})); + } + + serde_json::from_str::(source).map_err(|message| format!("invalid options json: {}", message)) +} + +fn read_c_string(value: *const c_char) -> Result { + if value.is_null() { + return Ok(String::new()); + } + + let c_str = unsafe { CStr::from_ptr(value) }; + + c_str + .to_str() + .map(|value| value.to_owned()) + .map_err(|_| "input contained invalid UTF-8".to_string()) +} + +fn current_timestamp_millis() -> u128 { + match SystemTime::now().duration_since(UNIX_EPOCH) { + Ok(duration) => duration.as_millis(), + Err(_) => 0, + } +} + +fn error_payload(message: &str) -> Value { + json!({ + "ok": false, + "error": { + "message": message, + } + }) +} + +fn json_to_c_string(payload: Value) -> *mut c_char { + let serialized = match serde_json::to_string(&payload) { + Ok(value) => value, + Err(message) => { + format!( + "{{\"ok\":false,\"error\":{{\"message\":\"failed to serialize bridge payload: {}\"}}}}", + message + ) + } + }; + + match CString::new(serialized) { + Ok(value) => value.into_raw(), + Err(_) => CString::new( + "{\"ok\":false,\"error\":{\"message\":\"bridge payload contained an interior null byte\"}}", + ) + .expect("static fallback CString must be valid") + .into_raw(), + } +} diff --git a/pyrustengine/test_native_engine.py b/pyrustengine/test_native_engine.py new file mode 100644 index 00000000..e988beb6 --- /dev/null +++ b/pyrustengine/test_native_engine.py @@ -0,0 +1,34 @@ +from __future__ import annotations + +import unittest + +from pyrustengine.native_engine import execute_command + + +INITIAL_POSITION = "b/qbk/n1b1n/r5r/ppppppppp/11/5P5/4P1P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 1" + + +class NativeEngineTests(unittest.TestCase): + def test_ping(self) -> None: + response = execute_command("hexchess/ping", {}) + + self.assertIn("now", response) + self.assertIsInstance(response["now"], int) + + def test_evaluate(self) -> None: + response = execute_command( + "hexchess/evaluate", + { + "depth": 1, + "position": INITIAL_POSITION, + }, + ) + + self.assertEqual(response["depth"], 1) + self.assertIn("evaluations", response) + self.assertIn("sans", response) + self.assertIsInstance(response["sans"], list) + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/results/2.1.003/benchmark-candidates-20260329-210806.yaml b/results/2.1.003/benchmark-candidates-20260329-210806.yaml new file mode 100644 index 00000000..3baa34aa --- /dev/null +++ b/results/2.1.003/benchmark-candidates-20260329-210806.yaml @@ -0,0 +1,46 @@ +version: 1 +benchmarks: +- name: harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + category: harvested + fen: b/qbk/n1b1n/r5r/p2ppp2p/3p7/2pPP1PP3/2P5p2/5B5/3Q1B2P2/1PRN1BKNRP1 b h4 0 7 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 14 (b7 k7k5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=486507.1, negamaxNodes=849351, quiescenceNodes=16278157, ttHits=1192920, + movegenCalls=9117488.' +- name: harvested-hexchess-game-20260329-210806-ply-020-qsearch-heavy + category: harvested + fen: b/qbk/n1b1n/r6/p2ppp1r1/11/2p1P1PP1p1/2P5p2/4BB3P1/3Q4P2/1PRN1BKNR2 b k2 0 + 10 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 20 (b10 f11k3). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=74173.1, + negamaxNodes=611349, quiescenceNodes=2680684, ttHits=283244, movegenCalls=1546842.' +- name: harvested-hexchess-game-20260329-210806-ply-058-wide-root + category: harvested + fen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r5p2/Q8p1/3R4P2/3N2BKN2 b - 5 29 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 58 (b29 i4i3). + tags: wide-root. wallMs=34068.7, negamaxNodes=519873, quiescenceNodes=888734, + ttHits=160009, movegenCalls=604623.' +- name: harvested-hexchess-game-20260329-210806-ply-042-node-heavy + category: harvested + fen: 1/q1k/1rb1n/7/3ppp1r1/3b7/2Q3PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 b - 7 21 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 42 (b21 e9c7). + tags: node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. wallMs=68709.9, + negamaxNodes=699350, quiescenceNodes=2098881, ttHits=404581, movegenCalls=1147819.' +- name: harvested-hexchess-game-20260329-210806-ply-028-low-throughput + category: harvested + fen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p3PP1p1/2P3Qnp2/4BB3N1/8P2/1PRN1BK1R2 b - 3 14 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 28 (b14 h4i1). + tags: low-throughput. wallMs=44083.7, negamaxNodes=651597, quiescenceNodes=891456, + ttHits=198530, movegenCalls=608259.' +- name: harvested-hexchess-game-20260329-210806-ply-008-slow-search + category: harvested + fen: b/qbk/n1b1n/r5r/pppppp2p/11/4P1P1p2/2P8/3P1B1P3/5B2P2/1PRNQBKNRP1 b c3 0 4 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 8 (b4 c7c5). + tags: slow-search, movegen-heavy, pruning-heavy. wallMs=75414.7, negamaxNodes=635323, + quiescenceNodes=1851437, ttHits=246345, movegenCalls=1097512.' +- name: harvested-hexchess-game-20260329-210806-ply-034-interesting + category: harvested + fen: 1/qbk/2b1n/r6/3ppp1r1/11/2B3PP1p1/1pP3Q1p2/5B5/3R4P2/1P1N1BK1N2 b - 0 17 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 34 (b17 b4c4). + tags: interesting. wallMs=42174.5, negamaxNodes=469413, quiescenceNodes=1555830, + ttHits=211732, movegenCalls=890113.' diff --git a/results/2.1.003/clean-search-comparison-20260329.yaml b/results/2.1.003/clean-search-comparison-20260329.yaml new file mode 100644 index 00000000..4430bdef --- /dev/null +++ b/results/2.1.003/clean-search-comparison-20260329.yaml @@ -0,0 +1,307 @@ +version: 1 +kind: pyengine2-benchmark-suite +suite: clean-search-comparison +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-29T19:20:00.469738+00:00' +topCount: 3 +diagnostics: false +entries: +- mode: search + filter: tt-transposition-midgame + repeat: 3 + cases: + - name: tt-transposition-midgame + category: middlegame + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + summaries: + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 648.3517 + units: 20556 + unitsLabel: evals + unitsPerMs: 31.705014 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 4 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 646.7438999970909 + evalsPerMs: 31.783832827943893 + rootMoves: 57 + negamaxNodes: 20418 + quiescenceNodes: 21658 + movegenCalls: 14885 + tacticalMovegenCalls: 8950 + legalContextCalls: 14885 + ttHits: 4359 + ttCutoffs: 3757 + betaCutoffs: 6931 + ttEntries: 22877 + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 3014.2384 + units: 72364 + unitsLabel: evals + unitsPerMs: 24.007391 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 5 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 2988.2944999844767 + evalsPerMs: 24.215819424884632 + rootMoves: 57 + negamaxNodes: 111740 + quiescenceNodes: 75990 + movegenCalls: 67232 + tacticalMovegenCalls: 34044 + legalContextCalls: 67232 + ttHits: 35385 + ttCutoffs: 34329 + betaCutoffs: 29593 + ttEntries: 81459 + depths: + - 4 + - 5 +- mode: search + filter: capture-storm-qsearch + repeat: 3 + cases: + - name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summaries: + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 224.3165 + units: 7900 + unitsLabel: evals + unitsPerMs: 35.218096 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 4 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5c8 + score: -19.200000000000003 + metrics: + wallMs: 223.60710002249107 + evalsPerMs: 35.329826285504325 + rootMoves: 36 + negamaxNodes: 15028 + quiescenceNodes: 8267 + movegenCalls: 5493 + tacticalMovegenCalls: 2146 + legalContextCalls: 5493 + ttHits: 6371 + ttCutoffs: 5691 + betaCutoffs: 2284 + ttEntries: 8932 + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 553.3968 + units: 13862 + unitsLabel: evals + unitsPerMs: 25.048934 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 5 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5g4 + score: -19.599999999999994 + metrics: + wallMs: 547.7562000160106 + evalsPerMs: 25.30687922764694 + rootMoves: 36 + negamaxNodes: 36986 + quiescenceNodes: 13972 + movegenCalls: 13876 + tacticalMovegenCalls: 5362 + legalContextCalls: 13876 + ttHits: 19171 + ttCutoffs: 17367 + betaCutoffs: 5127 + ttEntries: 14560 + depths: + - 4 + - 5 +- mode: search + filter: initial-position + repeat: 3 + cases: + - name: initial-position + category: opening + notes: High-branching opening baseline. + summaries: + - name: initial-position + category: opening + mode: search + medianMs: 3404.4299 + units: 134821 + unitsLabel: evals + unitsPerMs: 39.601638 + notes: High-branching opening baseline. + depth: 4 + topMoves: + - san: d3d5 + score: -0.0 + - san: h3h5 + score: -0.0 + - san: c2c4 + score: -0.0 + metrics: + wallMs: 3409.156699985033 + evalsPerMs: 39.54673013434434 + rootMoves: 51 + negamaxNodes: 155774 + quiescenceNodes: 136519 + movegenCalls: 40073 + tacticalMovegenCalls: 28246 + legalContextCalls: 40073 + ttHits: 35137 + ttCutoffs: 33924 + betaCutoffs: 18648 + ttEntries: 136337 + - name: initial-position + category: opening + mode: search + medianMs: 28348.3074 + units: 665456 + unitsLabel: evals + unitsPerMs: 23.474276 + notes: High-branching opening baseline. + depth: 5 + topMoves: + - san: d3d5 + score: -0.32000000000000006 + - san: h3h5 + score: -0.32000000000000006 + - san: c2c4 + score: -0.32000000000000006 + metrics: + wallMs: 23385.510800027987 + evalsPerMs: 28.455910400691508 + rootMoves: 51 + negamaxNodes: 391552 + quiescenceNodes: 691299 + movegenCalls: 467305 + tacticalMovegenCalls: 390386 + legalContextCalls: 467305 + ttHits: 121118 + ttCutoffs: 114008 + betaCutoffs: 231272 + ttEntries: 669829 + depths: + - 4 + - 5 +- mode: search + filter: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + repeat: 3 + cases: + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 1368.8656 + units: 45842 + unitsLabel: evals + unitsPerMs: 33.489044 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 + b7b5). tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 3 + topMoves: + - san: b7b5 + score: -2.0 + - san: c7c5 + score: -2.0 + - san: d6e8 + score: -1.6799999999999997 + metrics: + wallMs: 1365.2832999941893 + evalsPerMs: 33.57691403695856 + rootMoves: 51 + negamaxNodes: 12374 + quiescenceNodes: 47719 + movegenCalls: 31951 + tacticalMovegenCalls: 29453 + legalContextCalls: 31951 + ttHits: 4808 + ttCutoffs: 4022 + betaCutoffs: 15414 + ttEntries: 42315 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + repeat: 1 + cases: + - name: harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 14 (b7 k7k5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=486507.1, negamaxNodes=849351, quiescenceNodes=16278157, ttHits=1192920, + movegenCalls=9117488.' + summaries: + - name: harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + category: harvested + mode: search + medianMs: 5817.7373 + units: 216221 + unitsLabel: evals + unitsPerMs: 37.165824 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 14 (b7 + k7k5). tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, + pruning-heavy. wallMs=486507.1, negamaxNodes=849351, quiescenceNodes=16278157, + ttHits=1192920, movegenCalls=9117488.' + depth: 3 + topMoves: + - san: b7b5 + score: -0.32000000000000006 + - san: k7k5 + score: -0.32000000000000006 + - san: i4i3 + score: -0.32000000000000006 + metrics: + wallMs: 5806.272899993928 + evalsPerMs: 37.23920727188454 + rootMoves: 50 + negamaxNodes: 14550 + quiescenceNodes: 224231 + movegenCalls: 131857 + tacticalMovegenCalls: 128564 + legalContextCalls: 131857 + ttHits: 10010 + ttCutoffs: 9494 + betaCutoffs: 65049 + ttEntries: 212607 + depths: + - 3 diff --git a/results/2.1.003/game-analysis-20260329-210806-merged.yaml b/results/2.1.003/game-analysis-20260329-210806-merged.yaml new file mode 100644 index 00000000..7ed20ee2 --- /dev/null +++ b/results/2.1.003/game-analysis-20260329-210806-merged.yaml @@ -0,0 +1,878 @@ +version: 1 +pyengine2Version: 2.1.003 +files: +- results\2.1.003\hexchess-game-20260329-210806.yaml +gameCount: 1 +totalLoggedPlies: 62 +enginePliesWithMetrics: 31 +metricSummary: + wall_ms: + mean: 65855.59786128861 + median: 37854.75950001273 + max: 486507.08119999035 + evals_per_ms: + mean: 27.25919545558675 + median: 27.513398121723398 + max: 37.61874118927237 + negamax_nodes: + mean: 503377.6451612903 + median: 496813.0 + max: 849351.0 + quiescence_nodes: + mean: 2049160.7096774194 + median: 1157234.0 + max: 16278157.0 + tt_hits: + mean: 250783.25806451612 + median: 201885.0 + max: 1192920.0 + beta_cutoffs: + mean: 584856.6129032258 + median: 318582.0 + max: 4603402.0 + movegen_calls: + mean: 1171622.064516129 + median: 644139.0 + max: 9117488.0 + qsearch_ratio: + mean: 3.40891548193761 + median: 2.342169478001634 + max: 19.16540629256927 +topWallMs: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + turn: b + fullmove: 7 + san: k7k5 + value: 486507.08119999035 + wallMs: 486507.08119999035 + dominantTag: tt-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 12 + turn: b + fullmove: 6 + san: i5i4 + value: 229094.97569999075 + wallMs: 229094.97569999075 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 22 + turn: b + fullmove: 11 + san: d9f8 + value: 146405.48369998578 + wallMs: 146405.48369998578 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + - wide-root +- game: hexchess-game-20260329-210806.yaml + ply: 18 + turn: b + fullmove: 9 + san: d6c5 + value: 100281.9545000093 + wallMs: 100281.9545000093 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 6 + turn: b + fullmove: 3 + san: i7i5 + value: 78291.50449999725 + wallMs: 78291.50449999725 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - tt-heavy + - low-throughput +- game: hexchess-game-20260329-210806.yaml + ply: 8 + turn: b + fullmove: 4 + san: c7c5 + value: 75414.74940002081 + wallMs: 75414.74940002081 + dominantTag: slow-search + tags: + - slow-search + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 20 + turn: b + fullmove: 10 + san: f11k3 + value: 74173.11819997849 + wallMs: 74173.11819997849 + dominantTag: qsearch-heavy + tags: + - slow-search + - qsearch-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 42 + turn: b + fullmove: 21 + san: e9c7 + value: 68709.92409999599 + wallMs: 68709.92409999599 + dominantTag: node-heavy + tags: + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +topNegamaxNodes: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + turn: b + fullmove: 7 + san: k7k5 + value: 849351 + wallMs: 486507.08119999035 + dominantTag: tt-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 22 + turn: b + fullmove: 11 + san: d9f8 + value: 819506 + wallMs: 146405.48369998578 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + - wide-root +- game: hexchess-game-20260329-210806.yaml + ply: 18 + turn: b + fullmove: 9 + san: d6c5 + value: 764493 + wallMs: 100281.9545000093 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 42 + turn: b + fullmove: 21 + san: e9c7 + value: 699350 + wallMs: 68709.92409999599 + dominantTag: node-heavy + tags: + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 24 + turn: b + fullmove: 12 + san: f8e5 + value: 694621 + wallMs: 44633.99619999109 + dominantTag: node-heavy + tags: + - node-heavy + - tt-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 12 + turn: b + fullmove: 6 + san: i5i4 + value: 664003 + wallMs: 229094.97569999075 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 6 + turn: b + fullmove: 3 + san: i7i5 + value: 657672 + wallMs: 78291.50449999725 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - tt-heavy + - low-throughput +- game: hexchess-game-20260329-210806.yaml + ply: 28 + turn: b + fullmove: 14 + san: h4i1 + value: 651597 + wallMs: 44083.698600006755 + dominantTag: low-throughput + tags: + - low-throughput +topQuiescenceNodes: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + turn: b + fullmove: 7 + san: k7k5 + value: 16278157 + wallMs: 486507.08119999035 + dominantTag: tt-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 12 + turn: b + fullmove: 6 + san: i5i4 + value: 7358271 + wallMs: 229094.97569999075 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 22 + turn: b + fullmove: 11 + san: d9f8 + value: 5824151 + wallMs: 146405.48369998578 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + - wide-root +- game: hexchess-game-20260329-210806.yaml + ply: 18 + turn: b + fullmove: 9 + san: d6c5 + value: 3495614 + wallMs: 100281.9545000093 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 20 + turn: b + fullmove: 10 + san: f11k3 + value: 2680684 + wallMs: 74173.11819997849 + dominantTag: qsearch-heavy + tags: + - slow-search + - qsearch-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 42 + turn: b + fullmove: 21 + san: e9c7 + value: 2098881 + wallMs: 68709.92409999599 + dominantTag: node-heavy + tags: + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 10 + turn: b + fullmove: 5 + san: d7d6 + value: 1881492 + wallMs: 68475.12570000254 + dominantTag: qsearch-heavy + tags: + - qsearch-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 8 + turn: b + fullmove: 4 + san: c7c5 + value: 1851437 + wallMs: 75414.74940002081 + dominantTag: slow-search + tags: + - slow-search + - movegen-heavy + - pruning-heavy +topTtHits: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + turn: b + fullmove: 7 + san: k7k5 + value: 1192920 + wallMs: 486507.08119999035 + dominantTag: tt-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 12 + turn: b + fullmove: 6 + san: i5i4 + value: 602219 + wallMs: 229094.97569999075 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 18 + turn: b + fullmove: 9 + san: d6c5 + value: 512721 + wallMs: 100281.9545000093 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 22 + turn: b + fullmove: 11 + san: d9f8 + value: 497227 + wallMs: 146405.48369998578 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + - wide-root +- game: hexchess-game-20260329-210806.yaml + ply: 42 + turn: b + fullmove: 21 + san: e9c7 + value: 404581 + wallMs: 68709.92409999599 + dominantTag: node-heavy + tags: + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 24 + turn: b + fullmove: 12 + san: f8e5 + value: 294915 + wallMs: 44633.99619999109 + dominantTag: node-heavy + tags: + - node-heavy + - tt-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 6 + turn: b + fullmove: 3 + san: i7i5 + value: 292647 + wallMs: 78291.50449999725 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - tt-heavy + - low-throughput +- game: hexchess-game-20260329-210806.yaml + ply: 20 + turn: b + fullmove: 10 + san: f11k3 + value: 283244 + wallMs: 74173.11819997849 + dominantTag: qsearch-heavy + tags: + - slow-search + - qsearch-heavy + - movegen-heavy + - pruning-heavy +topQsearchRatio: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + turn: b + fullmove: 7 + san: k7k5 + value: 19.16540629256927 + wallMs: 486507.08119999035 + dominantTag: tt-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 12 + turn: b + fullmove: 6 + san: i5i4 + value: 11.081683365888408 + wallMs: 229094.97569999075 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 22 + turn: b + fullmove: 11 + san: d9f8 + value: 7.106904647433942 + wallMs: 146405.48369998578 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + - wide-root +- game: hexchess-game-20260329-210806.yaml + ply: 18 + turn: b + fullmove: 9 + san: d6c5 + value: 4.5724604411027965 + wallMs: 100281.9545000093 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 20 + turn: b + fullmove: 10 + san: f11k3 + value: 4.384866909081392 + wallMs: 74173.11819997849 + dominantTag: qsearch-heavy + tags: + - slow-search + - qsearch-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 10 + turn: b + fullmove: 5 + san: d7d6 + value: 3.7637442763438216 + wallMs: 68475.12570000254 + dominantTag: qsearch-heavy + tags: + - qsearch-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 32 + turn: b + fullmove: 16 + san: b5b4 + value: 3.427041441883276 + wallMs: 54108.1903000013 + dominantTag: qsearch-heavy + tags: + - qsearch-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 34 + turn: b + fullmove: 17 + san: b4c4 + value: 3.3144160898824704 + wallMs: 42174.51010001241 + dominantTag: interesting + tags: [] +benchmarkCandidates: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + san: k7k5 + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + dominantTag: tt-heavy + interestingness: 7.7 + fen: b/qbk/n1b1n/r5r/p2ppp2p/3p7/2pPP1PP3/2P5p2/5B5/3Q1B2P2/1PRN1BKNRP1 b h4 0 7 + metrics: + wallMs: 486507.08119999035 + evalsPerMs: 31.55929398217422 + rootMoves: 50 + negamaxNodes: 849351 + quiescenceNodes: 16278157 + movegenCalls: 9117488 + tacticalMovegenCalls: 8947572 + legalContextCalls: 9117488 + ttHits: 1192920 + ttCutoffs: 1101633 + betaCutoffs: 4603402 + ttEntries: 14963939 + duration: 487418.3000000119 + evaluations: 15353820 + qsearchRatio: 19.16540629256927 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + category: harvested + fen: b/qbk/n1b1n/r5r/p2ppp2p/3p7/2pPP1PP3/2P5p2/5B5/3Q1B2P2/1PRN1BKNRP1 b h4 0 + 7 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 14 (b7 k7k5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=486507.1, negamaxNodes=849351, quiescenceNodes=16278157, ttHits=1192920, + movegenCalls=9117488.' +- game: hexchess-game-20260329-210806.yaml + ply: 20 + san: f11k3 + tags: + - slow-search + - qsearch-heavy + - movegen-heavy + - pruning-heavy + dominantTag: qsearch-heavy + interestingness: 2.031414924843304 + fen: b/qbk/n1b1n/r6/p2ppp1r1/11/2p1P1PP1p1/2P5p2/4BB3P1/3Q4P2/1PRN1BKNR2 b k2 0 + 10 + metrics: + wallMs: 74173.11819997849 + evalsPerMs: 34.25789641402371 + rootMoves: 53 + negamaxNodes: 611349 + quiescenceNodes: 2680684 + movegenCalls: 1546842 + tacticalMovegenCalls: 1360045 + legalContextCalls: 1546842 + ttHits: 283244 + ttCutoffs: 254559 + betaCutoffs: 763509 + ttEntries: 2602044 + duration: 74334.59999999404 + evaluations: 2541015 + qsearchRatio: 4.384866909081392 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-020-qsearch-heavy + category: harvested + fen: b/qbk/n1b1n/r6/p2ppp1r1/11/2p1P1PP1p1/2P5p2/4BB3P1/3Q4P2/1PRN1BKNR2 b k2 + 0 10 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 20 (b10 f11k3). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=74173.1, + negamaxNodes=611349, quiescenceNodes=2680684, ttHits=283244, movegenCalls=1546842.' +- game: hexchess-game-20260329-210806.yaml + ply: 58 + san: i4i3 + tags: + - wide-root + dominantTag: wide-root + interestingness: 1.2362035652219001 + fen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r5p2/Q8p1/3R4P2/3N2BKN2 b - 5 29 + metrics: + wallMs: 34068.70049997815 + evalsPerMs: 24.82677611963927 + rootMoves: 61 + negamaxNodes: 519873 + quiescenceNodes: 888734 + movegenCalls: 604623 + tacticalMovegenCalls: 446798 + legalContextCalls: 604623 + ttHits: 160009 + ttCutoffs: 136991 + betaCutoffs: 293494 + ttEntries: 919743 + duration: 34153.09999999404 + evaluations: 845816 + qsearchRatio: 1.709521363871561 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-058-wide-root + category: harvested + fen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r5p2/Q8p1/3R4P2/3N2BKN2 b - 5 29 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 58 (b29 i4i3). + tags: wide-root. wallMs=34068.7, negamaxNodes=519873, quiescenceNodes=888734, + ttHits=160009, movegenCalls=604623.' +- game: hexchess-game-20260329-210806.yaml + ply: 42 + san: e9c7 + tags: + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + dominantTag: node-heavy + interestingness: 2.0556949857644633 + fen: 1/q1k/1rb1n/7/3ppp1r1/3b7/2Q3PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 b - 7 21 + metrics: + wallMs: 68709.92409999599 + evalsPerMs: 27.720507989909294 + rootMoves: 55 + negamaxNodes: 699350 + quiescenceNodes: 2098881 + movegenCalls: 1147819 + tacticalMovegenCalls: 979591 + legalContextCalls: 1147819 + ttHits: 404581 + ttCutoffs: 347935 + betaCutoffs: 570874 + ttEntries: 1964435 + duration: 68849.59999999404 + evaluations: 1904674 + qsearchRatio: 3.001188246228641 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-042-node-heavy + category: harvested + fen: 1/q1k/1rb1n/7/3ppp1r1/3b7/2Q3PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 b - 7 21 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 42 (b21 e9c7). + tags: node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. wallMs=68709.9, + negamaxNodes=699350, quiescenceNodes=2098881, ttHits=404581, movegenCalls=1147819.' +- game: hexchess-game-20260329-210806.yaml + ply: 28 + san: h4i1 + tags: + - low-throughput + dominantTag: low-throughput + interestingness: 1.4799563103412858 + fen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p3PP1p1/2P3Qnp2/4BB3N1/8P2/1PRN1BK1R2 b - 3 14 + metrics: + wallMs: 44083.698600006755 + evalsPerMs: 19.349601487382216 + rootMoves: 58 + negamaxNodes: 651597 + quiescenceNodes: 891456 + movegenCalls: 608259 + tacticalMovegenCalls: 424305 + legalContextCalls: 608259 + ttHits: 198530 + ttCutoffs: 176878 + betaCutoffs: 300086 + ttEntries: 988998 + duration: 44166.09999999404 + evaluations: 853002 + qsearchRatio: 1.3681094296014253 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-028-low-throughput + category: harvested + fen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p3PP1p1/2P3Qnp2/4BB3N1/8P2/1PRN1BK1R2 b - 3 14 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 28 (b14 h4i1). + tags: low-throughput. wallMs=44083.7, negamaxNodes=651597, quiescenceNodes=891456, + ttHits=198530, movegenCalls=608259.' +- game: hexchess-game-20260329-210806.yaml + ply: 8 + san: c7c5 + tags: + - slow-search + - movegen-heavy + - pruning-heavy + dominantTag: slow-search + interestingness: 1.842608745478134 + fen: b/qbk/n1b1n/r5r/pppppp2p/11/4P1P1p2/2P8/3P1B1P3/5B2P2/1PRNQBKNRP1 b c3 0 4 + metrics: + wallMs: 75414.74940002081 + evalsPerMs: 23.322002844174598 + rootMoves: 49 + negamaxNodes: 635323 + quiescenceNodes: 1851437 + movegenCalls: 1097512 + tacticalMovegenCalls: 958204 + legalContextCalls: 1097512 + ttHits: 246345 + ttCutoffs: 223432 + betaCutoffs: 544864 + ttEntries: 1794642 + duration: 75556.0 + evaluations: 1758823 + qsearchRatio: 2.914166494838059 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-008-slow-search + category: harvested + fen: b/qbk/n1b1n/r5r/pppppp2p/11/4P1P1p2/2P8/3P1B1P3/5B2P2/1PRNQBKNRP1 b c3 0 + 4 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 8 (b4 c7c5). + tags: slow-search, movegen-heavy, pruning-heavy. wallMs=75414.7, negamaxNodes=635323, + quiescenceNodes=1851437, ttHits=246345, movegenCalls=1097512.' +- game: hexchess-game-20260329-210806.yaml + ply: 34 + san: b4c4 + tags: [] + dominantTag: interesting + interestingness: 1.4039647449459296 + fen: 1/qbk/2b1n/r6/3ppp1r1/11/2B3PP1p1/1pP3Q1p2/5B5/3R4P2/1P1N1BK1N2 b - 0 17 + metrics: + wallMs: 42174.51010001241 + evalsPerMs: 34.22965664750129 + rootMoves: 49 + negamaxNodes: 469413 + quiescenceNodes: 1555830 + movegenCalls: 890113 + tacticalMovegenCalls: 742221 + legalContextCalls: 890113 + ttHits: 211732 + ttCutoffs: 188989 + betaCutoffs: 440169 + ttEntries: 1511329 + duration: 42272.19999998808 + evaluations: 1443619 + qsearchRatio: 3.3144160898824704 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-034-interesting + category: harvested + fen: 1/qbk/2b1n/r6/3ppp1r1/11/2B3PP1p1/1pP3Q1p2/5B5/3R4P2/1P1N1BK1N2 b - 0 17 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 34 (b17 b4c4). + tags: interesting. wallMs=42174.5, negamaxNodes=469413, quiescenceNodes=1555830, + ttHits=211732, movegenCalls=890113.' +mergeSummary: + path: pyengine2\benchmark\benchmarks.yaml + added: + - name: harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + category: harvested + fen: b/qbk/n1b1n/r5r/p2ppp2p/3p7/2pPP1PP3/2P5p2/5B5/3Q1B2P2/1PRN1BKNRP1 b h4 0 + 7 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 14 (b7 k7k5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=486507.1, negamaxNodes=849351, quiescenceNodes=16278157, ttHits=1192920, + movegenCalls=9117488.' + - name: harvested-hexchess-game-20260329-210806-ply-020-qsearch-heavy + category: harvested + fen: b/qbk/n1b1n/r6/p2ppp1r1/11/2p1P1PP1p1/2P5p2/4BB3P1/3Q4P2/1PRN1BKNR2 b k2 + 0 10 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 20 (b10 f11k3). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=74173.1, + negamaxNodes=611349, quiescenceNodes=2680684, ttHits=283244, movegenCalls=1546842.' + - name: harvested-hexchess-game-20260329-210806-ply-058-wide-root + category: harvested + fen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r5p2/Q8p1/3R4P2/3N2BKN2 b - 5 29 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 58 (b29 i4i3). + tags: wide-root. wallMs=34068.7, negamaxNodes=519873, quiescenceNodes=888734, + ttHits=160009, movegenCalls=604623.' + - name: harvested-hexchess-game-20260329-210806-ply-042-node-heavy + category: harvested + fen: 1/q1k/1rb1n/7/3ppp1r1/3b7/2Q3PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 b - 7 21 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 42 (b21 e9c7). + tags: node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. wallMs=68709.9, + negamaxNodes=699350, quiescenceNodes=2098881, ttHits=404581, movegenCalls=1147819.' + - name: harvested-hexchess-game-20260329-210806-ply-028-low-throughput + category: harvested + fen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p3PP1p1/2P3Qnp2/4BB3N1/8P2/1PRN1BK1R2 b - 3 14 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 28 (b14 h4i1). + tags: low-throughput. wallMs=44083.7, negamaxNodes=651597, quiescenceNodes=891456, + ttHits=198530, movegenCalls=608259.' + - name: harvested-hexchess-game-20260329-210806-ply-008-slow-search + category: harvested + fen: b/qbk/n1b1n/r5r/pppppp2p/11/4P1P1p2/2P8/3P1B1P3/5B2P2/1PRNQBKNRP1 b c3 0 + 4 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 8 (b4 c7c5). + tags: slow-search, movegen-heavy, pruning-heavy. wallMs=75414.7, negamaxNodes=635323, + quiescenceNodes=1851437, ttHits=246345, movegenCalls=1097512.' + - name: harvested-hexchess-game-20260329-210806-ply-034-interesting + category: harvested + fen: 1/qbk/2b1n/r6/3ppp1r1/11/2B3PP1p1/1pP3Q1p2/5B5/3R4P2/1P1N1BK1N2 b - 0 17 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 34 (b17 b4c4). + tags: interesting. wallMs=42174.5, negamaxNodes=469413, quiescenceNodes=1555830, + ttHits=211732, movegenCalls=890113.' + skipped: [] diff --git a/results/2.1.003/game-analysis-20260329-210806.yaml b/results/2.1.003/game-analysis-20260329-210806.yaml new file mode 100644 index 00000000..e14ce404 --- /dev/null +++ b/results/2.1.003/game-analysis-20260329-210806.yaml @@ -0,0 +1,829 @@ +version: 1 +pyengine2Version: 2.1.003 +files: +- results\2.1.003\hexchess-game-20260329-210806.yaml +gameCount: 1 +totalLoggedPlies: 62 +enginePliesWithMetrics: 31 +metricSummary: + wall_ms: + mean: 65855.59786128861 + median: 37854.75950001273 + max: 486507.08119999035 + evals_per_ms: + mean: 27.25919545558675 + median: 27.513398121723398 + max: 37.61874118927237 + negamax_nodes: + mean: 503377.6451612903 + median: 496813.0 + max: 849351.0 + quiescence_nodes: + mean: 2049160.7096774194 + median: 1157234.0 + max: 16278157.0 + tt_hits: + mean: 250783.25806451612 + median: 201885.0 + max: 1192920.0 + beta_cutoffs: + mean: 584856.6129032258 + median: 318582.0 + max: 4603402.0 + movegen_calls: + mean: 1171622.064516129 + median: 644139.0 + max: 9117488.0 + qsearch_ratio: + mean: 3.40891548193761 + median: 2.342169478001634 + max: 19.16540629256927 +topWallMs: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + turn: b + fullmove: 7 + san: k7k5 + value: 486507.08119999035 + wallMs: 486507.08119999035 + dominantTag: tt-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 12 + turn: b + fullmove: 6 + san: i5i4 + value: 229094.97569999075 + wallMs: 229094.97569999075 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 22 + turn: b + fullmove: 11 + san: d9f8 + value: 146405.48369998578 + wallMs: 146405.48369998578 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + - wide-root +- game: hexchess-game-20260329-210806.yaml + ply: 18 + turn: b + fullmove: 9 + san: d6c5 + value: 100281.9545000093 + wallMs: 100281.9545000093 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 6 + turn: b + fullmove: 3 + san: i7i5 + value: 78291.50449999725 + wallMs: 78291.50449999725 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - tt-heavy + - low-throughput +- game: hexchess-game-20260329-210806.yaml + ply: 8 + turn: b + fullmove: 4 + san: c7c5 + value: 75414.74940002081 + wallMs: 75414.74940002081 + dominantTag: slow-search + tags: + - slow-search + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 20 + turn: b + fullmove: 10 + san: f11k3 + value: 74173.11819997849 + wallMs: 74173.11819997849 + dominantTag: qsearch-heavy + tags: + - slow-search + - qsearch-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 42 + turn: b + fullmove: 21 + san: e9c7 + value: 68709.92409999599 + wallMs: 68709.92409999599 + dominantTag: node-heavy + tags: + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +topNegamaxNodes: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + turn: b + fullmove: 7 + san: k7k5 + value: 849351 + wallMs: 486507.08119999035 + dominantTag: tt-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 22 + turn: b + fullmove: 11 + san: d9f8 + value: 819506 + wallMs: 146405.48369998578 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + - wide-root +- game: hexchess-game-20260329-210806.yaml + ply: 18 + turn: b + fullmove: 9 + san: d6c5 + value: 764493 + wallMs: 100281.9545000093 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 42 + turn: b + fullmove: 21 + san: e9c7 + value: 699350 + wallMs: 68709.92409999599 + dominantTag: node-heavy + tags: + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 24 + turn: b + fullmove: 12 + san: f8e5 + value: 694621 + wallMs: 44633.99619999109 + dominantTag: node-heavy + tags: + - node-heavy + - tt-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 12 + turn: b + fullmove: 6 + san: i5i4 + value: 664003 + wallMs: 229094.97569999075 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 6 + turn: b + fullmove: 3 + san: i7i5 + value: 657672 + wallMs: 78291.50449999725 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - tt-heavy + - low-throughput +- game: hexchess-game-20260329-210806.yaml + ply: 28 + turn: b + fullmove: 14 + san: h4i1 + value: 651597 + wallMs: 44083.698600006755 + dominantTag: low-throughput + tags: + - low-throughput +topQuiescenceNodes: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + turn: b + fullmove: 7 + san: k7k5 + value: 16278157 + wallMs: 486507.08119999035 + dominantTag: tt-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 12 + turn: b + fullmove: 6 + san: i5i4 + value: 7358271 + wallMs: 229094.97569999075 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 22 + turn: b + fullmove: 11 + san: d9f8 + value: 5824151 + wallMs: 146405.48369998578 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + - wide-root +- game: hexchess-game-20260329-210806.yaml + ply: 18 + turn: b + fullmove: 9 + san: d6c5 + value: 3495614 + wallMs: 100281.9545000093 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 20 + turn: b + fullmove: 10 + san: f11k3 + value: 2680684 + wallMs: 74173.11819997849 + dominantTag: qsearch-heavy + tags: + - slow-search + - qsearch-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 42 + turn: b + fullmove: 21 + san: e9c7 + value: 2098881 + wallMs: 68709.92409999599 + dominantTag: node-heavy + tags: + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 10 + turn: b + fullmove: 5 + san: d7d6 + value: 1881492 + wallMs: 68475.12570000254 + dominantTag: qsearch-heavy + tags: + - qsearch-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 8 + turn: b + fullmove: 4 + san: c7c5 + value: 1851437 + wallMs: 75414.74940002081 + dominantTag: slow-search + tags: + - slow-search + - movegen-heavy + - pruning-heavy +topTtHits: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + turn: b + fullmove: 7 + san: k7k5 + value: 1192920 + wallMs: 486507.08119999035 + dominantTag: tt-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 12 + turn: b + fullmove: 6 + san: i5i4 + value: 602219 + wallMs: 229094.97569999075 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 18 + turn: b + fullmove: 9 + san: d6c5 + value: 512721 + wallMs: 100281.9545000093 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 22 + turn: b + fullmove: 11 + san: d9f8 + value: 497227 + wallMs: 146405.48369998578 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + - wide-root +- game: hexchess-game-20260329-210806.yaml + ply: 42 + turn: b + fullmove: 21 + san: e9c7 + value: 404581 + wallMs: 68709.92409999599 + dominantTag: node-heavy + tags: + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 24 + turn: b + fullmove: 12 + san: f8e5 + value: 294915 + wallMs: 44633.99619999109 + dominantTag: node-heavy + tags: + - node-heavy + - tt-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 6 + turn: b + fullmove: 3 + san: i7i5 + value: 292647 + wallMs: 78291.50449999725 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - tt-heavy + - low-throughput +- game: hexchess-game-20260329-210806.yaml + ply: 20 + turn: b + fullmove: 10 + san: f11k3 + value: 283244 + wallMs: 74173.11819997849 + dominantTag: qsearch-heavy + tags: + - slow-search + - qsearch-heavy + - movegen-heavy + - pruning-heavy +topQsearchRatio: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + turn: b + fullmove: 7 + san: k7k5 + value: 19.16540629256927 + wallMs: 486507.08119999035 + dominantTag: tt-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 12 + turn: b + fullmove: 6 + san: i5i4 + value: 11.081683365888408 + wallMs: 229094.97569999075 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 22 + turn: b + fullmove: 11 + san: d9f8 + value: 7.106904647433942 + wallMs: 146405.48369998578 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + - wide-root +- game: hexchess-game-20260329-210806.yaml + ply: 18 + turn: b + fullmove: 9 + san: d6c5 + value: 4.5724604411027965 + wallMs: 100281.9545000093 + dominantTag: node-heavy + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 20 + turn: b + fullmove: 10 + san: f11k3 + value: 4.384866909081392 + wallMs: 74173.11819997849 + dominantTag: qsearch-heavy + tags: + - slow-search + - qsearch-heavy + - movegen-heavy + - pruning-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 10 + turn: b + fullmove: 5 + san: d7d6 + value: 3.7637442763438216 + wallMs: 68475.12570000254 + dominantTag: qsearch-heavy + tags: + - qsearch-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 32 + turn: b + fullmove: 16 + san: b5b4 + value: 3.427041441883276 + wallMs: 54108.1903000013 + dominantTag: qsearch-heavy + tags: + - qsearch-heavy +- game: hexchess-game-20260329-210806.yaml + ply: 34 + turn: b + fullmove: 17 + san: b4c4 + value: 3.3144160898824704 + wallMs: 42174.51010001241 + dominantTag: interesting + tags: [] +benchmarkCandidates: +- game: hexchess-game-20260329-210806.yaml + ply: 14 + san: k7k5 + tags: + - slow-search + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + dominantTag: tt-heavy + interestingness: 7.7 + fen: b/qbk/n1b1n/r5r/p2ppp2p/3p7/2pPP1PP3/2P5p2/5B5/3Q1B2P2/1PRN1BKNRP1 b h4 0 7 + metrics: + wallMs: 486507.08119999035 + evalsPerMs: 31.55929398217422 + rootMoves: 50 + negamaxNodes: 849351 + quiescenceNodes: 16278157 + movegenCalls: 9117488 + tacticalMovegenCalls: 8947572 + legalContextCalls: 9117488 + ttHits: 1192920 + ttCutoffs: 1101633 + betaCutoffs: 4603402 + ttEntries: 14963939 + duration: 487418.3000000119 + evaluations: 15353820 + qsearchRatio: 19.16540629256927 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + category: harvested + fen: b/qbk/n1b1n/r5r/p2ppp2p/3p7/2pPP1PP3/2P5p2/5B5/3Q1B2P2/1PRN1BKNRP1 b h4 0 + 7 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 14 (b7 k7k5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=486507.1, negamaxNodes=849351, quiescenceNodes=16278157, ttHits=1192920, + movegenCalls=9117488.' +- game: hexchess-game-20260329-210806.yaml + ply: 20 + san: f11k3 + tags: + - slow-search + - qsearch-heavy + - movegen-heavy + - pruning-heavy + dominantTag: qsearch-heavy + interestingness: 2.031414924843304 + fen: b/qbk/n1b1n/r6/p2ppp1r1/11/2p1P1PP1p1/2P5p2/4BB3P1/3Q4P2/1PRN1BKNR2 b k2 0 + 10 + metrics: + wallMs: 74173.11819997849 + evalsPerMs: 34.25789641402371 + rootMoves: 53 + negamaxNodes: 611349 + quiescenceNodes: 2680684 + movegenCalls: 1546842 + tacticalMovegenCalls: 1360045 + legalContextCalls: 1546842 + ttHits: 283244 + ttCutoffs: 254559 + betaCutoffs: 763509 + ttEntries: 2602044 + duration: 74334.59999999404 + evaluations: 2541015 + qsearchRatio: 4.384866909081392 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-020-qsearch-heavy + category: harvested + fen: b/qbk/n1b1n/r6/p2ppp1r1/11/2p1P1PP1p1/2P5p2/4BB3P1/3Q4P2/1PRN1BKNR2 b k2 + 0 10 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 20 (b10 f11k3). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=74173.1, + negamaxNodes=611349, quiescenceNodes=2680684, ttHits=283244, movegenCalls=1546842.' +- game: hexchess-game-20260329-210806.yaml + ply: 58 + san: i4i3 + tags: + - wide-root + dominantTag: wide-root + interestingness: 1.2362035652219001 + fen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r5p2/Q8p1/3R4P2/3N2BKN2 b - 5 29 + metrics: + wallMs: 34068.70049997815 + evalsPerMs: 24.82677611963927 + rootMoves: 61 + negamaxNodes: 519873 + quiescenceNodes: 888734 + movegenCalls: 604623 + tacticalMovegenCalls: 446798 + legalContextCalls: 604623 + ttHits: 160009 + ttCutoffs: 136991 + betaCutoffs: 293494 + ttEntries: 919743 + duration: 34153.09999999404 + evaluations: 845816 + qsearchRatio: 1.709521363871561 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-058-wide-root + category: harvested + fen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r5p2/Q8p1/3R4P2/3N2BKN2 b - 5 29 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 58 (b29 i4i3). + tags: wide-root. wallMs=34068.7, negamaxNodes=519873, quiescenceNodes=888734, + ttHits=160009, movegenCalls=604623.' +- game: hexchess-game-20260329-210806.yaml + ply: 42 + san: e9c7 + tags: + - node-heavy + - qsearch-heavy + - tt-heavy + - movegen-heavy + - pruning-heavy + dominantTag: node-heavy + interestingness: 2.0556949857644633 + fen: 1/q1k/1rb1n/7/3ppp1r1/3b7/2Q3PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 b - 7 21 + metrics: + wallMs: 68709.92409999599 + evalsPerMs: 27.720507989909294 + rootMoves: 55 + negamaxNodes: 699350 + quiescenceNodes: 2098881 + movegenCalls: 1147819 + tacticalMovegenCalls: 979591 + legalContextCalls: 1147819 + ttHits: 404581 + ttCutoffs: 347935 + betaCutoffs: 570874 + ttEntries: 1964435 + duration: 68849.59999999404 + evaluations: 1904674 + qsearchRatio: 3.001188246228641 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-042-node-heavy + category: harvested + fen: 1/q1k/1rb1n/7/3ppp1r1/3b7/2Q3PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 b - 7 21 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 42 (b21 e9c7). + tags: node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. wallMs=68709.9, + negamaxNodes=699350, quiescenceNodes=2098881, ttHits=404581, movegenCalls=1147819.' +- game: hexchess-game-20260329-210806.yaml + ply: 28 + san: h4i1 + tags: + - low-throughput + dominantTag: low-throughput + interestingness: 1.4799563103412858 + fen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p3PP1p1/2P3Qnp2/4BB3N1/8P2/1PRN1BK1R2 b - 3 14 + metrics: + wallMs: 44083.698600006755 + evalsPerMs: 19.349601487382216 + rootMoves: 58 + negamaxNodes: 651597 + quiescenceNodes: 891456 + movegenCalls: 608259 + tacticalMovegenCalls: 424305 + legalContextCalls: 608259 + ttHits: 198530 + ttCutoffs: 176878 + betaCutoffs: 300086 + ttEntries: 988998 + duration: 44166.09999999404 + evaluations: 853002 + qsearchRatio: 1.3681094296014253 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-028-low-throughput + category: harvested + fen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p3PP1p1/2P3Qnp2/4BB3N1/8P2/1PRN1BK1R2 b - 3 14 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 28 (b14 h4i1). + tags: low-throughput. wallMs=44083.7, negamaxNodes=651597, quiescenceNodes=891456, + ttHits=198530, movegenCalls=608259.' +- game: hexchess-game-20260329-210806.yaml + ply: 8 + san: c7c5 + tags: + - slow-search + - movegen-heavy + - pruning-heavy + dominantTag: slow-search + interestingness: 1.842608745478134 + fen: b/qbk/n1b1n/r5r/pppppp2p/11/4P1P1p2/2P8/3P1B1P3/5B2P2/1PRNQBKNRP1 b c3 0 4 + metrics: + wallMs: 75414.74940002081 + evalsPerMs: 23.322002844174598 + rootMoves: 49 + negamaxNodes: 635323 + quiescenceNodes: 1851437 + movegenCalls: 1097512 + tacticalMovegenCalls: 958204 + legalContextCalls: 1097512 + ttHits: 246345 + ttCutoffs: 223432 + betaCutoffs: 544864 + ttEntries: 1794642 + duration: 75556.0 + evaluations: 1758823 + qsearchRatio: 2.914166494838059 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-008-slow-search + category: harvested + fen: b/qbk/n1b1n/r5r/pppppp2p/11/4P1P1p2/2P8/3P1B1P3/5B2P2/1PRNQBKNRP1 b c3 0 + 4 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 8 (b4 c7c5). + tags: slow-search, movegen-heavy, pruning-heavy. wallMs=75414.7, negamaxNodes=635323, + quiescenceNodes=1851437, ttHits=246345, movegenCalls=1097512.' +- game: hexchess-game-20260329-210806.yaml + ply: 34 + san: b4c4 + tags: [] + dominantTag: interesting + interestingness: 1.4039647449459296 + fen: 1/qbk/2b1n/r6/3ppp1r1/11/2B3PP1p1/1pP3Q1p2/5B5/3R4P2/1P1N1BK1N2 b - 0 17 + metrics: + wallMs: 42174.51010001241 + evalsPerMs: 34.22965664750129 + rootMoves: 49 + negamaxNodes: 469413 + quiescenceNodes: 1555830 + movegenCalls: 890113 + tacticalMovegenCalls: 742221 + legalContextCalls: 890113 + ttHits: 211732 + ttCutoffs: 188989 + betaCutoffs: 440169 + ttEntries: 1511329 + duration: 42272.19999998808 + evaluations: 1443619 + qsearchRatio: 3.3144160898824704 + benchmark: + name: harvested-hexchess-game-20260329-210806-ply-034-interesting + category: harvested + fen: 1/qbk/2b1n/r6/3ppp1r1/11/2B3PP1p1/1pP3Q1p2/5B5/3R4P2/1P1N1BK1N2 b - 0 17 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 34 (b17 b4c4). + tags: interesting. wallMs=42174.5, negamaxNodes=469413, quiescenceNodes=1555830, + ttHits=211732, movegenCalls=890113.' +mergeSummary: null diff --git a/results/2.1.003/harvested-diagnostics-20260329.yaml b/results/2.1.003/harvested-diagnostics-20260329.yaml new file mode 100644 index 00000000..1b237c9d --- /dev/null +++ b/results/2.1.003/harvested-diagnostics-20260329.yaml @@ -0,0 +1,307 @@ +version: 1 +kind: pyengine2-benchmark-suite +suite: harvested-diagnostics +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-29T19:14:45.954104+00:00' +topCount: 3 +diagnostics: true +entries: +- mode: search + filter: harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + repeat: 1 + cases: + - name: harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 14 (b7 k7k5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=486507.1, negamaxNodes=849351, quiescenceNodes=16278157, ttHits=1192920, + movegenCalls=9117488.' + summaries: + - name: harvested-hexchess-game-20260329-210806-ply-014-tt-heavy + category: harvested + mode: search + medianMs: 5989.9364 + units: 216221 + unitsLabel: evals + unitsPerMs: 36.097378 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 14 (b7 + k7k5). tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, + pruning-heavy. wallMs=486507.1, negamaxNodes=849351, quiescenceNodes=16278157, + ttHits=1192920, movegenCalls=9117488.' + depth: 3 + topMoves: + - san: b7b5 + score: -0.32000000000000006 + - san: k7k5 + score: -0.32000000000000006 + - san: i4i3 + score: -0.32000000000000006 + metrics: + wallMs: 5980.9916999947745 + evalsPerMs: 36.15136265783297 + rootMoves: 50 + negamaxNodes: 14550 + quiescenceNodes: 224231 + movegenCalls: 131857 + tacticalMovegenCalls: 128564 + legalContextCalls: 131857 + ttHits: 10010 + ttCutoffs: 9494 + betaCutoffs: 65049 + ttEntries: 212607 + negamaxTtHits: 1652 + quiescenceTtHits: 8358 + negamaxTtCutoffs: 1484 + quiescenceTtCutoffs: 8010 + negamaxBetaCutoffs: 3114 + quiescenceBetaCutoffs: 61935 + qsearchStandPatCutoffs: 87657 + qsearchDeltaPruneChecks: 68577 + qsearchDeltaPruneSkips: 67969 + qsearchNodesWithMoves: 122041 + qsearchGeneratedMoves: 476058 + pvsResearches: 166 + negamaxFrontierFutilityChecks: 7071 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260329-210806-ply-020-qsearch-heavy + repeat: 1 + cases: + - name: harvested-hexchess-game-20260329-210806-ply-020-qsearch-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 20 (b10 f11k3). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=74173.1, + negamaxNodes=611349, quiescenceNodes=2680684, ttHits=283244, movegenCalls=1546842.' + summaries: + - name: harvested-hexchess-game-20260329-210806-ply-020-qsearch-heavy + category: harvested + mode: search + medianMs: 1613.3069 + units: 55227 + unitsLabel: evals + unitsPerMs: 34.232172 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 20 (b10 + f11k3). tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=74173.1, + negamaxNodes=611349, quiescenceNodes=2680684, ttHits=283244, movegenCalls=1546842.' + depth: 3 + topMoves: + - san: f11k3 + score: -10.480000000000004 + - san: i4k3 + score: -0.8000000000000002 + - san: c8d8 + score: -0.8000000000000002 + metrics: + wallMs: 1610.0366000027861 + evalsPerMs: 34.30170469410722 + rootMoves: 53 + negamaxNodes: 13221 + quiescenceNodes: 57909 + movegenCalls: 32183 + tacticalMovegenCalls: 27939 + legalContextCalls: 32183 + ttHits: 5261 + ttCutoffs: 4082 + betaCutoffs: 15800 + ttEntries: 57134 + negamaxTtHits: 1736 + quiescenceTtHits: 3525 + negamaxTtCutoffs: 1400 + quiescenceTtCutoffs: 2682 + negamaxBetaCutoffs: 3780 + quiescenceBetaCutoffs: 12020 + qsearchStandPatCutoffs: 27288 + qsearchDeltaPruneChecks: 14879 + qsearchDeltaPruneSkips: 14673 + qsearchNodesWithMoves: 26750 + qsearchGeneratedMoves: 108199 + pvsResearches: 165 + negamaxFrontierFutilityChecks: 7956 + negamaxFrontierFutilitySkips: 3583 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260329-210806-ply-058-wide-root + repeat: 1 + cases: + - name: harvested-hexchess-game-20260329-210806-ply-058-wide-root + category: harvested + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 58 (b29 i4i3). + tags: wide-root. wallMs=34068.7, negamaxNodes=519873, quiescenceNodes=888734, + ttHits=160009, movegenCalls=604623.' + summaries: + - name: harvested-hexchess-game-20260329-210806-ply-058-wide-root + category: harvested + mode: search + medianMs: 1279.2621 + units: 43138 + unitsLabel: evals + unitsPerMs: 33.721002 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 58 (b29 + i4i3). tags: wide-root. wallMs=34068.7, negamaxNodes=519873, quiescenceNodes=888734, + ttHits=160009, movegenCalls=604623.' + depth: 3 + topMoves: + - san: i4i3 + score: -12.160000000000004 + - san: e7e5 + score: -11.920000000000002 + - san: e7e6 + score: -11.68 + metrics: + wallMs: 1276.587300002575 + evalsPerMs: 33.79165686507534 + rootMoves: 61 + negamaxNodes: 19370 + quiescenceNodes: 44728 + movegenCalls: 30795 + tacticalMovegenCalls: 25201 + legalContextCalls: 30795 + ttHits: 6587 + ttCutoffs: 5899 + betaCutoffs: 14485 + ttEntries: 44256 + negamaxTtHits: 4598 + quiescenceTtHits: 1989 + negamaxTtCutoffs: 4307 + quiescenceTtCutoffs: 1592 + negamaxBetaCutoffs: 3906 + quiescenceBetaCutoffs: 10579 + qsearchStandPatCutoffs: 17935 + qsearchDeltaPruneChecks: 9647 + qsearchDeltaPruneSkips: 9347 + qsearchNodesWithMoves: 22598 + qsearchGeneratedMoves: 60415 + pvsResearches: 258 + negamaxFrontierFutilityChecks: 10930 + negamaxFrontierFutilitySkips: 1299 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260329-210806-ply-042-node-heavy + repeat: 1 + cases: + - name: harvested-hexchess-game-20260329-210806-ply-042-node-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 42 (b21 e9c7). + tags: node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. wallMs=68709.9, + negamaxNodes=699350, quiescenceNodes=2098881, ttHits=404581, movegenCalls=1147819.' + summaries: + - name: harvested-hexchess-game-20260329-210806-ply-042-node-heavy + category: harvested + mode: search + medianMs: 1940.4387 + units: 70485 + unitsLabel: evals + unitsPerMs: 36.32426 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 42 (b21 + e9c7). tags: node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=68709.9, negamaxNodes=699350, quiescenceNodes=2098881, ttHits=404581, + movegenCalls=1147819.' + depth: 3 + topMoves: + - san: e9c7 + score: -11.36 + - san: e10f10 + score: -11.04 + - san: i4i3 + score: -1.2800000000000011 + metrics: + wallMs: 1935.8198999834713 + evalsPerMs: 36.410928516956474 + rootMoves: 55 + negamaxNodes: 19749 + quiescenceNodes: 74102 + movegenCalls: 40282 + tacticalMovegenCalls: 35524 + legalContextCalls: 40282 + ttHits: 10238 + ttCutoffs: 8369 + betaCutoffs: 19704 + ttEntries: 71138 + negamaxTtHits: 5544 + quiescenceTtHits: 4694 + negamaxTtCutoffs: 4752 + quiescenceTtCutoffs: 3617 + negamaxBetaCutoffs: 4125 + quiescenceBetaCutoffs: 15579 + qsearchStandPatCutoffs: 34961 + qsearchDeltaPruneChecks: 20926 + qsearchDeltaPruneSkips: 20068 + qsearchNodesWithMoves: 32895 + qsearchGeneratedMoves: 114523 + pvsResearches: 247 + negamaxFrontierFutilityChecks: 11726 + negamaxFrontierFutilitySkips: 1324 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260329-210806-ply-028-low-throughput + repeat: 1 + cases: + - name: harvested-hexchess-game-20260329-210806-ply-028-low-throughput + category: harvested + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 28 (b14 h4i1). + tags: low-throughput. wallMs=44083.7, negamaxNodes=651597, quiescenceNodes=891456, + ttHits=198530, movegenCalls=608259.' + summaries: + - name: harvested-hexchess-game-20260329-210806-ply-028-low-throughput + category: harvested + mode: search + medianMs: 1248.0406 + units: 46614 + unitsLabel: evals + unitsPerMs: 37.349746 + notes: 'Harvested from hexchess-game-20260329-210806.yaml before ply 28 (b14 + h4i1). tags: low-throughput. wallMs=44083.7, negamaxNodes=651597, quiescenceNodes=891456, + ttHits=198530, movegenCalls=608259.' + depth: 3 + topMoves: + - san: h4i1 + score: -10.96 + - san: b7b5 + score: -10.24 + - san: e7e5 + score: -10.24 + metrics: + wallMs: 1244.9820000038017 + evalsPerMs: 37.44150517827379 + rootMoves: 58 + negamaxNodes: 14879 + quiescenceNodes: 48740 + movegenCalls: 21631 + tacticalMovegenCalls: 17392 + legalContextCalls: 21631 + ttHits: 4853 + ttCutoffs: 3893 + betaCutoffs: 10325 + ttEntries: 49232 + negamaxTtHits: 2121 + quiescenceTtHits: 2732 + negamaxTtCutoffs: 1767 + quiescenceTtCutoffs: 2126 + negamaxBetaCutoffs: 3793 + quiescenceBetaCutoffs: 6532 + qsearchStandPatCutoffs: 29222 + qsearchDeltaPruneChecks: 11802 + qsearchDeltaPruneSkips: 11181 + qsearchNodesWithMoves: 16634 + qsearchGeneratedMoves: 75023 + pvsResearches: 147 + negamaxFrontierFutilityChecks: 9209 + negamaxFrontierFutilitySkips: 3383 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 diff --git a/results/2.1.003/harvested-history-diagnostics-20260329.yaml b/results/2.1.003/harvested-history-diagnostics-20260329.yaml new file mode 100644 index 00000000..5dac6571 --- /dev/null +++ b/results/2.1.003/harvested-history-diagnostics-20260329.yaml @@ -0,0 +1,554 @@ +version: 1 +kind: pyengine2-benchmark-suite +suite: harvested-history-diagnostics +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-29T19:17:55.747771+00:00' +topCount: 3 +diagnostics: true +entries: +- mode: search + filter: harvested-hexchess-game-20260324-175232-ply-018-tt-heavy + repeat: 1 + cases: + - name: harvested-hexchess-game-20260324-175232-ply-018-tt-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 18 (b9 h8g8). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy, + wide-root. wallMs=189338.8, negamaxNodes=1111688, quiescenceNodes=6124234, ttHits=827664, + movegenCalls=3423357.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-018-tt-heavy + category: harvested + mode: search + medianMs: 2267.9112 + units: 73916 + unitsLabel: evals + unitsPerMs: 32.592105 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 18 (b9 + h8g8). tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, + pruning-heavy, wide-root. wallMs=189338.8, negamaxNodes=1111688, quiescenceNodes=6124234, + ttHits=827664, movegenCalls=3423357.' + depth: 3 + topMoves: + - san: h8f8 + score: 8.719999999999999 + - san: h8g8 + score: 8.719999999999999 + - san: h8i8 + score: 8.719999999999999 + metrics: + wallMs: 2264.770599984331 + evalsPerMs: 32.63730110259794 + rootMoves: 58 + negamaxNodes: 15369 + quiescenceNodes: 77132 + movegenCalls: 42452 + tacticalMovegenCalls: 38028 + legalContextCalls: 42452 + ttHits: 6252 + ttCutoffs: 5393 + betaCutoffs: 20837 + ttEntries: 74089 + negamaxTtHits: 2490 + quiescenceTtHits: 3762 + negamaxTtCutoffs: 2177 + quiescenceTtCutoffs: 3216 + negamaxBetaCutoffs: 4136 + quiescenceBetaCutoffs: 16701 + qsearchStandPatCutoffs: 35888 + qsearchDeltaPruneChecks: 10517 + qsearchDeltaPruneSkips: 9689 + qsearchNodesWithMoves: 34470 + qsearchGeneratedMoves: 117297 + pvsResearches: 129 + negamaxFrontierFutilityChecks: 6532 + negamaxFrontierFutilitySkips: 46 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + repeat: 1 + cases: + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 1373.1687 + units: 45842 + unitsLabel: evals + unitsPerMs: 33.384099 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 + b7b5). tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 3 + topMoves: + - san: b7b5 + score: -2.0 + - san: c7c5 + score: -2.0 + - san: d6e8 + score: -1.6799999999999997 + metrics: + wallMs: 1369.4289000122808 + evalsPerMs: 33.47526841268568 + rootMoves: 51 + negamaxNodes: 12374 + quiescenceNodes: 47719 + movegenCalls: 31951 + tacticalMovegenCalls: 29453 + legalContextCalls: 31951 + ttHits: 4808 + ttCutoffs: 4022 + betaCutoffs: 15414 + ttEntries: 42315 + negamaxTtHits: 2405 + quiescenceTtHits: 2403 + negamaxTtCutoffs: 2145 + quiescenceTtCutoffs: 1877 + negamaxBetaCutoffs: 2296 + quiescenceBetaCutoffs: 13118 + qsearchStandPatCutoffs: 16389 + qsearchDeltaPruneChecks: 596 + qsearchDeltaPruneSkips: 535 + qsearchNodesWithMoves: 23997 + qsearchGeneratedMoves: 67578 + pvsResearches: 152 + negamaxFrontierFutilityChecks: 6845 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260324-175232-ply-024-wide-root + repeat: 1 + cases: + - name: harvested-hexchess-game-20260324-175232-ply-024-wide-root + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 24 (b12 e10l5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy, + wide-root. wallMs=80946.8, negamaxNodes=923651, quiescenceNodes=2007940, ttHits=527660, + movegenCalls=1448831.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-024-wide-root + category: harvested + mode: search + medianMs: 1112.9597 + units: 31271 + unitsLabel: evals + unitsPerMs: 28.097154 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 24 (b12 + e10l5). tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, + pruning-heavy, wide-root. wallMs=80946.8, negamaxNodes=923651, quiescenceNodes=2007940, + ttHits=527660, movegenCalls=1448831.' + depth: 3 + topMoves: + - san: e10l5 + score: -1.6799999999999997 + - san: g8k5 + score: -1.5199999999999996 + - san: d9f8 + score: -1.4400000000000013 + metrics: + wallMs: 1110.8675000141375 + evalsPerMs: 28.15007190290654 + rootMoves: 59 + negamaxNodes: 13979 + quiescenceNodes: 33105 + movegenCalls: 19932 + tacticalMovegenCalls: 15977 + legalContextCalls: 19932 + ttHits: 4175 + ttCutoffs: 3377 + betaCutoffs: 9536 + ttEntries: 32163 + negamaxTtHits: 1946 + quiescenceTtHits: 2229 + negamaxTtCutoffs: 1543 + quiescenceTtCutoffs: 1834 + negamaxBetaCutoffs: 3577 + quiescenceBetaCutoffs: 5959 + qsearchStandPatCutoffs: 15294 + qsearchDeltaPruneChecks: 5104 + qsearchDeltaPruneSkips: 4817 + qsearchNodesWithMoves: 13488 + qsearchGeneratedMoves: 42305 + pvsResearches: 203 + negamaxFrontierFutilityChecks: 11220 + negamaxFrontierFutilitySkips: 5148 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260324-175232-ply-004-node-heavy + repeat: 1 + cases: + - name: harvested-hexchess-game-20260324-175232-ply-004-node-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 4 (b2 h7h5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=132733.5, negamaxNodes=1122032, quiescenceNodes=3740444, ttHits=795469, + movegenCalls=2284733.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-004-node-heavy + category: harvested + mode: search + medianMs: 1332.8942 + units: 39971 + unitsLabel: evals + unitsPerMs: 29.988127 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 4 (b2 h7h5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=132733.5, negamaxNodes=1122032, quiescenceNodes=3740444, ttHits=795469, + movegenCalls=2284733.' + depth: 3 + topMoves: + - san: b7b5 + score: -0.32000000000000006 + - san: k7k5 + score: -0.32000000000000006 + - san: f11e9 + score: -0.32000000000000006 + metrics: + wallMs: 1330.237499991199 + evalsPerMs: 30.048017741391632 + rootMoves: 47 + negamaxNodes: 18018 + quiescenceNodes: 42450 + movegenCalls: 24984 + tacticalMovegenCalls: 20675 + legalContextCalls: 24984 + ttHits: 6199 + ttCutoffs: 5593 + betaCutoffs: 12256 + ttEntries: 41041 + negamaxTtHits: 3412 + quiescenceTtHits: 2787 + negamaxTtCutoffs: 3114 + quiescenceTtCutoffs: 2479 + negamaxBetaCutoffs: 3950 + quiescenceBetaCutoffs: 8306 + qsearchStandPatCutoffs: 19296 + qsearchDeltaPruneChecks: 6198 + qsearchDeltaPruneSkips: 5594 + qsearchNodesWithMoves: 17910 + qsearchGeneratedMoves: 54840 + pvsResearches: 209 + negamaxFrontierFutilityChecks: 9930 + negamaxFrontierFutilitySkips: 558 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260324-175232-ply-074-low-throughput + repeat: 1 + cases: + - name: harvested-hexchess-game-20260324-175232-ply-074-low-throughput + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 74 (b37 b2b1q). + tags: low-throughput. wallMs=21115.0, negamaxNodes=355012, quiescenceNodes=443761, + ttHits=172651, movegenCalls=437826.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-074-low-throughput + category: harvested + mode: search + medianMs: 404.2329 + units: 12989 + unitsLabel: evals + unitsPerMs: 32.132466 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 74 (b37 + b2b1q). tags: low-throughput. wallMs=21115.0, negamaxNodes=355012, quiescenceNodes=443761, + ttHits=172651, movegenCalls=437826.' + depth: 3 + topMoves: + - san: b2b1q + score: -81.6 + - san: b2b1r + score: -81.6 + - san: f8d5 + score: -70.08 + metrics: + wallMs: 403.0827999813482 + evalsPerMs: 32.224148489097125 + rootMoves: 44 + negamaxNodes: 8931 + quiescenceNodes: 13897 + movegenCalls: 10005 + tacticalMovegenCalls: 7470 + legalContextCalls: 10005 + ttHits: 3742 + ttCutoffs: 3003 + betaCutoffs: 4663 + ttEntries: 13327 + negamaxTtHits: 2380 + quiescenceTtHits: 1362 + negamaxTtCutoffs: 2094 + quiescenceTtCutoffs: 909 + negamaxBetaCutoffs: 1892 + quiescenceBetaCutoffs: 2771 + qsearchStandPatCutoffs: 5518 + qsearchDeltaPruneChecks: 411 + qsearchDeltaPruneSkips: 317 + qsearchNodesWithMoves: 6238 + qsearchGeneratedMoves: 16628 + pvsResearches: 120 + negamaxFrontierFutilityChecks: 4394 + negamaxFrontierFutilitySkips: 369 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260324-175232-ply-010-node-heavy + repeat: 1 + cases: + - name: harvested-hexchess-game-20260324-175232-ply-010-node-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 10 (b5 k7k5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=97689.2, negamaxNodes=921501, quiescenceNodes=2646313, ttHits=548905, + movegenCalls=1773051.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-010-node-heavy + category: harvested + mode: search + medianMs: 1220.3042 + units: 35731 + unitsLabel: evals + unitsPerMs: 29.280404 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 10 (b5 + k7k5). tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, + pruning-heavy. wallMs=97689.2, negamaxNodes=921501, quiescenceNodes=2646313, + ttHits=548905, movegenCalls=1773051.' + depth: 3 + topMoves: + - san: b7b5 + score: -0.96 + - san: k7k5 + score: -0.96 + - san: i5i4 + score: -0.96 + metrics: + wallMs: 1217.8810000186786 + evalsPerMs: 29.33866280814956 + rootMoves: 53 + negamaxNodes: 23308 + quiescenceNodes: 37094 + movegenCalls: 22429 + tacticalMovegenCalls: 18681 + legalContextCalls: 22429 + ttHits: 8683 + ttCutoffs: 7834 + betaCutoffs: 10666 + ttEntries: 35573 + negamaxTtHits: 6858 + quiescenceTtHits: 1825 + negamaxTtCutoffs: 6471 + quiescenceTtCutoffs: 1363 + negamaxBetaCutoffs: 3265 + quiescenceBetaCutoffs: 7401 + qsearchStandPatCutoffs: 17050 + qsearchDeltaPruneChecks: 4418 + qsearchDeltaPruneSkips: 4255 + qsearchNodesWithMoves: 15459 + qsearchGeneratedMoves: 43888 + pvsResearches: 260 + negamaxFrontierFutilityChecks: 15762 + negamaxFrontierFutilitySkips: 204 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260326-173542-ply-032-tt-heavy + repeat: 1 + cases: + - name: harvested-hexchess-game-20260326-173542-ply-032-tt-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260326-173542.yaml before ply 32 (b16 i4k3). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=100537.7, negamaxNodes=1314268, quiescenceNodes=2290113, ttHits=610384, + movegenCalls=1959062.' + summaries: + - name: harvested-hexchess-game-20260326-173542-ply-032-tt-heavy + category: harvested + mode: search + medianMs: 2450.5713 + units: 84736 + unitsLabel: evals + unitsPerMs: 34.578059 + notes: 'Harvested from hexchess-game-20260326-173542.yaml before ply 32 (b16 + i4k3). tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, + pruning-heavy. wallMs=100537.7, negamaxNodes=1314268, quiescenceNodes=2290113, + ttHits=610384, movegenCalls=1959062.' + depth: 3 + topMoves: + - san: h8i6 + score: -32.96 + - san: i4k3 + score: -32.4 + - san: c5c4 + score: -30.72 + metrics: + wallMs: 2445.8290000038687 + evalsPerMs: 34.645103970827876 + rootMoves: 60 + negamaxNodes: 32353 + quiescenceNodes: 89080 + movegenCalls: 54911 + tacticalMovegenCalls: 49351 + legalContextCalls: 54911 + ttHits: 15034 + ttCutoffs: 12360 + betaCutoffs: 26144 + ttEntries: 83095 + negamaxTtHits: 8934 + quiescenceTtHits: 6100 + negamaxTtCutoffs: 8016 + quiescenceTtCutoffs: 4344 + negamaxBetaCutoffs: 3866 + quiescenceBetaCutoffs: 22278 + qsearchStandPatCutoffs: 35385 + qsearchDeltaPruneChecks: 13633 + qsearchDeltaPruneSkips: 13356 + qsearchNodesWithMoves: 45261 + qsearchGeneratedMoves: 134146 + pvsResearches: 516 + negamaxFrontierFutilityChecks: 23585 + negamaxFrontierFutilitySkips: 4019 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260326-173542-ply-012-qsearch-heavy + repeat: 1 + cases: + - name: harvested-hexchess-game-20260326-173542-ply-012-qsearch-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260326-173542.yaml before ply 12 (b6 f8e5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy. + wallMs=106783.5, negamaxNodes=845527, quiescenceNodes=2326002, ttHits=364240, + movegenCalls=1969314.' + summaries: + - name: harvested-hexchess-game-20260326-173542-ply-012-qsearch-heavy + category: harvested + mode: search + medianMs: 1510.108 + units: 45196 + unitsLabel: evals + unitsPerMs: 29.928985 + notes: 'Harvested from hexchess-game-20260326-173542.yaml before ply 12 (b6 + f8e5). tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, + pruning-heavy. wallMs=106783.5, negamaxNodes=845527, quiescenceNodes=2326002, + ttHits=364240, movegenCalls=1969314.' + depth: 3 + topMoves: + - san: f8e5 + score: -9.84 + - san: f8g5 + score: -9.76 + - san: k7k5 + score: -0.15999999999999992 + metrics: + wallMs: 1506.7657000035979 + evalsPerMs: 29.99537353411488 + rootMoves: 55 + negamaxNodes: 26136 + quiescenceNodes: 46450 + movegenCalls: 29344 + tacticalMovegenCalls: 25250 + legalContextCalls: 29344 + ttHits: 8503 + ttCutoffs: 7311 + betaCutoffs: 14072 + ttEntries: 44600 + negamaxTtHits: 6584 + quiescenceTtHits: 1919 + negamaxTtCutoffs: 6057 + quiescenceTtCutoffs: 1254 + negamaxBetaCutoffs: 3522 + quiescenceBetaCutoffs: 10550 + qsearchStandPatCutoffs: 19946 + qsearchDeltaPruneChecks: 3135 + qsearchDeltaPruneSkips: 2910 + qsearchNodesWithMoves: 21479 + qsearchGeneratedMoves: 55782 + pvsResearches: 387 + negamaxFrontierFutilityChecks: 14503 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 +- mode: search + filter: harvested-hexchess-game-20260326-173542-ply-048-wide-root + repeat: 1 + cases: + - name: harvested-hexchess-game-20260326-173542-ply-048-wide-root + category: harvested + notes: 'Harvested from hexchess-game-20260326-173542.yaml before ply 48 (b24 h7f5). + tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, pruning-heavy, + wide-root. wallMs=80029.6, negamaxNodes=1155468, quiescenceNodes=1692986, ttHits=438005, + movegenCalls=1501474.' + summaries: + - name: harvested-hexchess-game-20260326-173542-ply-048-wide-root + category: harvested + mode: search + medianMs: 2017.0716 + units: 70664 + unitsLabel: evals + unitsPerMs: 35.032966 + notes: 'Harvested from hexchess-game-20260326-173542.yaml before ply 48 (b24 + h7f5). tags: slow-search, node-heavy, qsearch-heavy, tt-heavy, movegen-heavy, + pruning-heavy, wide-root. wallMs=80029.6, negamaxNodes=1155468, quiescenceNodes=1692986, + ttHits=438005, movegenCalls=1501474.' + depth: 3 + topMoves: + - san: h7f5 + score: -62.800000000000004 + - san: c8f8 + score: -51.28 + - san: i7i5 + score: -42.800000000000004 + metrics: + wallMs: 2012.7600000123493 + evalsPerMs: 35.108010890303085 + rootMoves: 85 + negamaxNodes: 26530 + quiescenceNodes: 73280 + movegenCalls: 37015 + tacticalMovegenCalls: 30846 + legalContextCalls: 37015 + ttHits: 10841 + ttCutoffs: 8659 + betaCutoffs: 17531 + ttEntries: 72303 + negamaxTtHits: 6868 + quiescenceTtHits: 3973 + negamaxTtCutoffs: 6043 + quiescenceTtCutoffs: 2616 + negamaxBetaCutoffs: 4552 + quiescenceBetaCutoffs: 12979 + qsearchStandPatCutoffs: 39818 + qsearchDeltaPruneChecks: 19833 + qsearchDeltaPruneSkips: 18424 + qsearchNodesWithMoves: 29026 + qsearchGeneratedMoves: 112306 + pvsResearches: 227 + negamaxFrontierFutilityChecks: 15685 + negamaxFrontierFutilitySkips: 363 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + depths: + - 3 diff --git a/results/2.1.003/hexchess-game-2026-03-30T12-17-03-779Z.yaml b/results/2.1.003/hexchess-game-2026-03-30T12-17-03-779Z.yaml new file mode 100644 index 00000000..84e6c7c8 --- /dev/null +++ b/results/2.1.003/hexchess-game-2026-03-30T12-17-03-779Z.yaml @@ -0,0 +1,2492 @@ +version: 1 +startFen: b/qbk/n1b1n/r5r/ppppppppp/11/5P5/4P1P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 1 +historyIndex: 118 +engineUrl: "" +whiteSide: pyengine2 +blackSide: pyrustengine +depth: 4 +moves: + - san: d3d5 + source: pyengine2 + beforeFen: b/qbk/n1b1n/r5r/ppppppppp/11/5P5/4P1P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 1 + evaluations: 134821 + duration: 4233.699999988079 + metrics: + wallMs: 4220.591799996328 + evalsPerMs: 31.94362458840898 + rootMoves: 51 + negamaxNodes: 155774 + quiescenceNodes: 136519 + movegenCalls: 40073 + tacticalMovegenCalls: 28246 + legalContextCalls: 40073 + ttHits: 35137 + ttCutoffs: 33924 + betaCutoffs: 18648 + ttEntries: 136337 + negamaxTtHits: 32861 + quiescenceTtHits: 2276 + negamaxTtCutoffs: 32226 + quiescenceTtCutoffs: 1698 + negamaxBetaCutoffs: 8274 + quiescenceBetaCutoffs: 10374 + qsearchStandPatCutoffs: 106575 + qsearchDeltaPruneChecks: 1206 + qsearchDeltaPruneSkips: 1177 + qsearchNodesWithMoves: 19316 + qsearchGeneratedMoves: 37747 + pvsResearches: 738 + negamaxFrontierFutilityChecks: 139389 + negamaxFrontierFutilitySkips: 6899 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: e7e6 + source: pyrustengine + beforeFen: b/qbk/n1b1n/r5r/ppppppppp/11/3P1P5/4P1P4/5B1P3/2P2B2P2/1PRNQBKNRP1 b d4 0 1 + evaluations: 709376 + duration: 10254.5 + metrics: null + - san: e4e5 + source: pyengine2 + beforeFen: b/qbk/n1b1n/r5r/ppp1ppppp/4p6/3P1P5/4P1P4/5B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 2 + evaluations: 159802 + duration: 4231.699999988079 + metrics: + wallMs: 4218.610899988562 + evalsPerMs: 37.8802415744086 + rootMoves: 54 + negamaxNodes: 195124 + quiescenceNodes: 160938 + movegenCalls: 30526 + tacticalMovegenCalls: 20688 + legalContextCalls: 30526 + ttHits: 49033 + ttCutoffs: 48193 + betaCutoffs: 14548 + ttEntries: 164565 + negamaxTtHits: 47466 + quiescenceTtHits: 1567 + negamaxTtCutoffs: 47057 + quiescenceTtCutoffs: 1136 + negamaxBetaCutoffs: 5956 + quiescenceBetaCutoffs: 8592 + qsearchStandPatCutoffs: 139114 + qsearchDeltaPruneChecks: 2230 + qsearchDeltaPruneSkips: 2158 + qsearchNodesWithMoves: 16683 + qsearchGeneratedMoves: 42568 + pvsResearches: 209 + negamaxFrontierFutilityChecks: 185068 + negamaxFrontierFutilitySkips: 13923 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: e6d5 + source: pyrustengine + beforeFen: b/qbk/n1b1n/r5r/ppp1ppppp/4p6/3PPP5/6P4/5B1P3/2P2B2P2/1PRNQBKNRP1 b - 0 2 + evaluations: 1368602 + duration: 20364.5 + metrics: null + - san: e5d5 + source: pyengine2 + beforeFen: b/qbk/n1b1n/r5r/ppp1ppppp/11/3pPP5/6P4/5B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 3 + evaluations: 254170 + duration: 7896.900000035763 + metrics: + wallMs: 7870.555400033481 + evalsPerMs: 32.29378196091711 + rootMoves: 62 + negamaxNodes: 222652 + quiescenceNodes: 258649 + movegenCalls: 87018 + tacticalMovegenCalls: 70741 + legalContextCalls: 87018 + ttHits: 56674 + ttCutoffs: 54790 + betaCutoffs: 40888 + ttEntries: 259079 + negamaxTtHits: 51050 + quiescenceTtHits: 5624 + negamaxTtCutoffs: 50311 + quiescenceTtCutoffs: 4479 + negamaxBetaCutoffs: 9557 + quiescenceBetaCutoffs: 31331 + qsearchStandPatCutoffs: 183429 + qsearchDeltaPruneChecks: 14584 + qsearchDeltaPruneSkips: 13551 + qsearchNodesWithMoves: 63580 + qsearchGeneratedMoves: 176944 + pvsResearches: 421 + negamaxFrontierFutilityChecks: 212766 + negamaxFrontierFutilitySkips: 21990 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: e10e1 + source: pyrustengine + beforeFen: b/qbk/n1b1n/r5r/ppp1ppppp/11/3P1P5/6P4/5B1P3/2P2B2P2/1PRNQBKNRP1 b - 0 3 + evaluations: 1478619 + duration: 21917.600000023842 + metrics: null + - san: g1e1 + source: pyengine2 + beforeFen: b/1bk/n1b1n/r5r/ppp1ppppp/11/3P1P5/6P4/5B1P3/2P2B2P2/1PRNqBKNRP1 w - 0 4 + evaluations: 11655 + duration: 412.9000000357628 + metrics: + wallMs: 405.4821999743581 + evalsPerMs: 28.743555205967215 + rootMoves: 5 + negamaxNodes: 13629 + quiescenceNodes: 11714 + movegenCalls: 3685 + tacticalMovegenCalls: 2197 + legalContextCalls: 3685 + ttHits: 2829 + ttCutoffs: 2584 + betaCutoffs: 1534 + ttEntries: 11864 + negamaxTtHits: 2649 + quiescenceTtHits: 180 + negamaxTtCutoffs: 2525 + quiescenceTtCutoffs: 59 + negamaxBetaCutoffs: 776 + quiescenceBetaCutoffs: 758 + qsearchStandPatCutoffs: 9458 + qsearchDeltaPruneChecks: 102 + qsearchDeltaPruneSkips: 100 + qsearchNodesWithMoves: 1487 + qsearchGeneratedMoves: 2615 + pvsResearches: 43 + negamaxFrontierFutilityChecks: 16075 + negamaxFrontierFutilitySkips: 4726 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: h7h5 + source: pyrustengine + beforeFen: b/1bk/n1b1n/r5r/ppp1ppppp/11/3P1P5/6P4/5B1P3/2P2B2P2/1PRNKB1NRP1 b - 0 4 + evaluations: 688739 + duration: 9338.300000011921 + metrics: null + - san: g4g5 + source: pyengine2 + beforeFen: b/1bk/n1b1n/r5r/ppp1pp1pp/11/3P1P1p3/6P4/5B1P3/2P2B2P2/1PRNKB1NRP1 w h6 0 5 + evaluations: 182984 + duration: 5397.600000023842 + metrics: + wallMs: 5380.248699977528 + evalsPerMs: 34.010323723653194 + rootMoves: 55 + negamaxNodes: 189071 + quiescenceNodes: 185943 + movegenCalls: 59549 + tacticalMovegenCalls: 41213 + legalContextCalls: 59549 + ttHits: 42458 + ttCutoffs: 36690 + betaCutoffs: 26098 + ttEntries: 183126 + negamaxTtHits: 36456 + quiescenceTtHits: 6002 + negamaxTtCutoffs: 33731 + quiescenceTtCutoffs: 2959 + negamaxBetaCutoffs: 9555 + quiescenceBetaCutoffs: 16543 + qsearchStandPatCutoffs: 141771 + qsearchDeltaPruneChecks: 1312 + qsearchDeltaPruneSkips: 1265 + qsearchNodesWithMoves: 31860 + qsearchGeneratedMoves: 73555 + pvsResearches: 937 + negamaxFrontierFutilityChecks: 168276 + negamaxFrontierFutilitySkips: 10082 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: c8e8 + source: pyrustengine + beforeFen: b/1bk/n1b1n/r5r/ppp1pp1pp/11/3P1PPp3/11/5B1P3/2P2B2P2/1PRNKB1NRP1 b - 0 5 + evaluations: 804132 + duration: 10561.100000023842 + metrics: null + - san: e1d2 + source: pyengine2 + beforeFen: b/1bk/n1b1n/2r3r/ppp1pp1pp/11/3P1PPp3/11/5B1P3/2P2B2P2/1PRNKB1NRP1 w - 1 6 + evaluations: 37805 + duration: 1080.5999999642372 + metrics: + wallMs: 1072.5856000208296 + evalsPerMs: 35.246604093198556 + rootMoves: 9 + negamaxNodes: 34283 + quiescenceNodes: 38296 + movegenCalls: 14205 + tacticalMovegenCalls: 11047 + legalContextCalls: 14205 + ttHits: 9691 + ttCutoffs: 8640 + betaCutoffs: 6285 + ttEntries: 37476 + negamaxTtHits: 8605 + quiescenceTtHits: 1086 + negamaxTtCutoffs: 8148 + quiescenceTtCutoffs: 492 + negamaxBetaCutoffs: 1490 + quiescenceBetaCutoffs: 4795 + qsearchStandPatCutoffs: 26757 + qsearchDeltaPruneChecks: 168 + qsearchDeltaPruneSkips: 143 + qsearchNodesWithMoves: 9456 + qsearchGeneratedMoves: 22497 + pvsResearches: 185 + negamaxFrontierFutilityChecks: 29579 + negamaxFrontierFutilitySkips: 499 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: h5g5 + source: pyrustengine + beforeFen: b/1bk/n1b1n/2r3r/ppp1pp1pp/11/3P1PPp3/11/5B1P3/2PK1B2P2/1PRN1B1NRP1 b - 2 6 + evaluations: 709100 + duration: 10113.199999988079 + metrics: null + - san: f5g5 + source: pyengine2 + beforeFen: b/1bk/n1b1n/2r3r/ppp1pp1pp/11/3P1Pp4/11/5B1P3/2PK1B2P2/1PRN1B1NRP1 w - 0 7 + evaluations: 165631 + duration: 4793 + metrics: + wallMs: 4777.928200026508 + evalsPerMs: 34.66586207785229 + rootMoves: 57 + negamaxNodes: 192315 + quiescenceNodes: 167936 + movegenCalls: 46134 + tacticalMovegenCalls: 28715 + legalContextCalls: 46134 + ttHits: 55092 + ttCutoffs: 51833 + betaCutoffs: 18982 + ttEntries: 170018 + negamaxTtHits: 50999 + quiescenceTtHits: 4093 + negamaxTtCutoffs: 49514 + quiescenceTtCutoffs: 2319 + negamaxBetaCutoffs: 7127 + quiescenceBetaCutoffs: 11855 + qsearchStandPatCutoffs: 136902 + qsearchDeltaPruneChecks: 806 + qsearchDeltaPruneSkips: 665 + qsearchNodesWithMoves: 24621 + qsearchGeneratedMoves: 59196 + pvsResearches: 486 + negamaxFrontierFutilityChecks: 189722 + negamaxFrontierFutilitySkips: 22307 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: g7g6 + source: pyrustengine + beforeFen: b/1bk/n1b1n/2r3r/ppp1pp1pp/11/3P2P4/11/5B1P3/2PK1B2P2/1PRN1B1NRP1 b - 0 7 + evaluations: 903253 + duration: 12237 + metrics: null + - san: h3h5 + source: pyengine2 + beforeFen: b/1bk/n1b1n/2r3r/ppp1p2pp/6p4/3P2P4/11/5B1P3/2PK1B2P2/1PRN1B1NRP1 w - 0 8 + evaluations: 292525 + duration: 8768 + metrics: + wallMs: 8747.416199999861 + evalsPerMs: 33.44130350171341 + rootMoves: 55 + negamaxNodes: 266408 + quiescenceNodes: 297941 + movegenCalls: 109864 + tacticalMovegenCalls: 76840 + legalContextCalls: 109864 + ttHits: 57289 + ttCutoffs: 50769 + betaCutoffs: 45372 + ttEntries: 290613 + negamaxTtHits: 48226 + quiescenceTtHits: 9063 + negamaxTtCutoffs: 45341 + quiescenceTtCutoffs: 5428 + negamaxBetaCutoffs: 12985 + quiescenceBetaCutoffs: 32387 + qsearchStandPatCutoffs: 215673 + qsearchDeltaPruneChecks: 1784 + qsearchDeltaPruneSkips: 1511 + qsearchNodesWithMoves: 62420 + qsearchGeneratedMoves: 167190 + pvsResearches: 1394 + negamaxFrontierFutilityChecks: 237146 + negamaxFrontierFutilitySkips: 17413 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: f9h8 + source: pyrustengine + beforeFen: b/1bk/n1b1n/2r3r/ppp1p2pp/6p4/3P2PP3/11/5B5/2PK1B2P2/1PRN1B1NRP1 b h4 0 8 + evaluations: 711777 + duration: 11014.5 + metrics: null + - san: d2c3 + source: pyengine2 + beforeFen: b/1bk/n3n/2r2br/ppp1p2pp/6p4/3P2PP3/11/5B5/2PK1B2P2/1PRN1B1NRP1 w - 1 9 + evaluations: 16246 + duration: 446.80000001192093 + metrics: + wallMs: 440.9402000019327 + evalsPerMs: 36.843998347006675 + rootMoves: 5 + negamaxNodes: 18027 + quiescenceNodes: 16369 + movegenCalls: 3763 + tacticalMovegenCalls: 1986 + legalContextCalls: 3763 + ttHits: 3421 + ttCutoffs: 3390 + betaCutoffs: 1372 + ttEntries: 16899 + negamaxTtHits: 3279 + quiescenceTtHits: 142 + negamaxTtCutoffs: 3267 + quiescenceTtCutoffs: 123 + negamaxBetaCutoffs: 557 + quiescenceBetaCutoffs: 815 + qsearchStandPatCutoffs: 14260 + qsearchDeltaPruneChecks: 19 + qsearchDeltaPruneSkips: 19 + qsearchNodesWithMoves: 1764 + qsearchGeneratedMoves: 3784 + pvsResearches: 41 + negamaxFrontierFutilityChecks: 16420 + negamaxFrontierFutilitySkips: 497 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: e8e5 + source: pyrustengine + beforeFen: b/1bk/n3n/2r2br/ppp1p2pp/6p4/3P2PP3/11/2K2B5/2P2B2P2/1PRN1B1NRP1 b - 2 9 + evaluations: 1269281 + duration: 17523.100000023842 + metrics: null + - san: c3b3 + source: pyengine2 + beforeFen: b/1bk/n3n/5br/ppp1p2pp/6p4/3Pr1PP3/11/2K2B5/2P2B2P2/1PRN1B1NRP1 w - 3 10 + evaluations: 29000 + duration: 946.1000000238419 + metrics: + wallMs: 936.6957999882288 + evalsPerMs: 30.959891141141483 + rootMoves: 6 + negamaxNodes: 27139 + quiescenceNodes: 29205 + movegenCalls: 9656 + tacticalMovegenCalls: 5610 + legalContextCalls: 9656 + ttHits: 4608 + ttCutoffs: 4153 + betaCutoffs: 3338 + ttEntries: 29340 + negamaxTtHits: 4147 + quiescenceTtHits: 461 + negamaxTtCutoffs: 3946 + quiescenceTtCutoffs: 207 + negamaxBetaCutoffs: 994 + quiescenceBetaCutoffs: 2344 + qsearchStandPatCutoffs: 23388 + qsearchDeltaPruneChecks: 297 + qsearchDeltaPruneSkips: 239 + qsearchNodesWithMoves: 4841 + qsearchGeneratedMoves: 12007 + pvsResearches: 99 + negamaxFrontierFutilityChecks: 24750 + negamaxFrontierFutilitySkips: 1452 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: g6h5 + source: pyrustengine + beforeFen: b/1bk/n3n/5br/ppp1p2pp/6p4/3Pr1PP3/11/1K3B5/2P2B2P2/1PRN1B1NRP1 b - 4 10 + evaluations: 734800 + duration: 10573.900000035763 + metrics: null + - san: g5h5 + source: pyengine2 + beforeFen: b/1bk/n3n/5br/ppp1p2pp/11/3Pr1Pp3/11/1K3B5/2P2B2P2/1PRN1B1NRP1 w - 0 11 + evaluations: 239507 + duration: 7524.199999988079 + metrics: + wallMs: 7507.568300003186 + evalsPerMs: 31.90207407102755 + rootMoves: 68 + negamaxNodes: 267178 + quiescenceNodes: 241336 + movegenCalls: 70000 + tacticalMovegenCalls: 29212 + legalContextCalls: 70000 + ttHits: 47426 + ttCutoffs: 44387 + betaCutoffs: 22139 + ttEntries: 246793 + negamaxTtHits: 44006 + quiescenceTtHits: 3420 + negamaxTtCutoffs: 42558 + quiescenceTtCutoffs: 1829 + negamaxBetaCutoffs: 10641 + quiescenceBetaCutoffs: 11498 + qsearchStandPatCutoffs: 210295 + qsearchDeltaPruneChecks: 3083 + qsearchDeltaPruneSkips: 2655 + qsearchNodesWithMoves: 22863 + qsearchGeneratedMoves: 55903 + pvsResearches: 423 + negamaxFrontierFutilityChecks: 286339 + negamaxFrontierFutilitySkips: 59737 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: f11k3 + source: pyrustengine + beforeFen: b/1bk/n3n/5br/ppp1p2pp/11/3Pr2P3/11/1K3B5/2P2B2P2/1PRN1B1NRP1 b - 0 11 + evaluations: 717057 + duration: 10638 + metrics: null + - san: b3a4 + source: pyengine2 + beforeFen: 1/1bk/n3n/5br/ppp1p2pp/11/3Pr2P3/11/1K3B3b1/2P2B2P2/1PRN1B1NRP1 w - 1 12 + evaluations: 37601 + duration: 1191.0999999642372 + metrics: + wallMs: 1179.7743000206538 + evalsPerMs: 31.87135030771711 + rootMoves: 9 + negamaxNodes: 38439 + quiescenceNodes: 37958 + movegenCalls: 13513 + tacticalMovegenCalls: 7076 + legalContextCalls: 13513 + ttHits: 6159 + ttCutoffs: 5699 + betaCutoffs: 4696 + ttEntries: 38295 + negamaxTtHits: 5564 + quiescenceTtHits: 595 + negamaxTtCutoffs: 5319 + quiescenceTtCutoffs: 380 + negamaxBetaCutoffs: 1790 + quiescenceBetaCutoffs: 2906 + qsearchStandPatCutoffs: 30502 + qsearchDeltaPruneChecks: 791 + qsearchDeltaPruneSkips: 750 + qsearchNodesWithMoves: 5639 + qsearchGeneratedMoves: 12128 + pvsResearches: 104 + negamaxFrontierFutilityChecks: 42154 + negamaxFrontierFutilitySkips: 10651 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: f10g8 + source: pyrustengine + beforeFen: 1/1bk/n3n/5br/ppp1p2pp/11/3Pr2P3/K10/5B3b1/2P2B2P2/1PRN1B1NRP1 b - 2 12 + evaluations: 1665649 + duration: 25591.5 + metrics: null + - san: i1g3 + source: pyengine2 + beforeFen: 1/2k/n3n/4bbr/ppp1p2pp/11/3Pr2P3/K10/5B3b1/2P2B2P2/1PRN1B1NRP1 w - 3 13 + evaluations: 316864 + duration: 9282.699999988079 + metrics: + wallMs: 9258.206000027712 + evalsPerMs: 34.22520518543782 + rootMoves: 65 + negamaxNodes: 302981 + quiescenceNodes: 321687 + movegenCalls: 110633 + tacticalMovegenCalls: 68655 + legalContextCalls: 110633 + ttHits: 51872 + ttCutoffs: 45938 + betaCutoffs: 43429 + ttEntries: 318648 + negamaxTtHits: 43897 + quiescenceTtHits: 7975 + negamaxTtCutoffs: 41113 + quiescenceTtCutoffs: 4825 + negamaxBetaCutoffs: 14288 + quiescenceBetaCutoffs: 29141 + qsearchStandPatCutoffs: 248207 + qsearchDeltaPruneChecks: 6238 + qsearchDeltaPruneSkips: 5716 + qsearchNodesWithMoves: 55470 + qsearchGeneratedMoves: 135459 + pvsResearches: 713 + negamaxFrontierFutilityChecks: 279126 + negamaxFrontierFutilitySkips: 27045 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: h9g7 + source: pyrustengine + beforeFen: 1/2k/n3n/4bbr/ppp1p2pp/11/3Pr2P3/K10/5BR2b1/2P2B2P2/1PRN1B1N1P1 b - 4 13 + evaluations: 941540 + duration: 16593.600000023842 + metrics: null + - san: g3k3 + source: pyengine2 + beforeFen: 1/2k/n4/4bbr/ppp1pn1pp/11/3Pr2P3/K10/5BR2b1/2P2B2P2/1PRN1B1N1P1 w - 5 14 + evaluations: 357597 + duration: 11022.199999988079 + metrics: + wallMs: 10976.788399973884 + evalsPerMs: 32.57756157537398 + rootMoves: 70 + negamaxNodes: 328886 + quiescenceNodes: 364534 + movegenCalls: 131298 + tacticalMovegenCalls: 84529 + legalContextCalls: 131298 + ttHits: 60315 + ttCutoffs: 54003 + betaCutoffs: 52927 + ttEntries: 361756 + negamaxTtHits: 49916 + quiescenceTtHits: 10399 + negamaxTtCutoffs: 47065 + quiescenceTtCutoffs: 6938 + negamaxBetaCutoffs: 17938 + quiescenceBetaCutoffs: 34989 + qsearchStandPatCutoffs: 273067 + qsearchDeltaPruneChecks: 7551 + qsearchDeltaPruneSkips: 6877 + qsearchNodesWithMoves: 69950 + qsearchGeneratedMoves: 183072 + pvsResearches: 1017 + negamaxFrontierFutilityChecks: 295067 + negamaxFrontierFutilitySkips: 28962 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d9e7 + source: pyrustengine + beforeFen: 1/2k/n4/4bbr/ppp1pn1pp/11/3Pr2P3/K10/5B3R1/2P2B2P2/1PRN1B1N1P1 b - 0 14 + evaluations: 1922028 + duration: 27650.80000001192 + metrics: null + - san: f1d3 + source: pyengine2 + beforeFen: 1/2k/5/4bbr/pppnpn1pp/11/3Pr2P3/K10/5B3R1/2P2B2P2/1PRN1B1N1P1 w - 1 15 + evaluations: 257419 + duration: 8465.299999952316 + metrics: + wallMs: 8432.948599976953 + evalsPerMs: 30.525384679885693 + rootMoves: 69 + negamaxNodes: 265915 + quiescenceNodes: 262262 + movegenCalls: 80861 + tacticalMovegenCalls: 44976 + legalContextCalls: 80861 + ttHits: 47990 + ttCutoffs: 40208 + betaCutoffs: 32808 + ttEntries: 264941 + negamaxTtHits: 38709 + quiescenceTtHits: 9281 + negamaxTtCutoffs: 35361 + quiescenceTtCutoffs: 4847 + negamaxBetaCutoffs: 16432 + quiescenceBetaCutoffs: 16376 + qsearchStandPatCutoffs: 212439 + qsearchDeltaPruneChecks: 7881 + qsearchDeltaPruneSkips: 7277 + qsearchNodesWithMoves: 36826 + qsearchGeneratedMoves: 88425 + pvsResearches: 939 + negamaxFrontierFutilityChecks: 262232 + negamaxFrontierFutilitySkips: 50028 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: e5f6 + source: pyrustengine + beforeFen: 1/2k/5/4bbr/pppnpn1pp/11/3Pr2P3/K10/3B1B3R1/2P2B2P2/1PRN3N1P1 b - 2 15 + evaluations: 1461574 + duration: 21201.599999964237 + metrics: null + - san: f2e3 + source: pyengine2 + beforeFen: 1/2k/5/4bbr/pppnpn1pp/5r5/3P3P3/K10/3B1B3R1/2P2B2P2/1PRN3N1P1 w - 3 16 + evaluations: 251855 + duration: 8002.199999988079 + metrics: + wallMs: 7983.958300028462 + evalsPerMs: 31.545129688252775 + rootMoves: 70 + negamaxNodes: 255610 + quiescenceNodes: 256773 + movegenCalls: 89963 + tacticalMovegenCalls: 50087 + legalContextCalls: 89963 + ttHits: 50658 + ttCutoffs: 43447 + betaCutoffs: 35472 + ttEntries: 260222 + negamaxTtHits: 41789 + quiescenceTtHits: 8869 + negamaxTtCutoffs: 38493 + quiescenceTtCutoffs: 4954 + negamaxBetaCutoffs: 16400 + quiescenceBetaCutoffs: 19072 + qsearchStandPatCutoffs: 201732 + qsearchDeltaPruneChecks: 5497 + qsearchDeltaPruneSkips: 5115 + qsearchNodesWithMoves: 42227 + qsearchGeneratedMoves: 108169 + pvsResearches: 765 + negamaxFrontierFutilityChecks: 279723 + negamaxFrontierFutilitySkips: 76738 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: f6c6 + source: pyrustengine + beforeFen: 1/2k/5/4bbr/pppnpn1pp/5r5/3P3P3/K10/3BBB3R1/2P5P2/1PRN3N1P1 b - 4 16 + evaluations: 1654785 + duration: 23028.69999998808 + metrics: null + - san: a4b4 + source: pyengine2 + beforeFen: 1/2k/5/4bbr/pppnpn1pp/2r8/3P3P3/K10/3BBB3R1/2P5P2/1PRN3N1P1 w - 5 17 + evaluations: 21038 + duration: 681.6999999880791 + metrics: + wallMs: 675.0553000019863 + evalsPerMs: 31.1648541977792 + rootMoves: 5 + negamaxNodes: 18788 + quiescenceNodes: 21484 + movegenCalls: 8669 + tacticalMovegenCalls: 5451 + legalContextCalls: 8669 + ttHits: 5590 + ttCutoffs: 4111 + betaCutoffs: 3397 + ttEntries: 20885 + negamaxTtHits: 4130 + quiescenceTtHits: 1460 + negamaxTtCutoffs: 3658 + quiescenceTtCutoffs: 453 + negamaxBetaCutoffs: 1188 + quiescenceBetaCutoffs: 2209 + qsearchStandPatCutoffs: 15580 + qsearchDeltaPruneChecks: 1246 + qsearchDeltaPruneSkips: 1195 + qsearchNodesWithMoves: 4995 + qsearchGeneratedMoves: 14001 + pvsResearches: 54 + negamaxFrontierFutilityChecks: 18688 + negamaxFrontierFutilitySkips: 3369 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: i8h9 + source: pyrustengine + beforeFen: 1/2k/5/4bbr/pppnpn1pp/2r8/3P3P3/1K9/3BBB3R1/2P5P2/1PRN3N1P1 b - 6 17 + evaluations: 1400981 + duration: 19807.69999998808 + metrics: null + - san: c2c4 + source: pyengine2 + beforeFen: 1/2k/4r/4bb1/pppnpn1pp/2r8/3P3P3/1K9/3BBB3R1/2P5P2/1PRN3N1P1 w - 7 18 + evaluations: 259937 + duration: 7711.600000023842 + metrics: + wallMs: 7685.290300054476 + evalsPerMs: 33.82266509804548 + rootMoves: 63 + negamaxNodes: 238425 + quiescenceNodes: 264604 + movegenCalls: 95405 + tacticalMovegenCalls: 55340 + legalContextCalls: 95405 + ttHits: 43090 + ttCutoffs: 34785 + betaCutoffs: 36670 + ttEntries: 267660 + negamaxTtHits: 33752 + quiescenceTtHits: 9338 + negamaxTtCutoffs: 30030 + quiescenceTtCutoffs: 4755 + negamaxBetaCutoffs: 15143 + quiescenceBetaCutoffs: 21527 + qsearchStandPatCutoffs: 204509 + qsearchDeltaPruneChecks: 8224 + qsearchDeltaPruneSkips: 8080 + qsearchNodesWithMoves: 49811 + qsearchGeneratedMoves: 133577 + pvsResearches: 879 + negamaxFrontierFutilityChecks: 228730 + negamaxFrontierFutilitySkips: 35599 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: c6g5 + source: pyrustengine + beforeFen: 1/2k/4r/4bb1/pppnpn1pp/2r8/3P3P3/1KP8/3BBB3R1/8P2/1PRN3N1P1 b c3 0 18 + evaluations: 1882804 + duration: 25253.80000001192 + metrics: null + - san: b4c3 + source: pyengine2 + beforeFen: 1/2k/4r/4bb1/pppnpn1pp/11/3P2rP3/1KP8/3BBB3R1/8P2/1PRN3N1P1 w - 1 19 + evaluations: 222975 + duration: 6803.200000047684 + metrics: + wallMs: 6783.58119999757 + evalsPerMs: 32.86980629052982 + rootMoves: 66 + negamaxNodes: 203308 + quiescenceNodes: 226359 + movegenCalls: 82011 + tacticalMovegenCalls: 51987 + legalContextCalls: 82011 + ttHits: 39014 + ttCutoffs: 35727 + betaCutoffs: 34070 + ttEntries: 230435 + negamaxTtHits: 33643 + quiescenceTtHits: 5371 + negamaxTtCutoffs: 32309 + quiescenceTtCutoffs: 3418 + negamaxBetaCutoffs: 11295 + quiescenceBetaCutoffs: 22775 + qsearchStandPatCutoffs: 170954 + qsearchDeltaPruneChecks: 6099 + qsearchDeltaPruneSkips: 5863 + qsearchNodesWithMoves: 46126 + qsearchGeneratedMoves: 134497 + pvsResearches: 442 + negamaxFrontierFutilityChecks: 244667 + negamaxFrontierFutilitySkips: 87067 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: e7h6 + source: pyrustengine + beforeFen: 1/2k/4r/4bb1/pppnpn1pp/11/3P2rP3/2P8/2KBBB3R1/8P2/1PRN3N1P1 b - 2 19 + evaluations: 1840487 + duration: 25887.900000035763 + metrics: null + - san: k3g3 + source: pyengine2 + beforeFen: 1/2k/4r/4bb1/ppp1pn1pp/7n3/3P2rP3/2P8/2KBBB3R1/8P2/1PRN3N1P1 w - 3 20 + evaluations: 67365 + duration: 2781.300000011921 + metrics: + wallMs: 2769.9509999947622 + evalsPerMs: 24.319924792939435 + rootMoves: 63 + negamaxNodes: 71807 + quiescenceNodes: 68168 + movegenCalls: 35155 + tacticalMovegenCalls: 17320 + legalContextCalls: 35155 + ttHits: 12645 + ttCutoffs: 10722 + betaCutoffs: 14196 + ttEntries: 72834 + negamaxTtHits: 10917 + quiescenceTtHits: 1728 + negamaxTtCutoffs: 9919 + quiescenceTtCutoffs: 803 + negamaxBetaCutoffs: 7135 + quiescenceBetaCutoffs: 7061 + qsearchStandPatCutoffs: 50045 + qsearchDeltaPruneChecks: 468 + qsearchDeltaPruneSkips: 422 + qsearchNodesWithMoves: 12900 + qsearchGeneratedMoves: 28668 + pvsResearches: 263 + negamaxFrontierFutilityChecks: 213367 + negamaxFrontierFutilitySkips: 172616 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: g7d6 + source: pyrustengine + beforeFen: 1/2k/4r/4bb1/ppp1pn1pp/7n3/3P2rP3/2P8/2KBBBR4/8P2/1PRN3N1P1 b - 4 20 + evaluations: 1480116 + duration: 26606.80000001192 + metrics: null + - san: c3b4 + source: pyengine2 + beforeFen: 1/2k/4r/4bb1/ppp1p2pp/3n3n3/3P2rP3/2P8/2KBBBR4/8P2/1PRN3N1P1 w - 5 21 + evaluations: 11042 + duration: 324.80000001192093 + metrics: + wallMs: 317.4297999939881 + evalsPerMs: 34.785643944611145 + rootMoves: 5 + negamaxNodes: 15754 + quiescenceNodes: 11043 + movegenCalls: 1803 + tacticalMovegenCalls: 346 + legalContextCalls: 1803 + ttHits: 4038 + ttCutoffs: 4033 + betaCutoffs: 588 + ttEntries: 11850 + negamaxTtHits: 4037 + quiescenceTtHits: 1 + negamaxTtCutoffs: 4032 + quiescenceTtCutoffs: 1 + negamaxBetaCutoffs: 515 + quiescenceBetaCutoffs: 73 + qsearchStandPatCutoffs: 10696 + qsearchDeltaPruneChecks: 303 + qsearchDeltaPruneSkips: 299 + qsearchNodesWithMoves: 306 + qsearchGeneratedMoves: 579 + pvsResearches: 5 + negamaxFrontierFutilityChecks: 15078 + negamaxFrontierFutilitySkips: 943 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: h8d8 + source: pyrustengine + beforeFen: 1/2k/4r/4bb1/ppp1p2pp/3n3n3/3P2rP3/1KP8/3BBBR4/8P2/1PRN3N1P1 b - 6 21 + evaluations: 1458519 + duration: 27532.100000023842 + metrics: null + - san: b4c5 + source: pyengine2 + beforeFen: 1/2k/4r/1b2b2/ppp1p2pp/3n3n3/3P2rP3/1KP8/3BBBR4/8P2/1PRN3N1P1 w - 7 22 + evaluations: 5743 + duration: 190.69999998807907 + metrics: + wallMs: 182.29750002501532 + evalsPerMs: 31.50344902816512 + rootMoves: 3 + negamaxNodes: 7548 + quiescenceNodes: 5766 + movegenCalls: 1615 + tacticalMovegenCalls: 599 + legalContextCalls: 1615 + ttHits: 1748 + ttCutoffs: 1716 + betaCutoffs: 563 + ttEntries: 6159 + negamaxTtHits: 1708 + quiescenceTtHits: 40 + negamaxTtCutoffs: 1692 + quiescenceTtCutoffs: 24 + negamaxBetaCutoffs: 351 + quiescenceBetaCutoffs: 212 + qsearchStandPatCutoffs: 5143 + qsearchDeltaPruneChecks: 294 + qsearchDeltaPruneSkips: 289 + qsearchNodesWithMoves: 464 + qsearchGeneratedMoves: 1110 + pvsResearches: 12 + negamaxFrontierFutilityChecks: 10211 + negamaxFrontierFutilitySkips: 3800 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: b7b5 + source: pyrustengine + beforeFen: 1/2k/4r/1b2b2/ppp1p2pp/3n3n3/2KP2rP3/2P8/3BBBR4/8P2/1PRN3N1P1 b - 8 22 + evaluations: 1188966 + duration: 21630.19999998808 + metrics: null + - san: c5b5 + source: pyengine2 + beforeFen: 1/2k/4r/1b2b2/1pp1p2pp/3n3n3/1pKP2rP3/2P8/3BBBR4/8P2/1PRN3N1P1 w - 0 23 + evaluations: 5764 + duration: 160.9000000357628 + metrics: + wallMs: 156.3728000037372 + evalsPerMs: 36.860630492401775 + rootMoves: 2 + negamaxNodes: 7241 + quiescenceNodes: 5787 + movegenCalls: 1248 + tacticalMovegenCalls: 454 + legalContextCalls: 1248 + ttHits: 1761 + ttCutoffs: 1757 + betaCutoffs: 392 + ttEntries: 6062 + negamaxTtHits: 1733 + quiescenceTtHits: 28 + negamaxTtCutoffs: 1732 + quiescenceTtCutoffs: 25 + negamaxBetaCutoffs: 199 + quiescenceBetaCutoffs: 193 + qsearchStandPatCutoffs: 5308 + qsearchDeltaPruneChecks: 122 + qsearchDeltaPruneSkips: 121 + qsearchNodesWithMoves: 412 + qsearchGeneratedMoves: 1175 + pvsResearches: 5 + negamaxFrontierFutilityChecks: 7051 + negamaxFrontierFutilitySkips: 482 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: c7c6 + source: pyrustengine + beforeFen: 1/2k/4r/1b2b2/1pp1p2pp/3n3n3/1K1P2rP3/2P8/3BBBR4/8P2/1PRN3N1P1 b - 0 23 + evaluations: 1716477 + duration: 32955.39999997616 + metrics: null + - san: b5c5 + source: pyengine2 + beforeFen: 1/2k/4r/1b2b2/2p1p2pp/2pn3n3/1K1P2rP3/2P8/3BBBR4/8P2/1PRN3N1P1 w - 0 24 + evaluations: 7425 + duration: 241.5 + metrics: + wallMs: 232.58050001459196 + evalsPerMs: 31.924430464007774 + rootMoves: 4 + negamaxNodes: 10015 + quiescenceNodes: 7448 + movegenCalls: 1782 + tacticalMovegenCalls: 739 + legalContextCalls: 1782 + ttHits: 2497 + ttCutoffs: 2459 + betaCutoffs: 710 + ttEntries: 8007 + negamaxTtHits: 2452 + quiescenceTtHits: 45 + negamaxTtCutoffs: 2436 + quiescenceTtCutoffs: 23 + negamaxBetaCutoffs: 460 + quiescenceBetaCutoffs: 250 + qsearchStandPatCutoffs: 6686 + qsearchDeltaPruneChecks: 297 + qsearchDeltaPruneSkips: 290 + qsearchNodesWithMoves: 604 + qsearchGeneratedMoves: 1257 + pvsResearches: 20 + negamaxFrontierFutilityChecks: 11941 + negamaxFrontierFutilitySkips: 3462 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d6b7 + source: pyrustengine + beforeFen: 1/2k/4r/1b2b2/2p1p2pp/2pn3n3/2KP2rP3/2P8/3BBBR4/8P2/1PRN3N1P1 b - 1 24 + evaluations: 1447150 + duration: 25942.5 + metrics: null + - san: c5b6 + source: pyengine2 + beforeFen: 1/2k/4r/1b2b2/n1p1p2pp/2p4n3/2KP2rP3/2P8/3BBBR4/8P2/1PRN3N1P1 w - 2 25 + evaluations: 6784 + duration: 208.60000002384186 + metrics: + wallMs: 200.52479999139905 + evalsPerMs: 33.83122686216857 + rootMoves: 4 + negamaxNodes: 8846 + quiescenceNodes: 6807 + movegenCalls: 1631 + tacticalMovegenCalls: 559 + legalContextCalls: 1631 + ttHits: 1876 + ttCutoffs: 1843 + betaCutoffs: 598 + ttEntries: 7332 + negamaxTtHits: 1835 + quiescenceTtHits: 41 + negamaxTtCutoffs: 1820 + quiescenceTtCutoffs: 23 + negamaxBetaCutoffs: 408 + quiescenceBetaCutoffs: 190 + qsearchStandPatCutoffs: 6225 + qsearchDeltaPruneChecks: 228 + qsearchDeltaPruneSkips: 219 + qsearchNodesWithMoves: 456 + qsearchGeneratedMoves: 969 + pvsResearches: 9 + negamaxFrontierFutilityChecks: 9826 + negamaxFrontierFutilitySkips: 2361 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: h6e7 + source: pyrustengine + beforeFen: 1/2k/4r/1b2b2/n1p1p2pp/1Kp4n3/3P2rP3/2P8/3BBBR4/8P2/1PRN3N1P1 b - 3 25 + evaluations: 1156736 + duration: 21009.099999964237 + metrics: null + - san: b6a5 + source: pyengine2 + beforeFen: 1/2k/4r/1b2b2/n1pnp2pp/1Kp8/3P2rP3/2P8/3BBBR4/8P2/1PRN3N1P1 w - 4 26 + evaluations: 1950 + duration: 73.60000002384186 + metrics: + wallMs: 67.21340003423393 + evalsPerMs: 29.012071982771335 + rootMoves: 1 + negamaxNodes: 2621 + quiescenceNodes: 1955 + movegenCalls: 422 + tacticalMovegenCalls: 106 + legalContextCalls: 422 + ttHits: 562 + ttCutoffs: 559 + betaCutoffs: 139 + ttEntries: 2116 + negamaxTtHits: 555 + quiescenceTtHits: 7 + negamaxTtCutoffs: 554 + quiescenceTtCutoffs: 5 + negamaxBetaCutoffs: 112 + quiescenceBetaCutoffs: 27 + qsearchStandPatCutoffs: 1844 + qsearchDeltaPruneChecks: 73 + qsearchDeltaPruneSkips: 72 + qsearchNodesWithMoves: 97 + qsearchGeneratedMoves: 192 + pvsResearches: 2 + negamaxFrontierFutilityChecks: 2203 + negamaxFrontierFutilitySkips: 41 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: b7d6 + source: pyrustengine + beforeFen: 1/2k/4r/1b2b2/n1pnp2pp/2p8/K2P2rP3/2P8/3BBBR4/8P2/1PRN3N1P1 b - 5 26 + evaluations: 1637669 + duration: 30679.899999976158 + metrics: null + - san: a5b4 + source: pyengine2 + beforeFen: 1/2k/4r/1b2b2/2pnp2pp/2pn7/K2P2rP3/2P8/3BBBR4/8P2/1PRN3N1P1 w - 6 27 + evaluations: 2226 + duration: 73.30000001192093 + metrics: + wallMs: 67.08880001679063 + evalsPerMs: 33.179904834232964 + rootMoves: 1 + negamaxNodes: 3189 + quiescenceNodes: 2227 + movegenCalls: 356 + tacticalMovegenCalls: 100 + legalContextCalls: 356 + ttHits: 850 + ttCutoffs: 846 + betaCutoffs: 141 + ttEntries: 2407 + negamaxTtHits: 846 + quiescenceTtHits: 4 + negamaxTtCutoffs: 845 + quiescenceTtCutoffs: 1 + negamaxBetaCutoffs: 118 + quiescenceBetaCutoffs: 23 + qsearchStandPatCutoffs: 2126 + qsearchDeltaPruneChecks: 79 + qsearchDeltaPruneSkips: 78 + qsearchNodesWithMoves: 95 + qsearchGeneratedMoves: 204 + pvsResearches: 2 + negamaxFrontierFutilityChecks: 2783 + negamaxFrontierFutilitySkips: 99 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: k7k5 + source: pyrustengine + beforeFen: 1/2k/4r/1b2b2/2pnp2pp/2pn7/3P2rP3/1KP8/3BBBR4/8P2/1PRN3N1P1 b - 7 27 + evaluations: 3455506 + duration: 72229.5 + metrics: null + - san: c4c5 + source: pyengine2 + beforeFen: 1/2k/4r/1b2b2/2pnp2p1/2pn7/3P2rP1p1/1KP8/3BBBR4/8P2/1PRN3N1P1 w k6 0 28 + evaluations: 137753 + duration: 4380.900000035763 + metrics: + wallMs: 4364.861799986102 + evalsPerMs: 31.559532996082172 + rootMoves: 63 + negamaxNodes: 152412 + quiescenceNodes: 139452 + movegenCalls: 38065 + tacticalMovegenCalls: 22950 + legalContextCalls: 38065 + ttHits: 38531 + ttCutoffs: 37321 + betaCutoffs: 17392 + ttEntries: 146742 + negamaxTtHits: 36066 + quiescenceTtHits: 2465 + negamaxTtCutoffs: 35614 + quiescenceTtCutoffs: 1707 + negamaxBetaCutoffs: 7494 + quiescenceBetaCutoffs: 9898 + qsearchStandPatCutoffs: 114795 + qsearchDeltaPruneChecks: 4376 + qsearchDeltaPruneSkips: 3986 + qsearchNodesWithMoves: 21074 + qsearchGeneratedMoves: 60883 + pvsResearches: 205 + negamaxFrontierFutilityChecks: 187214 + negamaxFrontierFutilitySkips: 69663 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d6e9 + source: pyrustengine + beforeFen: 1/2k/4r/1b2b2/2pnp2p1/2pn7/2PP2rP1p1/1K9/3BBBR4/8P2/1PRN3N1P1 b - 0 28 + evaluations: 3236422 + duration: 63401.39999997616 + metrics: null + - san: f3g4 + source: pyengine2 + beforeFen: 1/2k/1n2r/1b2b2/2pnp2p1/2p8/2PP2rP1p1/1K9/3BBBR4/8P2/1PRN3N1P1 w - 1 29 + evaluations: 129702 + duration: 4013 + metrics: + wallMs: 3999.2533999611624 + evalsPerMs: 32.431553349747624 + rootMoves: 69 + negamaxNodes: 141720 + quiescenceNodes: 131349 + movegenCalls: 41498 + tacticalMovegenCalls: 25207 + legalContextCalls: 41498 + ttHits: 34135 + ttCutoffs: 32556 + betaCutoffs: 18603 + ttEntries: 137873 + negamaxTtHits: 31563 + quiescenceTtHits: 2572 + negamaxTtCutoffs: 30906 + quiescenceTtCutoffs: 1650 + negamaxBetaCutoffs: 8164 + quiescenceBetaCutoffs: 10439 + qsearchStandPatCutoffs: 104492 + qsearchDeltaPruneChecks: 2338 + qsearchDeltaPruneSkips: 1944 + qsearchNodesWithMoves: 22138 + qsearchGeneratedMoves: 56220 + pvsResearches: 266 + negamaxFrontierFutilityChecks: 162641 + negamaxFrontierFutilitySkips: 53637 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: g5d3 + source: pyrustengine + beforeFen: 1/2k/1n2r/1b2b2/2pnp2p1/2p8/2PP2rP1p1/1K4B4/3BB1R4/8P2/1PRN3N1P1 b - 2 29 + evaluations: 1173126 + duration: 20520.5 + metrics: null + - san: g4e7 + source: pyengine2 + beforeFen: 1/2k/1n2r/1b2b2/2pnp2p1/2p8/2PP3P1p1/1K4B4/3rB1R4/8P2/1PRN3N1P1 w - 0 30 + evaluations: 203007 + duration: 6563.5 + metrics: + wallMs: 6546.699600003194 + evalsPerMs: 31.00905989330883 + rootMoves: 58 + negamaxNodes: 143865 + quiescenceNodes: 209591 + movegenCalls: 101044 + tacticalMovegenCalls: 78277 + legalContextCalls: 101044 + ttHits: 32314 + ttCutoffs: 24121 + betaCutoffs: 45752 + ttEntries: 200609 + negamaxTtHits: 20798 + quiescenceTtHits: 11516 + negamaxTtCutoffs: 17502 + quiescenceTtCutoffs: 6619 + negamaxBetaCutoffs: 10588 + quiescenceBetaCutoffs: 35164 + qsearchStandPatCutoffs: 124695 + qsearchDeltaPruneChecks: 6123 + qsearchDeltaPruneSkips: 4812 + qsearchNodesWithMoves: 67821 + qsearchGeneratedMoves: 175087 + pvsResearches: 667 + negamaxFrontierFutilityChecks: 105415 + negamaxFrontierFutilitySkips: 14464 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d7e7 + source: pyrustengine + beforeFen: 1/2k/1n2r/1b2b2/2pBp2p1/2p8/2PP3P1p1/1K9/3rB1R4/8P2/1PRN3N1P1 b - 0 30 + evaluations: 84066 + duration: 1173.699999988079 + metrics: null + - san: g3g8 + source: pyengine2 + beforeFen: 1/2k/1n2r/1b2b2/3pp2p1/2p8/2PP3P1p1/1K9/3rB1R4/8P2/1PRN3N1P1 w - 0 31 + evaluations: 100102 + duration: 3797.599999964237 + metrics: + wallMs: 3782.905599975493 + evalsPerMs: 26.46167009841549 + rootMoves: 55 + negamaxNodes: 93971 + quiescenceNodes: 102832 + movegenCalls: 51035 + tacticalMovegenCalls: 33287 + legalContextCalls: 51035 + ttHits: 22121 + ttCutoffs: 16314 + betaCutoffs: 22612 + ttEntries: 101992 + negamaxTtHits: 16166 + quiescenceTtHits: 5955 + negamaxTtCutoffs: 13575 + quiescenceTtCutoffs: 2739 + negamaxBetaCutoffs: 9469 + quiescenceBetaCutoffs: 13143 + qsearchStandPatCutoffs: 66806 + qsearchDeltaPruneChecks: 3808 + qsearchDeltaPruneSkips: 2967 + qsearchNodesWithMoves: 27309 + qsearchGeneratedMoves: 56993 + pvsResearches: 438 + negamaxFrontierFutilityChecks: 70442 + negamaxFrontierFutilitySkips: 11369 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: g10e10 + source: pyrustengine + beforeFen: 1/2k/1n2r/1b2R2/3pp2p1/2p8/2PP3P1p1/1K9/3rB6/8P2/1PRN3N1P1 b - 0 31 + evaluations: 36939 + duration: 430.30000001192093 + metrics: null + - san: i2i4 + source: pyengine2 + beforeFen: 1/k2/1n2r/1b2R2/3pp2p1/2p8/2PP3P1p1/1K9/3rB6/8P2/1PRN3N1P1 w - 1 32 + evaluations: 91056 + duration: 3165.5 + metrics: + wallMs: 3153.8600999629125 + evalsPerMs: 28.871286967063238 + rootMoves: 55 + negamaxNodes: 73343 + quiescenceNodes: 93718 + movegenCalls: 50467 + tacticalMovegenCalls: 34147 + legalContextCalls: 50467 + ttHits: 15908 + ttCutoffs: 11378 + betaCutoffs: 22243 + ttEntries: 91070 + negamaxTtHits: 10633 + quiescenceTtHits: 5275 + negamaxTtCutoffs: 8716 + quiescenceTtCutoffs: 2662 + negamaxBetaCutoffs: 8474 + quiescenceBetaCutoffs: 13769 + qsearchStandPatCutoffs: 56909 + qsearchDeltaPruneChecks: 4234 + qsearchDeltaPruneSkips: 3758 + qsearchNodesWithMoves: 26557 + qsearchGeneratedMoves: 68964 + pvsResearches: 416 + negamaxFrontierFutilityChecks: 65519 + negamaxFrontierFutilitySkips: 23114 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: h9f9 + source: pyrustengine + beforeFen: 1/k2/1n2r/1b2R2/3pp2p1/2p8/2PP3P1p1/1K6P2/3rB6/11/1PRN3N1P1 b i3 0 32 + evaluations: 587598 + duration: 7462.699999988079 + metrics: null + - san: g8f9 + source: pyengine2 + beforeFen: 1/k2/1nr2/1b2R2/3pp2p1/2p8/2PP3P1p1/1K6P2/3rB6/11/1PRN3N1P1 w - 1 33 + evaluations: 39199 + duration: 1533.6000000238419 + metrics: + wallMs: 1525.433900009375 + evalsPerMs: 25.696950880506254 + rootMoves: 55 + negamaxNodes: 37031 + quiescenceNodes: 39677 + movegenCalls: 25681 + tacticalMovegenCalls: 16289 + legalContextCalls: 25681 + ttHits: 6780 + ttCutoffs: 5477 + betaCutoffs: 11203 + ttEntries: 39817 + negamaxTtHits: 5651 + quiescenceTtHits: 1129 + negamaxTtCutoffs: 4998 + quiescenceTtCutoffs: 479 + negamaxBetaCutoffs: 4509 + quiescenceBetaCutoffs: 6694 + qsearchStandPatCutoffs: 22909 + qsearchDeltaPruneChecks: 676 + qsearchDeltaPruneSkips: 569 + qsearchNodesWithMoves: 11103 + qsearchGeneratedMoves: 22644 + pvsResearches: 269 + negamaxFrontierFutilityChecks: 47206 + negamaxFrontierFutilitySkips: 32258 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: e10f9 + source: pyrustengine + beforeFen: 1/k2/1nR2/1b5/3pp2p1/2p8/2PP3P1p1/1K6P2/3rB6/11/1PRN3N1P1 b - 0 33 + evaluations: 138165 + duration: 1290.8999999761581 + metrics: null + - san: b4c4 + source: pyengine2 + beforeFen: 1/3/1nk2/1b5/3pp2p1/2p8/2PP3P1p1/1K6P2/3rB6/11/1PRN3N1P1 w - 0 34 + evaluations: 50808 + duration: 1530.6000000238419 + metrics: + wallMs: 1521.8113000155427 + evalsPerMs: 33.386530905297576 + rootMoves: 38 + negamaxNodes: 50752 + quiescenceNodes: 51364 + movegenCalls: 26255 + tacticalMovegenCalls: 16245 + legalContextCalls: 26255 + ttHits: 10117 + ttCutoffs: 8040 + betaCutoffs: 10590 + ttEntries: 49944 + negamaxTtHits: 8487 + quiescenceTtHits: 1630 + negamaxTtCutoffs: 7484 + quiescenceTtCutoffs: 556 + negamaxBetaCutoffs: 4052 + quiescenceBetaCutoffs: 6538 + qsearchStandPatCutoffs: 34563 + qsearchDeltaPruneChecks: 802 + qsearchDeltaPruneSkips: 537 + qsearchNodesWithMoves: 11304 + qsearchGeneratedMoves: 21146 + pvsResearches: 247 + negamaxFrontierFutilityChecks: 39638 + negamaxFrontierFutilitySkips: 5057 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d3g5 + source: pyrustengine + beforeFen: 1/3/1nk2/1b5/3pp2p1/2p8/2PP3P1p1/2K5P2/3rB6/11/1PRN3N1P1 b - 1 34 + evaluations: 147792 + duration: 1233.3999999761581 + metrics: null + - san: k1k3 + source: pyengine2 + beforeFen: 1/3/1nk2/1b5/3pp2p1/2p8/2PP2rP1p1/2K5P2/4B6/11/1PRN3N1P1 w - 2 35 + evaluations: 65236 + duration: 2162 + metrics: + wallMs: 2149.8939000302926 + evalsPerMs: 30.34382301335001 + rootMoves: 40 + negamaxNodes: 72573 + quiescenceNodes: 65798 + movegenCalls: 25926 + tacticalMovegenCalls: 14274 + legalContextCalls: 25926 + ttHits: 13486 + ttCutoffs: 11722 + betaCutoffs: 10520 + ttEntries: 67168 + negamaxTtHits: 12043 + quiescenceTtHits: 1443 + negamaxTtCutoffs: 11160 + quiescenceTtCutoffs: 562 + negamaxBetaCutoffs: 5809 + quiescenceBetaCutoffs: 4711 + qsearchStandPatCutoffs: 50962 + qsearchDeltaPruneChecks: 822 + qsearchDeltaPruneSkips: 679 + qsearchNodesWithMoves: 9697 + qsearchGeneratedMoves: 16746 + pvsResearches: 362 + negamaxFrontierFutilityChecks: 60200 + negamaxFrontierFutilitySkips: 6824 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: e7e6 + source: pyrustengine + beforeFen: 1/3/1nk2/1b5/3pp2p1/2p8/2PP2rP1p1/2K5P2/4B4P1/11/1PRN3N3 b k2 0 35 + evaluations: 330080 + duration: 2951.300000011921 + metrics: null + - san: b1b3 + source: pyengine2 + beforeFen: 1/3/1nk2/1b5/4p2p1/2p1p6/2PP2rP1p1/2K5P2/4B4P1/11/1PRN3N3 w - 0 36 + evaluations: 65723 + duration: 1833.699999988079 + metrics: + wallMs: 1824.710100016091 + evalsPerMs: 36.0183242255416 + rootMoves: 40 + negamaxNodes: 77022 + quiescenceNodes: 66358 + movegenCalls: 19914 + tacticalMovegenCalls: 9283 + legalContextCalls: 19914 + ttHits: 17087 + ttCutoffs: 16549 + betaCutoffs: 6893 + ttEntries: 68655 + negamaxTtHits: 16167 + quiescenceTtHits: 920 + negamaxTtCutoffs: 15914 + quiescenceTtCutoffs: 635 + negamaxBetaCutoffs: 3120 + quiescenceBetaCutoffs: 3773 + qsearchStandPatCutoffs: 56440 + qsearchDeltaPruneChecks: 9 + qsearchDeltaPruneSkips: 8 + qsearchNodesWithMoves: 7413 + qsearchGeneratedMoves: 14949 + pvsResearches: 245 + negamaxFrontierFutilityChecks: 69791 + negamaxFrontierFutilitySkips: 6525 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: e6d5 + source: pyrustengine + beforeFen: 1/3/1nk2/1b5/4p2p1/2p1p6/2PP2rP1p1/2K5P2/1P2B4P1/11/2RN3N3 b - 0 36 + evaluations: 529712 + duration: 5030.300000011921 + metrics: null + - san: c4d5 + source: pyengine2 + beforeFen: 1/3/1nk2/1b5/4p2p1/2p8/2Pp2rP1p1/2K5P2/1P2B4P1/11/2RN3N3 w - 0 37 + evaluations: 13424 + duration: 389.19999998807907 + metrics: + wallMs: 383.4490000153892 + evalsPerMs: 35.00856697881921 + rootMoves: 6 + negamaxNodes: 13764 + quiescenceNodes: 13902 + movegenCalls: 6011 + tacticalMovegenCalls: 3690 + legalContextCalls: 6011 + ttHits: 2852 + ttCutoffs: 2429 + betaCutoffs: 2434 + ttEntries: 13711 + negamaxTtHits: 2162 + quiescenceTtHits: 690 + negamaxTtCutoffs: 1951 + quiescenceTtCutoffs: 478 + negamaxBetaCutoffs: 1193 + quiescenceBetaCutoffs: 1241 + qsearchStandPatCutoffs: 9734 + qsearchDeltaPruneChecks: 252 + qsearchDeltaPruneSkips: 220 + qsearchNodesWithMoves: 2772 + qsearchGeneratedMoves: 4776 + pvsResearches: 101 + negamaxFrontierFutilityChecks: 10533 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d8e7 + source: pyrustengine + beforeFen: 1/3/1nk2/1b5/4p2p1/2p8/2PK2rP1p1/8P2/1P2B4P1/11/2RN3N3 b - 0 37 + evaluations: 266772 + duration: 2783.7000000476837 + metrics: null + - san: d5b4 + source: pyengine2 + beforeFen: 1/3/1nk2/7/3bp2p1/2p8/2PK2rP1p1/8P2/1P2B4P1/11/2RN3N3 w - 1 38 + evaluations: 8018 + duration: 222.89999997615814 + metrics: + wallMs: 217.799499980174 + evalsPerMs: 36.81367496587397 + rootMoves: 4 + negamaxNodes: 9821 + quiescenceNodes: 8058 + movegenCalls: 2555 + tacticalMovegenCalls: 1092 + legalContextCalls: 2555 + ttHits: 1818 + ttCutoffs: 1704 + betaCutoffs: 921 + ttEntries: 8386 + negamaxTtHits: 1736 + quiescenceTtHits: 82 + negamaxTtCutoffs: 1664 + quiescenceTtCutoffs: 40 + negamaxBetaCutoffs: 619 + quiescenceBetaCutoffs: 302 + qsearchStandPatCutoffs: 6926 + qsearchDeltaPruneChecks: 90 + qsearchDeltaPruneSkips: 70 + qsearchNodesWithMoves: 698 + qsearchGeneratedMoves: 930 + pvsResearches: 45 + negamaxFrontierFutilityChecks: 8272 + negamaxFrontierFutilitySkips: 156 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: g5h4 + source: pyrustengine + beforeFen: 1/3/1nk2/7/3bp2p1/2p8/2P3rP1p1/1K6P2/1P2B4P1/11/2RN3N3 b - 2 38 + evaluations: 334219 + duration: 3164 + metrics: null + - san: d1f4 + source: pyengine2 + beforeFen: 1/3/1nk2/7/3bp2p1/2p8/2P4P1p1/1K5rP2/1P2B4P1/11/2RN3N3 w - 3 39 + evaluations: 38410 + duration: 1160.4000000357628 + metrics: + wallMs: 1152.6604000246152 + evalsPerMs: 33.32291106658973 + rootMoves: 37 + negamaxNodes: 48536 + quiescenceNodes: 38732 + movegenCalls: 15590 + tacticalMovegenCalls: 7551 + legalContextCalls: 15590 + ttHits: 12199 + ttCutoffs: 11030 + betaCutoffs: 6038 + ttEntries: 40083 + negamaxTtHits: 11349 + quiescenceTtHits: 850 + negamaxTtCutoffs: 10708 + quiescenceTtCutoffs: 322 + negamaxBetaCutoffs: 3352 + quiescenceBetaCutoffs: 2686 + qsearchStandPatCutoffs: 30859 + qsearchDeltaPruneChecks: 460 + qsearchDeltaPruneSkips: 441 + qsearchNodesWithMoves: 4920 + qsearchGeneratedMoves: 8101 + pvsResearches: 245 + negamaxFrontierFutilityChecks: 54829 + negamaxFrontierFutilitySkips: 19725 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: i7i5 + source: pyrustengine + beforeFen: 1/3/1nk2/7/3bp2p1/2p8/2P4P1p1/1K3N1rP2/1P2B4P1/11/2R4N3 b - 4 39 + evaluations: 349138 + duration: 3405.199999988079 + metrics: null + - san: h5i5 + source: pyengine2 + beforeFen: 1/3/1nk2/7/3bp4/2p8/2P4Ppp1/1K3N1rP2/1P2B4P1/11/2R4N3 w i6 0 40 + evaluations: 65057 + duration: 1813.5 + metrics: + wallMs: 1804.2077000136487 + evalsPerMs: 36.05848705750887 + rootMoves: 44 + negamaxNodes: 72362 + quiescenceNodes: 66012 + movegenCalls: 26113 + tacticalMovegenCalls: 14220 + legalContextCalls: 26113 + ttHits: 18420 + ttCutoffs: 15325 + betaCutoffs: 10076 + ttEntries: 66820 + negamaxTtHits: 15830 + quiescenceTtHits: 2590 + negamaxTtCutoffs: 14370 + quiescenceTtCutoffs: 955 + negamaxBetaCutoffs: 4412 + quiescenceBetaCutoffs: 5664 + qsearchStandPatCutoffs: 50837 + qsearchDeltaPruneChecks: 1955 + qsearchDeltaPruneSkips: 1553 + qsearchNodesWithMoves: 11932 + qsearchGeneratedMoves: 22304 + pvsResearches: 237 + negamaxFrontierFutilityChecks: 61717 + negamaxFrontierFutilitySkips: 8074 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: e7f6 + source: pyrustengine + beforeFen: 1/3/1nk2/7/3bp4/2p8/2P5Pp1/1K3N1rP2/1P2B4P1/11/2R4N3 b - 0 40 + evaluations: 365361 + duration: 3318.699999988079 + metrics: null + - san: b4a5 + source: pyengine2 + beforeFen: 1/3/1nk2/7/4p4/2p2b5/2P5Pp1/1K3N1rP2/1P2B4P1/11/2R4N3 w - 1 41 + evaluations: 11130 + duration: 316.2999999523163 + metrics: + wallMs: 310.2917000069283 + evalsPerMs: 35.869473787895345 + rootMoves: 7 + negamaxNodes: 13264 + quiescenceNodes: 11210 + movegenCalls: 4617 + tacticalMovegenCalls: 2665 + legalContextCalls: 4617 + ttHits: 2873 + ttCutoffs: 2706 + betaCutoffs: 1838 + ttEntries: 10985 + negamaxTtHits: 2715 + quiescenceTtHits: 158 + negamaxTtCutoffs: 2626 + quiescenceTtCutoffs: 80 + negamaxBetaCutoffs: 734 + quiescenceBetaCutoffs: 1104 + qsearchStandPatCutoffs: 8465 + qsearchDeltaPruneChecks: 158 + qsearchDeltaPruneSkips: 118 + qsearchNodesWithMoves: 1570 + qsearchGeneratedMoves: 2274 + pvsResearches: 23 + negamaxFrontierFutilityChecks: 11551 + negamaxFrontierFutilitySkips: 1396 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: k5i5 + source: pyrustengine + beforeFen: 1/3/1nk2/7/4p4/2p2b5/K1P5Pp1/5N1rP2/1P2B4P1/11/2R4N3 b - 2 41 + evaluations: 354709 + duration: 3649.300000011921 + metrics: null + - san: e3i2 + source: pyengine2 + beforeFen: 1/3/1nk2/7/4p4/2p2b5/K1P5p2/5N1rP2/1P2B4P1/11/2R4N3 w - 0 42 + evaluations: 62839 + duration: 1979.3999999761581 + metrics: + wallMs: 1967.750600015279 + evalsPerMs: 31.934433154034906 + rootMoves: 42 + negamaxNodes: 70163 + quiescenceNodes: 64190 + movegenCalls: 31631 + tacticalMovegenCalls: 20454 + legalContextCalls: 31631 + ttHits: 17775 + ttCutoffs: 15675 + betaCutoffs: 13505 + ttEntries: 61766 + negamaxTtHits: 15400 + quiescenceTtHits: 2375 + negamaxTtCutoffs: 14324 + quiescenceTtCutoffs: 1351 + negamaxBetaCutoffs: 5297 + quiescenceBetaCutoffs: 8208 + qsearchStandPatCutoffs: 42385 + qsearchDeltaPruneChecks: 1073 + qsearchDeltaPruneSkips: 861 + qsearchNodesWithMoves: 13501 + qsearchGeneratedMoves: 22554 + pvsResearches: 382 + negamaxFrontierFutilityChecks: 57832 + negamaxFrontierFutilitySkips: 7980 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: h4h6 + source: pyrustengine + beforeFen: 1/3/1nk2/7/4p4/2p2b5/K1P5p2/5N1rP2/1P7P1/8B2/2R4N3 b - 1 42 + evaluations: 286183 + duration: 2640 + metrics: null + - san: i2e9 + source: pyengine2 + beforeFen: 1/3/1nk2/7/4p4/2p2b1r3/K1P5p2/5N2P2/1P7P1/8B2/2R4N3 w - 2 43 + evaluations: 45791 + duration: 1189.300000011921 + metrics: + wallMs: 1181.195100012701 + evalsPerMs: 38.76666945156446 + rootMoves: 39 + negamaxNodes: 57647 + quiescenceNodes: 46163 + movegenCalls: 16475 + tacticalMovegenCalls: 7457 + legalContextCalls: 16475 + ttHits: 13490 + ttCutoffs: 12569 + betaCutoffs: 6009 + ttEntries: 47943 + negamaxTtHits: 12648 + quiescenceTtHits: 842 + negamaxTtCutoffs: 12195 + quiescenceTtCutoffs: 374 + negamaxBetaCutoffs: 3293 + quiescenceBetaCutoffs: 2716 + qsearchStandPatCutoffs: 38332 + qsearchDeltaPruneChecks: 882 + qsearchDeltaPruneSkips: 717 + qsearchNodesWithMoves: 5225 + qsearchGeneratedMoves: 9014 + pvsResearches: 148 + negamaxFrontierFutilityChecks: 52423 + negamaxFrontierFutilitySkips: 6197 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: f9e9 + source: pyrustengine + beforeFen: 1/3/1Bk2/7/4p4/2p2b1r3/K1P5p2/5N2P2/1P7P1/11/2R4N3 b - 0 43 + evaluations: 207206 + duration: 1748.300000011921 + metrics: null + - san: a5c6 + source: pyengine2 + beforeFen: 1/3/1k3/7/4p4/2p2b1r3/K1P5p2/5N2P2/1P7P1/11/2R4N3 w - 0 44 + evaluations: 38376 + duration: 1109.5 + metrics: + wallMs: 1101.6321999486536 + evalsPerMs: 34.83558305738402 + rootMoves: 33 + negamaxNodes: 50135 + quiescenceNodes: 38892 + movegenCalls: 18060 + tacticalMovegenCalls: 8110 + legalContextCalls: 18060 + ttHits: 14318 + ttCutoffs: 12976 + betaCutoffs: 6099 + ttEntries: 39529 + negamaxTtHits: 13187 + quiescenceTtHits: 1131 + negamaxTtCutoffs: 12459 + quiescenceTtCutoffs: 517 + negamaxBetaCutoffs: 3371 + quiescenceBetaCutoffs: 2728 + qsearchStandPatCutoffs: 30265 + qsearchDeltaPruneChecks: 489 + qsearchDeltaPruneSkips: 392 + qsearchNodesWithMoves: 5321 + qsearchGeneratedMoves: 8382 + pvsResearches: 246 + negamaxFrontierFutilityChecks: 41778 + negamaxFrontierFutilitySkips: 2814 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: h6e8 + source: pyrustengine + beforeFen: 1/3/1k3/7/4p4/2K2b1r3/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 0 44 + evaluations: 138292 + duration: 1406.5 + metrics: null + - san: c6c7 + source: pyengine2 + beforeFen: 1/3/1k3/2r4/4p4/2K2b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 1 45 + evaluations: 4989 + duration: 211.19999998807907 + metrics: + wallMs: 205.30030003283173 + evalsPerMs: 24.30098737898657 + rootMoves: 5 + negamaxNodes: 6971 + quiescenceNodes: 5012 + movegenCalls: 1933 + tacticalMovegenCalls: 751 + legalContextCalls: 1933 + ttHits: 1765 + ttCutoffs: 1726 + betaCutoffs: 654 + ttEntries: 5152 + negamaxTtHits: 1737 + quiescenceTtHits: 28 + negamaxTtCutoffs: 1702 + quiescenceTtCutoffs: 24 + negamaxBetaCutoffs: 405 + quiescenceBetaCutoffs: 249 + qsearchStandPatCutoffs: 4237 + qsearchDeltaPruneChecks: 0 + qsearchDeltaPruneSkips: 0 + qsearchNodesWithMoves: 340 + qsearchGeneratedMoves: 442 + pvsResearches: 16 + negamaxFrontierFutilityChecks: 5843 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: e8d7 + source: pyrustengine + beforeFen: 1/3/1k3/2r4/1K2p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 2 45 + evaluations: 159347 + duration: 1394.5999999642372 + metrics: null + - san: c7a6 + source: pyengine2 + beforeFen: 1/3/1k3/7/1Kr1p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 3 46 + evaluations: 2619 + duration: 63.5 + metrics: + wallMs: 58.377599983941764 + evalsPerMs: 44.86309818698306 + rootMoves: 2 + negamaxNodes: 3187 + quiescenceNodes: 2629 + movegenCalls: 1117 + tacticalMovegenCalls: 574 + legalContextCalls: 1117 + ttHits: 565 + ttCutoffs: 548 + betaCutoffs: 421 + ttEntries: 2600 + negamaxTtHits: 552 + quiescenceTtHits: 13 + negamaxTtCutoffs: 538 + quiescenceTtCutoffs: 10 + negamaxBetaCutoffs: 215 + quiescenceBetaCutoffs: 206 + qsearchStandPatCutoffs: 2045 + qsearchDeltaPruneChecks: 0 + qsearchDeltaPruneSkips: 0 + qsearchNodesWithMoves: 267 + qsearchGeneratedMoves: 311 + pvsResearches: 15 + negamaxFrontierFutilityChecks: 2616 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d7d9 + source: pyrustengine + beforeFen: 1/3/1k3/7/2r1p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 4 46 + evaluations: 138774 + duration: 1351.9000000357628 + metrics: null + - san: a6c7 + source: pyengine2 + beforeFen: 1/3/rk3/7/4p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 5 47 + evaluations: 4244 + duration: 172.19999998807907 + metrics: + wallMs: 166.7324000154622 + evalsPerMs: 25.453960955437733 + rootMoves: 4 + negamaxNodes: 5688 + quiescenceNodes: 4262 + movegenCalls: 2282 + tacticalMovegenCalls: 1093 + legalContextCalls: 2282 + ttHits: 1357 + ttCutoffs: 1231 + betaCutoffs: 825 + ttEntries: 4237 + negamaxTtHits: 1280 + quiescenceTtHits: 77 + negamaxTtCutoffs: 1213 + quiescenceTtCutoffs: 18 + negamaxBetaCutoffs: 520 + quiescenceBetaCutoffs: 305 + qsearchStandPatCutoffs: 3151 + qsearchDeltaPruneChecks: 37 + qsearchDeltaPruneSkips: 28 + qsearchNodesWithMoves: 472 + qsearchGeneratedMoves: 596 + pvsResearches: 50 + negamaxFrontierFutilityChecks: 4309 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d9d7 + source: pyrustengine + beforeFen: 1/3/rk3/7/1K2p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 6 47 + evaluations: 77524 + duration: 661 + metrics: null + - san: c7a6 + source: pyengine2 + beforeFen: 1/3/1k3/7/1Kr1p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 7 48 + evaluations: 2619 + duration: 88.89999997615814 + metrics: + wallMs: 82.37930003087968 + evalsPerMs: 31.791967144880743 + rootMoves: 2 + negamaxNodes: 3187 + quiescenceNodes: 2629 + movegenCalls: 1117 + tacticalMovegenCalls: 574 + legalContextCalls: 1117 + ttHits: 565 + ttCutoffs: 548 + betaCutoffs: 421 + ttEntries: 2600 + negamaxTtHits: 552 + quiescenceTtHits: 13 + negamaxTtCutoffs: 538 + quiescenceTtCutoffs: 10 + negamaxBetaCutoffs: 215 + quiescenceBetaCutoffs: 206 + qsearchStandPatCutoffs: 2045 + qsearchDeltaPruneChecks: 0 + qsearchDeltaPruneSkips: 0 + qsearchNodesWithMoves: 267 + qsearchGeneratedMoves: 311 + pvsResearches: 15 + negamaxFrontierFutilityChecks: 2616 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d7d9 + source: pyrustengine + beforeFen: 1/3/1k3/7/2r1p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 8 48 + evaluations: 138774 + duration: 1144.800000011921 + metrics: null + - san: a6c7 + source: pyengine2 + beforeFen: 1/3/rk3/7/4p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 9 49 + evaluations: 4244 + duration: 147.60000002384186 + metrics: + wallMs: 141.95509999990463 + evalsPerMs: 29.896777220422873 + rootMoves: 4 + negamaxNodes: 5688 + quiescenceNodes: 4262 + movegenCalls: 2282 + tacticalMovegenCalls: 1093 + legalContextCalls: 2282 + ttHits: 1357 + ttCutoffs: 1231 + betaCutoffs: 825 + ttEntries: 4237 + negamaxTtHits: 1280 + quiescenceTtHits: 77 + negamaxTtCutoffs: 1213 + quiescenceTtCutoffs: 18 + negamaxBetaCutoffs: 520 + quiescenceBetaCutoffs: 305 + qsearchStandPatCutoffs: 3151 + qsearchDeltaPruneChecks: 37 + qsearchDeltaPruneSkips: 28 + qsearchNodesWithMoves: 472 + qsearchGeneratedMoves: 596 + pvsResearches: 50 + negamaxFrontierFutilityChecks: 4309 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d9d7 + source: pyrustengine + beforeFen: 1/3/rk3/7/1K2p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 10 49 + evaluations: 77524 + duration: 616.1999999880791 + metrics: null + - san: c7a6 + source: pyengine2 + beforeFen: 1/3/1k3/7/1Kr1p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 11 50 + evaluations: 2619 + duration: 69.5 + metrics: + wallMs: 63.79739998374134 + evalsPerMs: 41.05182970885095 + rootMoves: 2 + negamaxNodes: 3187 + quiescenceNodes: 2629 + movegenCalls: 1117 + tacticalMovegenCalls: 574 + legalContextCalls: 1117 + ttHits: 565 + ttCutoffs: 548 + betaCutoffs: 421 + ttEntries: 2600 + negamaxTtHits: 552 + quiescenceTtHits: 13 + negamaxTtCutoffs: 538 + quiescenceTtCutoffs: 10 + negamaxBetaCutoffs: 215 + quiescenceBetaCutoffs: 206 + qsearchStandPatCutoffs: 2045 + qsearchDeltaPruneChecks: 0 + qsearchDeltaPruneSkips: 0 + qsearchNodesWithMoves: 267 + qsearchGeneratedMoves: 311 + pvsResearches: 15 + negamaxFrontierFutilityChecks: 2616 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d7d9 + source: pyrustengine + beforeFen: 1/3/1k3/7/2r1p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 12 50 + evaluations: 138774 + duration: 1397.300000011921 + metrics: null + - san: a6c7 + source: pyengine2 + beforeFen: 1/3/rk3/7/4p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 13 51 + evaluations: 4244 + duration: 108.5 + metrics: + wallMs: 103.55090000666678 + evalsPerMs: 40.98467516677078 + rootMoves: 4 + negamaxNodes: 5688 + quiescenceNodes: 4262 + movegenCalls: 2282 + tacticalMovegenCalls: 1093 + legalContextCalls: 2282 + ttHits: 1357 + ttCutoffs: 1231 + betaCutoffs: 825 + ttEntries: 4237 + negamaxTtHits: 1280 + quiescenceTtHits: 77 + negamaxTtCutoffs: 1213 + quiescenceTtCutoffs: 18 + negamaxBetaCutoffs: 520 + quiescenceBetaCutoffs: 305 + qsearchStandPatCutoffs: 3151 + qsearchDeltaPruneChecks: 37 + qsearchDeltaPruneSkips: 28 + qsearchNodesWithMoves: 472 + qsearchGeneratedMoves: 596 + pvsResearches: 50 + negamaxFrontierFutilityChecks: 4309 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d9d7 + source: pyrustengine + beforeFen: 1/3/rk3/7/1K2p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 14 51 + evaluations: 77524 + duration: 631.1999999880791 + metrics: null + - san: c7a6 + source: pyengine2 + beforeFen: 1/3/1k3/7/1Kr1p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 15 52 + evaluations: 2619 + duration: 63.30000001192093 + metrics: + wallMs: 57.58289998630062 + evalsPerMs: 45.48225255454447 + rootMoves: 2 + negamaxNodes: 3187 + quiescenceNodes: 2629 + movegenCalls: 1117 + tacticalMovegenCalls: 574 + legalContextCalls: 1117 + ttHits: 565 + ttCutoffs: 548 + betaCutoffs: 421 + ttEntries: 2600 + negamaxTtHits: 552 + quiescenceTtHits: 13 + negamaxTtCutoffs: 538 + quiescenceTtCutoffs: 10 + negamaxBetaCutoffs: 215 + quiescenceBetaCutoffs: 206 + qsearchStandPatCutoffs: 2045 + qsearchDeltaPruneChecks: 0 + qsearchDeltaPruneSkips: 0 + qsearchNodesWithMoves: 267 + qsearchGeneratedMoves: 311 + pvsResearches: 15 + negamaxFrontierFutilityChecks: 2616 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d7d9 + source: pyrustengine + beforeFen: 1/3/1k3/7/2r1p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 16 52 + evaluations: 138774 + duration: 1281.2000000476837 + metrics: null + - san: a6c7 + source: pyengine2 + beforeFen: 1/3/rk3/7/4p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 17 53 + evaluations: 4244 + duration: 130.60000002384186 + metrics: + wallMs: 125.13800000306219 + evalsPerMs: 33.914558326776415 + rootMoves: 4 + negamaxNodes: 5688 + quiescenceNodes: 4262 + movegenCalls: 2282 + tacticalMovegenCalls: 1093 + legalContextCalls: 2282 + ttHits: 1357 + ttCutoffs: 1231 + betaCutoffs: 825 + ttEntries: 4237 + negamaxTtHits: 1280 + quiescenceTtHits: 77 + negamaxTtCutoffs: 1213 + quiescenceTtCutoffs: 18 + negamaxBetaCutoffs: 520 + quiescenceBetaCutoffs: 305 + qsearchStandPatCutoffs: 3151 + qsearchDeltaPruneChecks: 37 + qsearchDeltaPruneSkips: 28 + qsearchNodesWithMoves: 472 + qsearchGeneratedMoves: 596 + pvsResearches: 50 + negamaxFrontierFutilityChecks: 4309 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d9d7 + source: pyrustengine + beforeFen: 1/3/rk3/7/1K2p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 18 53 + evaluations: 77524 + duration: 708.3000000119209 + metrics: null + - san: c7a6 + source: pyengine2 + beforeFen: 1/3/1k3/7/1Kr1p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 19 54 + evaluations: 2619 + duration: 67.69999998807907 + metrics: + wallMs: 60.77829998685047 + evalsPerMs: 43.0910374355095 + rootMoves: 2 + negamaxNodes: 3187 + quiescenceNodes: 2629 + movegenCalls: 1117 + tacticalMovegenCalls: 574 + legalContextCalls: 1117 + ttHits: 565 + ttCutoffs: 548 + betaCutoffs: 421 + ttEntries: 2600 + negamaxTtHits: 552 + quiescenceTtHits: 13 + negamaxTtCutoffs: 538 + quiescenceTtCutoffs: 10 + negamaxBetaCutoffs: 215 + quiescenceBetaCutoffs: 206 + qsearchStandPatCutoffs: 2045 + qsearchDeltaPruneChecks: 0 + qsearchDeltaPruneSkips: 0 + qsearchNodesWithMoves: 267 + qsearchGeneratedMoves: 311 + pvsResearches: 15 + negamaxFrontierFutilityChecks: 2616 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d7d9 + source: pyrustengine + beforeFen: 1/3/1k3/7/2r1p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 20 54 + evaluations: 138774 + duration: 1245.0999999642372 + metrics: null + - san: a6c7 + source: pyengine2 + beforeFen: 1/3/rk3/7/4p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 21 55 + evaluations: 4244 + duration: 182.5 + metrics: + wallMs: 177.75309999706224 + evalsPerMs: 23.87581426186177 + rootMoves: 4 + negamaxNodes: 5688 + quiescenceNodes: 4262 + movegenCalls: 2282 + tacticalMovegenCalls: 1093 + legalContextCalls: 2282 + ttHits: 1357 + ttCutoffs: 1231 + betaCutoffs: 825 + ttEntries: 4237 + negamaxTtHits: 1280 + quiescenceTtHits: 77 + negamaxTtCutoffs: 1213 + quiescenceTtCutoffs: 18 + negamaxBetaCutoffs: 520 + quiescenceBetaCutoffs: 305 + qsearchStandPatCutoffs: 3151 + qsearchDeltaPruneChecks: 37 + qsearchDeltaPruneSkips: 28 + qsearchNodesWithMoves: 472 + qsearchGeneratedMoves: 596 + pvsResearches: 50 + negamaxFrontierFutilityChecks: 4309 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d9d7 + source: pyrustengine + beforeFen: 1/3/rk3/7/1K2p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 22 55 + evaluations: 77524 + duration: 730.3000000119209 + metrics: null + - san: c7a6 + source: pyengine2 + beforeFen: 1/3/1k3/7/1Kr1p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 23 56 + evaluations: 2619 + duration: 108.5 + metrics: + wallMs: 103.27399999368936 + evalsPerMs: 25.359722681023648 + rootMoves: 2 + negamaxNodes: 3187 + quiescenceNodes: 2629 + movegenCalls: 1117 + tacticalMovegenCalls: 574 + legalContextCalls: 1117 + ttHits: 565 + ttCutoffs: 548 + betaCutoffs: 421 + ttEntries: 2600 + negamaxTtHits: 552 + quiescenceTtHits: 13 + negamaxTtCutoffs: 538 + quiescenceTtCutoffs: 10 + negamaxBetaCutoffs: 215 + quiescenceBetaCutoffs: 206 + qsearchStandPatCutoffs: 2045 + qsearchDeltaPruneChecks: 0 + qsearchDeltaPruneSkips: 0 + qsearchNodesWithMoves: 267 + qsearchGeneratedMoves: 311 + pvsResearches: 15 + negamaxFrontierFutilityChecks: 2616 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d7d9 + source: pyrustengine + beforeFen: 1/3/1k3/7/2r1p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 24 56 + evaluations: 138774 + duration: 1224.800000011921 + metrics: null + - san: a6c7 + source: pyengine2 + beforeFen: 1/3/rk3/7/4p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 25 57 + evaluations: 4244 + duration: 111.39999997615814 + metrics: + wallMs: 106.20169999310747 + evalsPerMs: 39.961695531007855 + rootMoves: 4 + negamaxNodes: 5688 + quiescenceNodes: 4262 + movegenCalls: 2282 + tacticalMovegenCalls: 1093 + legalContextCalls: 2282 + ttHits: 1357 + ttCutoffs: 1231 + betaCutoffs: 825 + ttEntries: 4237 + negamaxTtHits: 1280 + quiescenceTtHits: 77 + negamaxTtCutoffs: 1213 + quiescenceTtCutoffs: 18 + negamaxBetaCutoffs: 520 + quiescenceBetaCutoffs: 305 + qsearchStandPatCutoffs: 3151 + qsearchDeltaPruneChecks: 37 + qsearchDeltaPruneSkips: 28 + qsearchNodesWithMoves: 472 + qsearchGeneratedMoves: 596 + pvsResearches: 50 + negamaxFrontierFutilityChecks: 4309 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d9d7 + source: pyrustengine + beforeFen: 1/3/rk3/7/1K2p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 26 57 + evaluations: 77524 + duration: 678.8999999761581 + metrics: null + - san: c7a6 + source: pyengine2 + beforeFen: 1/3/1k3/7/1Kr1p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 27 58 + evaluations: 2619 + duration: 63.39999997615814 + metrics: + wallMs: 57.90140002500266 + evalsPerMs: 45.232066908038114 + rootMoves: 2 + negamaxNodes: 3187 + quiescenceNodes: 2629 + movegenCalls: 1117 + tacticalMovegenCalls: 574 + legalContextCalls: 1117 + ttHits: 565 + ttCutoffs: 548 + betaCutoffs: 421 + ttEntries: 2600 + negamaxTtHits: 552 + quiescenceTtHits: 13 + negamaxTtCutoffs: 538 + quiescenceTtCutoffs: 10 + negamaxBetaCutoffs: 215 + quiescenceBetaCutoffs: 206 + qsearchStandPatCutoffs: 2045 + qsearchDeltaPruneChecks: 0 + qsearchDeltaPruneSkips: 0 + qsearchNodesWithMoves: 267 + qsearchGeneratedMoves: 311 + pvsResearches: 15 + negamaxFrontierFutilityChecks: 2616 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d7d9 + source: pyrustengine + beforeFen: 1/3/1k3/7/2r1p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 28 58 + evaluations: 138774 + duration: 1198.300000011921 + metrics: null + - san: a6c7 + source: pyengine2 + beforeFen: 1/3/rk3/7/4p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 29 59 + evaluations: 4244 + duration: 142.19999998807907 + metrics: + wallMs: 136.79159997263923 + evalsPerMs: 31.025296881159925 + rootMoves: 4 + negamaxNodes: 5688 + quiescenceNodes: 4262 + movegenCalls: 2282 + tacticalMovegenCalls: 1093 + legalContextCalls: 2282 + ttHits: 1357 + ttCutoffs: 1231 + betaCutoffs: 825 + ttEntries: 4237 + negamaxTtHits: 1280 + quiescenceTtHits: 77 + negamaxTtCutoffs: 1213 + quiescenceTtCutoffs: 18 + negamaxBetaCutoffs: 520 + quiescenceBetaCutoffs: 305 + qsearchStandPatCutoffs: 3151 + qsearchDeltaPruneChecks: 37 + qsearchDeltaPruneSkips: 28 + qsearchNodesWithMoves: 472 + qsearchGeneratedMoves: 596 + pvsResearches: 50 + negamaxFrontierFutilityChecks: 4309 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d9d7 + source: pyrustengine + beforeFen: 1/3/rk3/7/1K2p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 30 59 + evaluations: 77524 + duration: 732.3999999761581 + metrics: null + - san: c7a6 + source: pyengine2 + beforeFen: 1/3/1k3/7/1Kr1p4/5b5/2P5p2/5N2P2/1P7P1/11/2R4N3 w - 31 60 + evaluations: 2619 + duration: 78.69999998807907 + metrics: + wallMs: 72.98930000979453 + evalsPerMs: 35.88197173624837 + rootMoves: 2 + negamaxNodes: 3187 + quiescenceNodes: 2629 + movegenCalls: 1117 + tacticalMovegenCalls: 574 + legalContextCalls: 1117 + ttHits: 565 + ttCutoffs: 548 + betaCutoffs: 421 + ttEntries: 2600 + negamaxTtHits: 552 + quiescenceTtHits: 13 + negamaxTtCutoffs: 538 + quiescenceTtCutoffs: 10 + negamaxBetaCutoffs: 215 + quiescenceBetaCutoffs: 206 + qsearchStandPatCutoffs: 2045 + qsearchDeltaPruneChecks: 0 + qsearchDeltaPruneSkips: 0 + qsearchNodesWithMoves: 267 + qsearchGeneratedMoves: 311 + pvsResearches: 15 + negamaxFrontierFutilityChecks: 2616 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - san: d7d9 + source: pyrustengine + beforeFen: 1/3/1k3/7/2r1p4/K4b5/2P5p2/5N2P2/1P7P1/11/2R4N3 b - 32 60 + evaluations: 138774 + duration: 1337.5 + metrics: null +evaluation: + depth: 4 + evaluations: 138774 + sans: + - san: d7d9 + score: 51.36000061035156 + - san: d7c6 + score: 51.36000061035156 + - san: d7a4 + score: 51.36000061035156 + - san: d7d3 + score: 51.76000213623047 + - san: e9f11 + score: 51.91999816894531 + - san: e9e10 + score: 51.91999816894531 + - san: e9f10 + score: 51.91999816894531 + - san: e9f9 + score: 51.91999816894531 + - san: e9g9 + score: 51.91999816894531 + - san: e9c8 + score: 51.91999816894531 + - san: e9d8 + score: 51.91999816894531 + - san: e9e8 + score: 51.91999816894531 + - san: e9f8 + score: 51.91999816894531 + - san: d7d8 + score: 51.91999816894531 + - san: d7e8 + score: 51.91999816894531 + - san: d7f9 + score: 51.91999816894531 + - san: d7g9 + score: 51.91999816894531 + - san: d7h9 + score: 51.91999816894531 + - san: d7d4 + score: 51.91999816894531 + - san: d7d2 + score: 51.91999816894531 + - san: f6g7 + score: 51.91999816894531 + - san: f6h8 + score: 51.91999816894531 + - san: f6e4 + score: 51.91999816894531 + - san: f6d2 + score: 51.91999816894531 + - san: f6b4 + score: 51.91999816894531 + - san: f6e7 + score: 51.91999816894531 + - san: f6d8 + score: 51.91999816894531 + - san: e9d9 + score: 52.31999969482422 + - san: d7e7 + score: 61.68000030517578 + - san: f6h2 + score: 80.36000061035156 + - san: f6d5 + score: 80.36000061035156 + - san: f6h5 + score: 81.36000061035156 + - san: f6g4 + score: 81.36000061035156 + - san: f6k4 + score: 81.76000213623047 + - san: d7d5 + score: 100.36000061035156 + - san: d7b7 + score: 101.36000061035156 + - san: d7d6 + score: 101.76000213623047 + - san: d7d1 + score: 101.91999816894531 + - san: d7c7 + score: 101.91999816894531 + - san: d7b5 + score: 102.63999938964844 diff --git a/results/2.1.003/hexchess-game-20260326-173542.yaml b/results/2.1.003/hexchess-game-20260326-173542.yaml new file mode 100644 index 00000000..03965391 --- /dev/null +++ b/results/2.1.003/hexchess-game-20260326-173542.yaml @@ -0,0 +1,1485 @@ +version: 1 +startFen: b/qbk/n1b1n/r5r/ppppppppp/11/5P5/4P1P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 1 +historyIndex: 196 +moves: + - san: e4e5 + beforeFen: b/qbk/n1b1n/r5r/ppppppppp/11/5P5/4P1P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 1 + source: manual + evaluations: null + duration: null + metrics: null + - san: h7h5 + beforeFen: b/qbk/n1b1n/r5r/ppppppppp/11/4PP5/6P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 b - 0 1 + source: python-api + evaluations: 812429 + duration: 51946.90000009537 + metrics: + wallMs: 51733.60650008544 + evalsPerMs: 15.704085892381352 + rootMoves: 50 + negamaxNodes: 511658 + quiescenceNodes: 860918 + movegenCalls: 817363 + tacticalMovegenCalls: 445280 + legalContextCalls: 817363 + ttHits: 201885 + ttCutoffs: 186242 + betaCutoffs: 267192 + ttEntries: 830673 + negamaxTtHits: 146314 + quiescenceTtHits: 55571 + negamaxTtCutoffs: 137753 + quiescenceTtCutoffs: 48489 + negamaxBetaCutoffs: 86255 + quiescenceBetaCutoffs: 180937 + qsearchStandPatCutoffs: 367149 + qsearchDeltaPruneChecks: 52268 + qsearchDeltaPruneSkips: 45320 + qsearchNodesWithMoves: 378048 + qsearchGeneratedMoves: 976535 + pvsResearches: 2420 + negamaxFrontierFutilityChecks: 322309 + negamaxFrontierFutilitySkips: 30807 + nullMoveAttempts: 2367 + nullMoveCutoffs: 1823 + - san: g4g5 + beforeFen: b/qbk/n1b1n/r5r/pppppp1pp/11/4PP1p3/6P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w + h6 0 2 + source: rust-worker + evaluations: 1151515 + duration: 19922.700000286102 + metrics: null + - san: h5g5 + beforeFen: b/qbk/n1b1n/r5r/pppppp1pp/11/4PPPp3/11/3P1B1P3/2P2B2P2/1PRNQBKNRP1 b - 0 2 + source: python-api + evaluations: 1193536 + duration: 68719.69999980927 + metrics: + wallMs: 68608.35150023922 + evalsPerMs: 17.39636609685686 + rootMoves: 53 + negamaxNodes: 582330 + quiescenceNodes: 1302178 + movegenCalls: 970878 + tacticalMovegenCalls: 514609 + legalContextCalls: 970878 + ttHits: 246333 + ttCutoffs: 234147 + betaCutoffs: 341982 + ttEntries: 1311912 + negamaxTtHits: 130306 + quiescenceTtHits: 116027 + negamaxTtCutoffs: 125505 + quiescenceTtCutoffs: 108642 + negamaxBetaCutoffs: 163776 + quiescenceBetaCutoffs: 178206 + qsearchStandPatCutoffs: 678927 + qsearchDeltaPruneChecks: 148590 + qsearchDeltaPruneSkips: 142984 + qsearchNodesWithMoves: 470874 + qsearchGeneratedMoves: 1573666 + pvsResearches: 1347 + negamaxFrontierFutilityChecks: 180938 + negamaxFrontierFutilitySkips: 14112 + nullMoveAttempts: 3461 + nullMoveCutoffs: 557 + - san: f5g5 + beforeFen: b/qbk/n1b1n/r5r/pppppp1pp/11/4PPp4/11/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 3 + source: rust-worker + evaluations: 1100069 + duration: 20464.300000190735 + metrics: null + - san: i7i5 + beforeFen: b/qbk/n1b1n/r5r/pppppp1pp/11/4P1P4/11/3P1B1P3/2P2B2P2/1PRNQBKNRP1 b - 0 3 + source: python-api + evaluations: 1536362 + duration: 86903.80000019073 + metrics: + wallMs: 86759.17540024966 + evalsPerMs: 17.70835180154996 + rootMoves: 52 + negamaxNodes: 657672 + quiescenceNodes: 1667430 + movegenCalls: 1357215 + tacticalMovegenCalls: 841319 + legalContextCalls: 1357215 + ttHits: 292647 + ttCutoffs: 270855 + betaCutoffs: 487292 + ttEntries: 1574207 + negamaxTtHits: 149073 + quiescenceTtHits: 143574 + negamaxTtCutoffs: 139787 + quiescenceTtCutoffs: 131068 + negamaxBetaCutoffs: 124568 + quiescenceBetaCutoffs: 362724 + qsearchStandPatCutoffs: 695043 + qsearchDeltaPruneChecks: 137735 + qsearchDeltaPruneSkips: 127107 + qsearchNodesWithMoves: 757768 + qsearchGeneratedMoves: 2303961 + pvsResearches: 4013 + negamaxFrontierFutilityChecks: 386799 + negamaxFrontierFutilitySkips: 53288 + nullMoveAttempts: 2875 + nullMoveCutoffs: 1990 + - san: f2e3 + beforeFen: b/qbk/n1b1n/r5r/pppppp2p/11/4P1P1p2/11/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w i6 0 4 + source: rust-worker + evaluations: 1332355 + duration: 25393.700000286102 + metrics: null + - san: i8i7 + beforeFen: b/qbk/n1b1n/r5r/pppppp2p/11/4P1P1p2/11/3PBB1P3/2P5P2/1PRNQBKNRP1 b - 1 4 + source: python-api + evaluations: 751614 + duration: 44108.90000009537 + metrics: + wallMs: 44015.71650011465 + evalsPerMs: 17.0760369196317 + rootMoves: 50 + negamaxNodes: 326960 + quiescenceNodes: 796270 + movegenCalls: 686249 + tacticalMovegenCalls: 412546 + legalContextCalls: 686249 + ttHits: 117662 + ttCutoffs: 95910 + betaCutoffs: 245900 + ttEntries: 779833 + negamaxTtHits: 59602 + quiescenceTtHits: 58060 + negamaxTtCutoffs: 51254 + quiescenceTtCutoffs: 44656 + negamaxBetaCutoffs: 88507 + quiescenceBetaCutoffs: 157393 + qsearchStandPatCutoffs: 339068 + qsearchDeltaPruneChecks: 120262 + qsearchDeltaPruneSkips: 106966 + qsearchNodesWithMoves: 363730 + qsearchGeneratedMoves: 1015300 + pvsResearches: 1978 + negamaxFrontierFutilityChecks: 131752 + negamaxFrontierFutilitySkips: 18477 + nullMoveAttempts: 3095 + nullMoveCutoffs: 2004 + - san: i2i3 + beforeFen: b/qbk/n1b1n/r6/pppppp1rp/11/4P1P1p2/11/3PBB1P3/2P5P2/1PRNQBKNRP1 w - 2 5 + source: rust-worker + evaluations: 1380058 + duration: 26019.299999713898 + metrics: null + - san: d9f8 + beforeFen: b/qbk/n1b1n/r6/pppppp1rp/11/4P1P1p2/11/3PBB1PP2/2P8/1PRNQBKNRP1 b - 0 5 + source: python-api + evaluations: 1269837 + duration: 80893.59999990463 + metrics: + wallMs: 80763.27499980107 + evalsPerMs: 15.722950809054336 + rootMoves: 52 + negamaxNodes: 626166 + quiescenceNodes: 1376508 + movegenCalls: 1285171 + tacticalMovegenCalls: 766148 + legalContextCalls: 1285171 + ttHits: 230198 + ttCutoffs: 212553 + betaCutoffs: 459865 + ttEntries: 1307978 + negamaxTtHits: 114329 + quiescenceTtHits: 115869 + negamaxTtCutoffs: 105882 + quiescenceTtCutoffs: 106671 + negamaxBetaCutoffs: 154363 + quiescenceBetaCutoffs: 305502 + qsearchStandPatCutoffs: 503689 + qsearchDeltaPruneChecks: 106396 + qsearchDeltaPruneSkips: 96551 + qsearchNodesWithMoves: 650556 + qsearchGeneratedMoves: 1710814 + pvsResearches: 3931 + negamaxFrontierFutilityChecks: 268022 + negamaxFrontierFutilitySkips: 44941 + nullMoveAttempts: 1986 + nullMoveCutoffs: 1262 + - san: d3d5 + beforeFen: b/qbk/2b1n/r2n3/pppppp1rp/11/4P1P1p2/11/3PBB1PP2/2P8/1PRNQBKNRP1 w - 1 6 + source: rust-worker + evaluations: 2427951 + duration: 47964 + metrics: null + - san: f8e5 + beforeFen: b/qbk/2b1n/r2n3/pppppp1rp/11/3PP1P1p2/11/4BB1PP2/2P8/1PRNQBKNRP1 b d4 0 6 + source: python-api + evaluations: 2166186 + duration: 106928.80000019073 + metrics: + wallMs: 106783.53489981964 + evalsPerMs: 20.285767857678017 + rootMoves: 55 + negamaxNodes: 845527 + quiescenceNodes: 2326002 + movegenCalls: 1969314 + tacticalMovegenCalls: 1273129 + legalContextCalls: 1969314 + ttHits: 364240 + ttCutoffs: 307932 + betaCutoffs: 746429 + ttEntries: 2219354 + negamaxTtHits: 171757 + quiescenceTtHits: 192483 + negamaxTtCutoffs: 148116 + quiescenceTtCutoffs: 159816 + negamaxBetaCutoffs: 204223 + quiescenceBetaCutoffs: 542206 + qsearchStandPatCutoffs: 893057 + qsearchDeltaPruneChecks: 214882 + qsearchDeltaPruneSkips: 207002 + qsearchNodesWithMoves: 1149970 + qsearchGeneratedMoves: 3564995 + pvsResearches: 5016 + negamaxFrontierFutilityChecks: 313097 + negamaxFrontierFutilitySkips: 37125 + nullMoveAttempts: 1641 + nullMoveCutoffs: 1227 + - san: e3f5 + beforeFen: b/qbk/2b1n/r6/pppppp1rp/11/3Pn1P1p2/11/4BB1PP2/2P8/1PRNQBKNRP1 w - 0 7 + source: rust-worker + evaluations: 3674774 + duration: 74787.5 + metrics: null + - san: e5f3 + beforeFen: b/qbk/2b1n/r6/pppppp1rp/11/3PnBP1p2/11/5B1PP2/2P8/1PRNQBKNRP1 b - 1 7 + source: python-api + evaluations: 770593 + duration: 51310.5 + metrics: + wallMs: 51254.43409988657 + evalsPerMs: 15.034660191511225 + rootMoves: 59 + negamaxNodes: 645158 + quiescenceNodes: 800708 + movegenCalls: 929794 + tacticalMovegenCalls: 400050 + legalContextCalls: 929794 + ttHits: 156742 + ttCutoffs: 143844 + betaCutoffs: 307861 + ttEntries: 953865 + negamaxTtHits: 119770 + quiescenceTtHits: 36972 + negamaxTtCutoffs: 113729 + quiescenceTtCutoffs: 30115 + negamaxBetaCutoffs: 205283 + quiescenceBetaCutoffs: 102578 + qsearchStandPatCutoffs: 370543 + qsearchDeltaPruneChecks: 632379 + qsearchDeltaPruneSkips: 624832 + qsearchNodesWithMoves: 379443 + qsearchGeneratedMoves: 1368584 + pvsResearches: 1554 + negamaxFrontierFutilityChecks: 201147 + negamaxFrontierFutilitySkips: 35161 + nullMoveAttempts: 4197 + nullMoveCutoffs: 1686 + - san: g1f3 + beforeFen: b/qbk/2b1n/r6/pppppp1rp/11/3P1BP1p2/11/5n1PP2/2P8/1PRNQBKNRP1 w - 0 8 + source: rust-worker + evaluations: 5502204 + duration: 113234.40000009537 + metrics: null + - san: h9f8 + beforeFen: b/qbk/2b1n/r6/pppppp1rp/11/3P1BP1p2/11/5K1PP2/2P8/1PRNQB1NRP1 b - 0 8 + source: python-api + evaluations: 1994610 + duration: 91005.69999980927 + metrics: + wallMs: 90886.82439969853 + evalsPerMs: 21.94608528985656 + rootMoves: 50 + negamaxNodes: 784073 + quiescenceNodes: 2149396 + movegenCalls: 1701795 + tacticalMovegenCalls: 1079341 + legalContextCalls: 1701795 + ttHits: 354198 + ttCutoffs: 314164 + betaCutoffs: 631275 + ttEntries: 2090893 + negamaxTtHits: 177325 + quiescenceTtHits: 176873 + negamaxTtCutoffs: 159378 + quiescenceTtCutoffs: 154786 + negamaxBetaCutoffs: 184318 + quiescenceBetaCutoffs: 446957 + qsearchStandPatCutoffs: 915269 + qsearchDeltaPruneChecks: 167928 + qsearchDeltaPruneSkips: 151382 + qsearchNodesWithMoves: 1006234 + qsearchGeneratedMoves: 2731950 + pvsResearches: 6990 + negamaxFrontierFutilityChecks: 374919 + negamaxFrontierFutilitySkips: 72928 + nullMoveAttempts: 2861 + nullMoveCutoffs: 2242 + - san: g5g6 + beforeFen: b/qbk/2b2/r2n3/pppppp1rp/11/3P1BP1p2/11/5K1PP2/2P8/1PRNQB1NRP1 w - 1 9 + source: rust-worker + evaluations: 2797508 + duration: 67082.60000038147 + metrics: null + - san: f7g6 + beforeFen: b/qbk/2b2/r2n3/pppppp1rp/6P4/3P1B2p2/11/5K1PP2/2P8/1PRNQB1NRP1 b - 0 9 + source: python-api + evaluations: 1092316 + duration: 56207.699999809265 + metrics: + wallMs: 56133.57549998909 + evalsPerMs: 19.459227214204667 + rootMoves: 55 + negamaxNodes: 644295 + quiescenceNodes: 1181356 + movegenCalls: 984480 + tacticalMovegenCalls: 478977 + legalContextCalls: 984480 + ttHits: 236278 + ttCutoffs: 226065 + betaCutoffs: 325182 + ttEntries: 1219340 + negamaxTtHits: 141205 + quiescenceTtHits: 95073 + negamaxTtCutoffs: 137025 + quiescenceTtCutoffs: 89040 + negamaxBetaCutoffs: 159614 + quiescenceBetaCutoffs: 165568 + qsearchStandPatCutoffs: 613339 + qsearchDeltaPruneChecks: 122590 + qsearchDeltaPruneSkips: 117127 + qsearchNodesWithMoves: 445812 + qsearchGeneratedMoves: 1350001 + pvsResearches: 1701 + negamaxFrontierFutilityChecks: 268832 + negamaxFrontierFutilitySkips: 31411 + nullMoveAttempts: 2149 + nullMoveCutoffs: 1768 + - san: f5g6 + beforeFen: b/qbk/2b2/r2n3/pppp1p1rp/6p4/3P1B2p2/11/5K1PP2/2P8/1PRNQB1NRP1 w - 0 10 + source: rust-worker + evaluations: 2237856 + duration: 51173.5 + metrics: null + - san: f8d5 + beforeFen: b/qbk/2b2/r2n3/pppp1p1rp/6B4/3P4p2/11/5K1PP2/2P8/1PRNQB1NRP1 b - 0 10 + source: python-api + evaluations: 1091933 + duration: 55694.800000190735 + metrics: + wallMs: 55602.593099698424 + evalsPerMs: 19.638166839487248 + rootMoves: 53 + negamaxNodes: 576405 + quiescenceNodes: 1182293 + movegenCalls: 1036879 + tacticalMovegenCalls: 564110 + legalContextCalls: 1036879 + ttHits: 216549 + ttCutoffs: 191466 + betaCutoffs: 359789 + ttEntries: 1155853 + negamaxTtHits: 110736 + quiescenceTtHits: 105813 + negamaxTtCutoffs: 101106 + quiescenceTtCutoffs: 90360 + negamaxBetaCutoffs: 139148 + quiescenceBetaCutoffs: 220641 + qsearchStandPatCutoffs: 527823 + qsearchDeltaPruneChecks: 116070 + qsearchDeltaPruneSkips: 109852 + qsearchNodesWithMoves: 498439 + qsearchGeneratedMoves: 1392738 + pvsResearches: 2639 + negamaxFrontierFutilityChecks: 277580 + negamaxFrontierFutilitySkips: 49923 + nullMoveAttempts: 3354 + nullMoveCutoffs: 2531 + - san: c1g4 + beforeFen: b/qbk/2b2/r6/pppp1p1rp/6B4/3n4p2/11/5K1PP2/2P8/1PRNQB1NRP1 w - 0 11 + source: rust-worker + evaluations: 3232500 + duration: 74644.19999980927 + metrics: null + - san: d5g6 + beforeFen: b/qbk/2b2/r6/pppp1p1rp/6B4/3n4p2/6R4/5K1PP2/2P8/1P1NQB1NRP1 b - 1 11 + source: python-api + evaluations: 1114229 + duration: 69165.5 + metrics: + wallMs: 69078.4289999865 + evalsPerMs: 16.129912276960116 + rootMoves: 57 + negamaxNodes: 757492 + quiescenceNodes: 1241463 + movegenCalls: 1198067 + tacticalMovegenCalls: 565842 + legalContextCalls: 1198067 + ttHits: 295869 + ttCutoffs: 251102 + betaCutoffs: 395382 + ttEntries: 1268091 + negamaxTtHits: 141227 + quiescenceTtHits: 154642 + negamaxTtCutoffs: 123868 + quiescenceTtCutoffs: 127234 + negamaxBetaCutoffs: 231324 + quiescenceBetaCutoffs: 164058 + qsearchStandPatCutoffs: 548387 + qsearchDeltaPruneChecks: 425469 + qsearchDeltaPruneSkips: 410451 + qsearchNodesWithMoves: 505561 + qsearchGeneratedMoves: 1629519 + pvsResearches: 2755 + negamaxFrontierFutilityChecks: 216009 + negamaxFrontierFutilitySkips: 46312 + nullMoveAttempts: 4173 + nullMoveCutoffs: 1400 + - san: g4g6 + beforeFen: b/qbk/2b2/r6/pppp1p1rp/6n4/8p2/6R4/5K1PP2/2P8/1P1NQB1NRP1 w - 0 12 + source: rust-worker + evaluations: 1489920 + duration: 32742.300000190735 + metrics: null + - san: c7c5 + beforeFen: b/qbk/2b2/r6/pppp1p1rp/6R4/8p2/11/5K1PP2/2P8/1P1NQB1NRP1 b - 0 12 + source: python-api + evaluations: 933448 + duration: 48301.59999990463 + metrics: + wallMs: 48232.14709991589 + evalsPerMs: 19.353233395691557 + rootMoves: 47 + negamaxNodes: 508114 + quiescenceNodes: 1032687 + movegenCalls: 897672 + tacticalMovegenCalls: 475572 + legalContextCalls: 897672 + ttHits: 196686 + ttCutoffs: 183185 + betaCutoffs: 303532 + ttEntries: 1019108 + negamaxTtHits: 90874 + quiescenceTtHits: 105812 + negamaxTtCutoffs: 83946 + quiescenceTtCutoffs: 99239 + negamaxBetaCutoffs: 127446 + quiescenceBetaCutoffs: 176086 + qsearchStandPatCutoffs: 457876 + qsearchDeltaPruneChecks: 166834 + qsearchDeltaPruneSkips: 156498 + qsearchNodesWithMoves: 433405 + qsearchGeneratedMoves: 1221375 + pvsResearches: 2956 + negamaxFrontierFutilityChecks: 240214 + negamaxFrontierFutilitySkips: 59801 + nullMoveAttempts: 2699 + nullMoveCutoffs: 2069 + - san: e1l2 + beforeFen: b/qbk/2b2/r6/p1pp1p1rp/6R4/2p5p2/11/5K1PP2/2P8/1P1NQB1NRP1 w c6 0 13 + source: rust-worker + evaluations: 1947834 + duration: 46034.2000002861 + metrics: null + - san: f9h8 + beforeFen: b/qbk/2b2/r6/p1pp1p1rp/6R4/2p5p2/11/5K1PP2/2P7Q/1P1N1B1NRP1 b - 1 13 + source: python-api + evaluations: 159370 + duration: 7989.39999961853 + metrics: + wallMs: 7975.105000194162 + evalsPerMs: 19.98343595427521 + rootMoves: 5 + negamaxNodes: 86502 + quiescenceNodes: 170049 + movegenCalls: 153420 + tacticalMovegenCalls: 80380 + legalContextCalls: 153420 + ttHits: 25770 + ttCutoffs: 23969 + betaCutoffs: 50654 + ttEntries: 170035 + negamaxTtHits: 14220 + quiescenceTtHits: 11550 + negamaxTtCutoffs: 13290 + quiescenceTtCutoffs: 10679 + negamaxBetaCutoffs: 20268 + quiescenceBetaCutoffs: 30386 + qsearchStandPatCutoffs: 78990 + qsearchDeltaPruneChecks: 31328 + qsearchDeltaPruneSkips: 30504 + qsearchNodesWithMoves: 70538 + qsearchGeneratedMoves: 193896 + pvsResearches: 474 + negamaxFrontierFutilityChecks: 45259 + negamaxFrontierFutilitySkips: 7752 + nullMoveAttempts: 193 + nullMoveCutoffs: 173 + - san: l2l1 + beforeFen: b/qbk/5/r4b1/p1pp1p1rp/6R4/2p5p2/11/5K1PP2/2P7Q/1P1N1B1NRP1 w - 2 14 + source: rust-worker + evaluations: 711203 + duration: 18722.400000095367 + metrics: null + - san: i5i4 + beforeFen: b/qbk/5/r4b1/p1pp1p1rp/6R4/2p5p2/11/5K1PP2/2P8/1P1N1B1NRPQ b - 3 14 + source: python-api + evaluations: 1234586 + duration: 71567.59999990463 + metrics: + wallMs: 71486.41999997199 + evalsPerMs: 17.27021719650367 + rootMoves: 50 + negamaxNodes: 939762 + quiescenceNodes: 1361074 + movegenCalls: 1325194 + tacticalMovegenCalls: 637595 + legalContextCalls: 1325194 + ttHits: 404515 + ttCutoffs: 378107 + betaCutoffs: 427519 + ttEntries: 1386104 + negamaxTtHits: 265423 + quiescenceTtHits: 139092 + negamaxTtCutoffs: 251619 + quiescenceTtCutoffs: 126488 + negamaxBetaCutoffs: 201388 + quiescenceBetaCutoffs: 226131 + qsearchStandPatCutoffs: 596991 + qsearchDeltaPruneChecks: 544263 + qsearchDeltaPruneSkips: 532056 + qsearchNodesWithMoves: 590334 + qsearchGeneratedMoves: 1874072 + pvsResearches: 2871 + negamaxFrontierFutilityChecks: 498317 + negamaxFrontierFutilitySkips: 93151 + nullMoveAttempts: 1023 + nullMoveCutoffs: 545 + - san: k1k3 + beforeFen: b/qbk/5/r4b1/p1pp1p1rp/6R4/2p8/8p2/5K1PP2/2P8/1P1N1B1NRPQ w - 0 15 + source: rust-worker + evaluations: 586741 + duration: 14334 + metrics: null + - san: f11h7 + beforeFen: b/qbk/5/r4b1/p1pp1p1rp/6R4/2p8/8p2/5K1PPP1/2P8/1P1N1B1NR1Q b k2 0 15 + source: python-api + evaluations: 1419529 + duration: 70608.19999980927 + metrics: + wallMs: 70520.03929996863 + evalsPerMs: 20.129441419648096 + rootMoves: 51 + negamaxNodes: 898732 + quiescenceNodes: 1497667 + movegenCalls: 1308785 + tacticalMovegenCalls: 627098 + legalContextCalls: 1308785 + ttHits: 326364 + ttCutoffs: 293582 + betaCutoffs: 398417 + ttEntries: 1525692 + negamaxTtHits: 232057 + quiescenceTtHits: 94307 + negamaxTtCutoffs: 215442 + quiescenceTtCutoffs: 78140 + negamaxBetaCutoffs: 155121 + quiescenceBetaCutoffs: 243296 + qsearchStandPatCutoffs: 792429 + qsearchDeltaPruneChecks: 317855 + qsearchDeltaPruneSkips: 309836 + qsearchNodesWithMoves: 583805 + qsearchGeneratedMoves: 1896288 + pvsResearches: 4981 + negamaxFrontierFutilityChecks: 661423 + negamaxFrontierFutilitySkips: 193493 + nullMoveAttempts: 2345 + nullMoveCutoffs: 1604 + - san: g6d4 + beforeFen: 1/qbk/5/r4b1/p1pp1pbrp/6R4/2p8/8p2/5K1PPP1/2P8/1P1N1B1NR1Q w - 1 16 + source: rust-worker + evaluations: 830061 + duration: 21008.60000038147 + metrics: null + - san: i4k3 + beforeFen: 1/qbk/5/r4b1/p1pp1pbrp/11/2p8/3R4p2/5K1PPP1/2P8/1P1N1B1NR1Q b - 2 16 + source: python-api + evaluations: 2134768 + duration: 100656.5 + metrics: + wallMs: 100537.65690000728 + evalsPerMs: 21.233516533244824 + rootMoves: 60 + negamaxNodes: 1314268 + quiescenceNodes: 2290113 + movegenCalls: 1959062 + tacticalMovegenCalls: 1034134 + legalContextCalls: 1959062 + ttHits: 610384 + ttCutoffs: 543711 + betaCutoffs: 635946 + ttEntries: 2251238 + negamaxTtHits: 418866 + quiescenceTtHits: 191518 + negamaxTtCutoffs: 388350 + quiescenceTtCutoffs: 155361 + negamaxBetaCutoffs: 221499 + quiescenceBetaCutoffs: 414447 + qsearchStandPatCutoffs: 1100618 + qsearchDeltaPruneChecks: 495134 + qsearchDeltaPruneSkips: 469399 + qsearchNodesWithMoves: 957059 + qsearchGeneratedMoves: 3046738 + pvsResearches: 4842 + negamaxFrontierFutilityChecks: 885827 + negamaxFrontierFutilitySkips: 181533 + nullMoveAttempts: 1634 + nullMoveCutoffs: 991 + - san: d1c3 + beforeFen: 1/qbk/5/r4b1/p1pp1pbrp/11/2p8/3R7/5K1PPp1/2P8/1P1N1B1NR1Q w - 0 17 + source: rust-worker + evaluations: 3180181 + duration: 74960.40000009537 + metrics: null + - san: e7e5 + beforeFen: 1/qbk/5/r4b1/p1pp1pbrp/11/2p8/3R7/2N2K1PPp1/2P8/1P3B1NR1Q b - 1 17 + source: python-api + evaluations: 861910 + duration: 55312.800000190735 + metrics: + wallMs: 55249.44849964231 + evalsPerMs: 15.60033671658424 + rootMoves: 64 + negamaxNodes: 715637 + quiescenceNodes: 902562 + movegenCalls: 992709 + tacticalMovegenCalls: 415291 + legalContextCalls: 992709 + ttHits: 189403 + ttCutoffs: 177697 + betaCutoffs: 303750 + ttEntries: 1010387 + negamaxTtHits: 142338 + quiescenceTtHits: 47065 + negamaxTtCutoffs: 137032 + quiescenceTtCutoffs: 40665 + negamaxBetaCutoffs: 176791 + quiescenceBetaCutoffs: 126959 + qsearchStandPatCutoffs: 446606 + qsearchDeltaPruneChecks: 601387 + qsearchDeltaPruneSkips: 585207 + qsearchNodesWithMoves: 385404 + qsearchGeneratedMoves: 1367150 + pvsResearches: 1438 + negamaxFrontierFutilityChecks: 385013 + negamaxFrontierFutilitySkips: 106677 + nullMoveAttempts: 3482 + nullMoveCutoffs: 1188 + - san: d4f4 + beforeFen: 1/qbk/5/r4b1/p1p2pbrp/11/2p1p6/3R7/2N2K1PPp1/2P8/1P3B1NR1Q w e6 0 18 + source: rust-worker + evaluations: 1505676 + duration: 34068.39999961853 + metrics: null + - san: h8f9 + beforeFen: 1/qbk/5/r4b1/p1p2pbrp/11/2p1p6/5R5/2N2K1PPp1/2P8/1P3B1NR1Q b - 1 18 + source: python-api + evaluations: 805873 + duration: 47127.90000009537 + metrics: + wallMs: 47081.96459989995 + evalsPerMs: 17.116384306565504 + rootMoves: 64 + negamaxNodes: 605046 + quiescenceNodes: 848572 + movegenCalls: 876188 + tacticalMovegenCalls: 393645 + legalContextCalls: 876188 + ttHits: 183131 + ttCutoffs: 163745 + betaCutoffs: 276719 + ttEntries: 917703 + negamaxTtHits: 130154 + quiescenceTtHits: 52977 + negamaxTtCutoffs: 121018 + quiescenceTtCutoffs: 42727 + negamaxBetaCutoffs: 144551 + quiescenceBetaCutoffs: 132168 + qsearchStandPatCutoffs: 412200 + qsearchDeltaPruneChecks: 467128 + qsearchDeltaPruneSkips: 455263 + qsearchNodesWithMoves: 363980 + qsearchGeneratedMoves: 1219832 + pvsResearches: 1428 + negamaxFrontierFutilityChecks: 382729 + negamaxFrontierFutilitySkips: 137591 + nullMoveAttempts: 3439 + nullMoveCutoffs: 1486 + - san: c3e2 + beforeFen: 1/qbk/2b2/r6/p1p2pbrp/11/2p1p6/5R5/2N2K1PPp1/2P8/1P3B1NR1Q w - 2 19 + source: rust-worker + evaluations: 1542879 + duration: 34799.300000190735 + metrics: null + - san: f9d5 + beforeFen: 1/qbk/2b2/r6/p1p2pbrp/11/2p1p6/5R5/5K1PPp1/2P1N6/1P3B1NR1Q b - 3 19 + source: python-api + evaluations: 719369 + duration: 40888.2000002861 + metrics: + wallMs: 40830.68579994142 + evalsPerMs: 17.618342330195006 + rootMoves: 67 + negamaxNodes: 518559 + quiescenceNodes: 765630 + movegenCalls: 786572 + tacticalMovegenCalls: 372112 + legalContextCalls: 786572 + ttHits: 166284 + ttCutoffs: 148934 + betaCutoffs: 258017 + ttEntries: 820290 + negamaxTtHits: 110886 + quiescenceTtHits: 55398 + negamaxTtCutoffs: 102671 + quiescenceTtCutoffs: 46263 + negamaxBetaCutoffs: 126253 + quiescenceBetaCutoffs: 131764 + qsearchStandPatCutoffs: 347255 + qsearchDeltaPruneChecks: 424822 + qsearchDeltaPruneSkips: 414286 + qsearchNodesWithMoves: 348385 + qsearchGeneratedMoves: 1158247 + pvsResearches: 1284 + negamaxFrontierFutilityChecks: 383677 + negamaxFrontierFutilitySkips: 195682 + nullMoveAttempts: 3321 + nullMoveCutoffs: 1429 + - san: f3g2 + beforeFen: 1/qbk/5/r6/p1p2pbrp/11/2pbp6/5R5/5K1PPp1/2P1N6/1P3B1NR1Q w - 4 20 + source: rust-worker + evaluations: 243879 + duration: 4917.699999809265 + metrics: null + - san: e5e4 + beforeFen: 1/qbk/5/r6/p1p2pbrp/11/2pbp6/5R5/7PPp1/2P1N1K4/1P3B1NR1Q b - 5 20 + source: python-api + evaluations: 961077 + duration: 46984.40000009537 + metrics: + wallMs: 46932.5962997973 + evalsPerMs: 20.477814478040095 + rootMoves: 73 + negamaxNodes: 606374 + quiescenceNodes: 1015840 + movegenCalls: 957922 + tacticalMovegenCalls: 483441 + legalContextCalls: 957922 + ttHits: 209252 + ttCutoffs: 184929 + betaCutoffs: 309986 + ttEntries: 1049967 + negamaxTtHits: 140477 + quiescenceTtHits: 68775 + negamaxTtCutoffs: 130038 + quiescenceTtCutoffs: 54891 + negamaxBetaCutoffs: 125408 + quiescenceBetaCutoffs: 184578 + qsearchStandPatCutoffs: 477508 + qsearchDeltaPruneChecks: 413494 + qsearchDeltaPruneSkips: 400060 + qsearchNodesWithMoves: 453912 + qsearchGeneratedMoves: 1510830 + pvsResearches: 1856 + negamaxFrontierFutilityChecks: 413633 + negamaxFrontierFutilitySkips: 133265 + nullMoveAttempts: 3620 + nullMoveCutoffs: 1856 + - san: f4g4 + beforeFen: 1/qbk/5/r6/p1p2pbrp/11/2pb7/4pR5/7PPp1/2P1N1K4/1P3B1NR1Q w - 0 21 + source: rust-worker + evaluations: 1279053 + duration: 23964.199999809265 + metrics: null + - san: f10d6 + beforeFen: 1/qbk/5/r6/p1p2pbrp/11/2pb7/4p1R4/7PPp1/2P1N1K4/1P3B1NR1Q b - 1 21 + source: python-api + evaluations: 790424 + duration: 40696.7000002861 + metrics: + wallMs: 40635.51210006699 + evalsPerMs: 19.451557496151178 + rootMoves: 72 + negamaxNodes: 591079 + quiescenceNodes: 825285 + movegenCalls: 775138 + tacticalMovegenCalls: 339899 + legalContextCalls: 775138 + ttHits: 203378 + ttCutoffs: 189239 + betaCutoffs: 228767 + ttEntries: 873418 + negamaxTtHits: 161424 + quiescenceTtHits: 41954 + negamaxTtCutoffs: 154363 + quiescenceTtCutoffs: 34876 + negamaxBetaCutoffs: 104807 + quiescenceBetaCutoffs: 123960 + qsearchStandPatCutoffs: 450510 + qsearchDeltaPruneChecks: 404492 + qsearchDeltaPruneSkips: 394474 + qsearchNodesWithMoves: 317120 + qsearchGeneratedMoves: 1236365 + pvsResearches: 1402 + negamaxFrontierFutilityChecks: 494115 + negamaxFrontierFutilitySkips: 180771 + nullMoveAttempts: 3081 + nullMoveCutoffs: 1478 + - san: g2g1 + beforeFen: 1/q1k/5/r6/p1p2pbrp/3b7/2pb7/4p1R4/7PPp1/2P1N1K4/1P3B1NR1Q w - 2 22 + source: rust-worker + evaluations: 215785 + duration: 5195.700000286102 + metrics: null + - san: e4e3 + beforeFen: 1/q1k/5/r6/p1p2pbrp/3b7/2pb7/4p1R4/7PPp1/2P1N6/1P3BKNR1Q b - 3 22 + source: python-api + evaluations: 730160 + duration: 36119.90000009537 + metrics: + wallMs: 36075.77939983457 + evalsPerMs: 20.23961816340822 + rootMoves: 78 + negamaxNodes: 521215 + quiescenceNodes: 758217 + movegenCalls: 700677 + tacticalMovegenCalls: 316233 + legalContextCalls: 700677 + ttHits: 180900 + ttCutoffs: 163150 + betaCutoffs: 204001 + ttEntries: 784389 + negamaxTtHits: 143138 + quiescenceTtHits: 37762 + negamaxTtCutoffs: 135027 + quiescenceTtCutoffs: 28123 + negamaxBetaCutoffs: 80189 + quiescenceBetaCutoffs: 123812 + qsearchStandPatCutoffs: 413861 + qsearchDeltaPruneChecks: 295380 + qsearchDeltaPruneSkips: 287589 + qsearchNodesWithMoves: 290769 + qsearchGeneratedMoves: 1106566 + pvsResearches: 1311 + negamaxFrontierFutilityChecks: 558522 + negamaxFrontierFutilitySkips: 266984 + nullMoveAttempts: 3451 + nullMoveCutoffs: 1745 + - san: g1f2 + beforeFen: 1/q1k/5/r6/p1p2pbrp/3b7/2pb7/6R4/4p2PPp1/2P1N6/1P3BKNR1Q w - 0 23 + source: rust-worker + evaluations: 83584 + duration: 1875.8999996185303 + metrics: null + - san: e10f10 + beforeFen: 1/q1k/5/r6/p1p2pbrp/3b7/2pb7/6R4/4p2PPp1/2P1NK5/1P3B1NR1Q b - 1 23 + source: python-api + evaluations: 1080815 + duration: 51224.09999990463 + metrics: + wallMs: 51167.34640020877 + evalsPerMs: 21.123139580980695 + rootMoves: 79 + negamaxNodes: 747059 + quiescenceNodes: 1119789 + movegenCalls: 995781 + tacticalMovegenCalls: 438878 + legalContextCalls: 995781 + ttHits: 250277 + ttCutoffs: 227733 + betaCutoffs: 276486 + ttEntries: 1141645 + negamaxTtHits: 198753 + quiescenceTtHits: 51524 + negamaxTtCutoffs: 188574 + quiescenceTtCutoffs: 39159 + negamaxBetaCutoffs: 95150 + quiescenceBetaCutoffs: 181336 + qsearchStandPatCutoffs: 641752 + qsearchDeltaPruneChecks: 388837 + qsearchDeltaPruneSkips: 374660 + qsearchNodesWithMoves: 405954 + qsearchGeneratedMoves: 1568038 + pvsResearches: 1444 + negamaxFrontierFutilityChecks: 732747 + negamaxFrontierFutilitySkips: 257481 + nullMoveAttempts: 3235 + nullMoveCutoffs: 1583 + - san: e2f5 + beforeFen: 1/1qk/5/r6/p1p2pbrp/3b7/2pb7/6R4/4p2PPp1/2P1NK5/1P3B1NR1Q w - 2 24 + source: rust-worker + evaluations: 182866 + duration: 4549.599999904633 + metrics: null + - san: h7f5 + beforeFen: 1/1qk/5/r6/p1p2pbrp/3b7/2pb1N5/6R4/4p2PPp1/2P2K5/1P3B1NR1Q b - 3 24 + source: python-api + evaluations: 1633135 + duration: 80118 + metrics: + wallMs: 80029.59159994498 + evalsPerMs: 20.40663918621225 + rootMoves: 85 + negamaxNodes: 1155468 + quiescenceNodes: 1692986 + movegenCalls: 1501474 + tacticalMovegenCalls: 690799 + legalContextCalls: 1501474 + ttHits: 438005 + ttCutoffs: 402934 + betaCutoffs: 441916 + ttEntries: 1740354 + negamaxTtHits: 357660 + quiescenceTtHits: 80345 + negamaxTtCutoffs: 343004 + quiescenceTtCutoffs: 59930 + negamaxBetaCutoffs: 157251 + quiescenceBetaCutoffs: 284665 + qsearchStandPatCutoffs: 942257 + qsearchDeltaPruneChecks: 569395 + qsearchDeltaPruneSkips: 539021 + qsearchNodesWithMoves: 648076 + qsearchGeneratedMoves: 2387393 + pvsResearches: 1483 + negamaxFrontierFutilityChecks: 927368 + negamaxFrontierFutilitySkips: 213084 + nullMoveAttempts: 3636 + nullMoveCutoffs: 1790 + - san: c2c4 + beforeFen: 1/1qk/5/r6/p1p2p1rp/3b7/2pb1b5/6R4/4p2PPp1/2P2K5/1P3B1NR1Q w - 0 25 + source: rust-worker + evaluations: 2564917 + duration: 69554.09999990463 + metrics: null + - san: d5b1 + beforeFen: 1/1qk/5/r6/p1p2p1rp/3b7/2pb1b5/2P3R4/4p2PPp1/5K5/1P3B1NR1Q b c3 0 25 + source: python-api + evaluations: 820822 + duration: 36716 + metrics: + wallMs: 36669.205700047314 + evalsPerMs: 22.384504499887242 + rootMoves: 84 + negamaxNodes: 579913 + quiescenceNodes: 855812 + movegenCalls: 733854 + tacticalMovegenCalls: 314161 + legalContextCalls: 733854 + ttHits: 215973 + ttCutoffs: 194599 + betaCutoffs: 198495 + ttEntries: 860502 + negamaxTtHits: 168835 + quiescenceTtHits: 47138 + negamaxTtCutoffs: 159214 + quiescenceTtCutoffs: 35385 + negamaxBetaCutoffs: 65016 + quiescenceBetaCutoffs: 133479 + qsearchStandPatCutoffs: 506266 + qsearchDeltaPruneChecks: 198337 + qsearchDeltaPruneSkips: 189619 + qsearchNodesWithMoves: 291844 + qsearchGeneratedMoves: 1139050 + pvsResearches: 1005 + negamaxFrontierFutilityChecks: 547698 + negamaxFrontierFutilitySkips: 159523 + nullMoveAttempts: 1834 + nullMoveCutoffs: 1007 + - san: h3h5 + beforeFen: 1/1qk/5/r6/p1p2p1rp/3b7/2p2b5/2P3R4/4p2PPp1/5K5/1b3B1NR1Q w - 0 26 + source: rust-worker + evaluations: 1825610 + duration: 43714.09999990463 + metrics: null + - san: i7l5 + beforeFen: 1/1qk/5/r6/p1p2p1rp/3b7/2p2b1P3/2P3R4/4p3Pp1/5K5/1b3B1NR1Q b h4 0 26 + source: python-api + evaluations: 1202387 + duration: 56815.199999809265 + metrics: + wallMs: 56753.854299895465 + evalsPerMs: 21.185997230186615 + rootMoves: 81 + negamaxNodes: 1040878 + quiescenceNodes: 1238748 + movegenCalls: 1134876 + tacticalMovegenCalls: 392525 + legalContextCalls: 1134876 + ttHits: 365143 + ttCutoffs: 334461 + betaCutoffs: 247221 + ttEntries: 1245805 + negamaxTtHits: 311486 + quiescenceTtHits: 53657 + negamaxTtCutoffs: 297219 + quiescenceTtCutoffs: 37242 + negamaxBetaCutoffs: 77964 + quiescenceBetaCutoffs: 169257 + qsearchStandPatCutoffs: 808981 + qsearchDeltaPruneChecks: 213275 + qsearchDeltaPruneSkips: 200941 + qsearchNodesWithMoves: 361657 + qsearchGeneratedMoves: 1279577 + pvsResearches: 1656 + negamaxFrontierFutilityChecks: 1011298 + negamaxFrontierFutilitySkips: 225507 + nullMoveAttempts: 1795 + nullMoveCutoffs: 1309 + - san: l1l5 + beforeFen: 1/1qk/5/r6/p1p2p2p/3b7/2p2b1P2r/2P3R4/4p3Pp1/5K5/1b3B1NR1Q w - 1 27 + source: rust-worker + evaluations: 1652501 + duration: 38378 + metrics: null + - san: f5h1 + beforeFen: 1/1qk/5/r6/p1p2p2p/3b7/2p2b1P2Q/2P3R4/4p3Pp1/5K5/1b3B1NR2 b - 0 27 + source: python-api + evaluations: 207884 + duration: 11482.099999904633 + metrics: + wallMs: 11463.761599734426 + evalsPerMs: 18.13401283613713 + rootMoves: 72 + negamaxNodes: 147078 + quiescenceNodes: 218821 + movegenCalls: 223181 + tacticalMovegenCalls: 99386 + legalContextCalls: 223181 + ttHits: 37010 + ttCutoffs: 31742 + betaCutoffs: 75112 + ttEntries: 245451 + negamaxTtHits: 23210 + quiescenceTtHits: 13800 + negamaxTtCutoffs: 20778 + quiescenceTtCutoffs: 10964 + negamaxBetaCutoffs: 45849 + quiescenceBetaCutoffs: 29263 + qsearchStandPatCutoffs: 108471 + qsearchDeltaPruneChecks: 102331 + qsearchDeltaPruneSkips: 100290 + qsearchNodesWithMoves: 91520 + qsearchGeneratedMoves: 334806 + pvsResearches: 388 + negamaxFrontierFutilityChecks: 58871 + negamaxFrontierFutilitySkips: 22579 + nullMoveAttempts: 2932 + nullMoveCutoffs: 2506 + - san: f2h1 + beforeFen: 1/1qk/5/r6/p1p2p2p/3b7/2p4P2Q/2P3R4/4p3Pp1/5K5/1b3B1bR2 w - 0 28 + source: rust-worker + evaluations: 58297 + duration: 1209 + metrics: null + - san: f10l5 + beforeFen: 1/1qk/5/r6/p1p2p2p/3b7/2p4P2Q/2P3R4/4p3Pp1/11/1b3B1KR2 b - 0 28 + source: python-api + evaluations: 264918 + duration: 14286.10000038147 + metrics: + wallMs: 14257.174199912697 + evalsPerMs: 18.581381996554562 + rootMoves: 68 + negamaxNodes: 207105 + quiescenceNodes: 280738 + movegenCalls: 309369 + tacticalMovegenCalls: 137208 + legalContextCalls: 309369 + ttHits: 57004 + ttCutoffs: 48519 + betaCutoffs: 101022 + ttEntries: 301551 + negamaxTtHits: 36701 + quiescenceTtHits: 20303 + negamaxTtCutoffs: 32622 + quiescenceTtCutoffs: 15897 + negamaxBetaCutoffs: 58140 + quiescenceBetaCutoffs: 42882 + qsearchStandPatCutoffs: 127633 + qsearchDeltaPruneChecks: 140750 + qsearchDeltaPruneSkips: 136353 + qsearchNodesWithMoves: 117101 + qsearchGeneratedMoves: 421745 + pvsResearches: 737 + negamaxFrontierFutilityChecks: 79566 + negamaxFrontierFutilitySkips: 16013 + nullMoveAttempts: 2952 + nullMoveCutoffs: 2323 + - san: g4e3 + beforeFen: 1/2k/5/r6/p1p2p2p/3b7/2p4P2q/2P3R4/4p3Pp1/11/1b3B1KR2 w - 0 29 + source: rust-worker + evaluations: 732691 + duration: 10134.5 + metrics: null + - san: l5h5 + beforeFen: 1/2k/5/r6/p1p2p2p/3b7/2p4P2q/2P8/4R3Pp1/11/1b3B1KR2 b - 0 29 + source: python-api + evaluations: 338894 + duration: 17523.200000286102 + metrics: + wallMs: 17491.162500344217 + evalsPerMs: 19.375155881910693 + rootMoves: 59 + negamaxNodes: 343099 + quiescenceNodes: 359833 + movegenCalls: 411703 + tacticalMovegenCalls: 145719 + legalContextCalls: 411703 + ttHits: 106845 + ttCutoffs: 97262 + betaCutoffs: 106419 + ttEntries: 369492 + negamaxTtHits: 81015 + quiescenceTtHits: 25830 + negamaxTtCutoffs: 76205 + quiescenceTtCutoffs: 21057 + negamaxBetaCutoffs: 54481 + quiescenceBetaCutoffs: 51938 + qsearchStandPatCutoffs: 193057 + qsearchDeltaPruneChecks: 45565 + qsearchDeltaPruneSkips: 40192 + qsearchNodesWithMoves: 120497 + qsearchGeneratedMoves: 276637 + pvsResearches: 934 + negamaxFrontierFutilityChecks: 267162 + negamaxFrontierFutilitySkips: 70697 + nullMoveAttempts: 2084 + nullMoveCutoffs: 911 + - san: e3h4 + beforeFen: 1/2k/5/r6/p1p2p2p/3b7/2p4q3/2P8/4R3Pp1/11/1b3B1KR2 w - 0 30 + source: rust-worker + evaluations: 131151 + duration: 2018.5999999046326 + metrics: null + - san: h5f5 + beforeFen: 1/2k/5/r6/p1p2p2p/3b7/2p4q3/2P4R3/8Pp1/11/1b3B1KR2 b - 1 30 + source: python-api + evaluations: 147580 + duration: 7356.300000190735 + metrics: + wallMs: 7340.637099929154 + evalsPerMs: 20.104521990526454 + rootMoves: 69 + negamaxNodes: 155006 + quiescenceNodes: 154174 + movegenCalls: 169920 + tacticalMovegenCalls: 62658 + legalContextCalls: 169920 + ttHits: 62227 + ttCutoffs: 53166 + betaCutoffs: 41333 + ttEntries: 152738 + negamaxTtHits: 50998 + quiescenceTtHits: 11229 + negamaxTtCutoffs: 46484 + quiescenceTtCutoffs: 6682 + negamaxBetaCutoffs: 17909 + quiescenceBetaCutoffs: 23424 + qsearchStandPatCutoffs: 84834 + qsearchDeltaPruneChecks: 23854 + qsearchDeltaPruneSkips: 20077 + qsearchNodesWithMoves: 51887 + qsearchGeneratedMoves: 132089 + pvsResearches: 691 + negamaxFrontierFutilityChecks: 116268 + negamaxFrontierFutilitySkips: 15229 + nullMoveAttempts: 1731 + nullMoveCutoffs: 1261 + - san: h1g1 + beforeFen: 1/2k/5/r6/p1p2p2p/3b7/2p2q5/2P4R3/8Pp1/11/1b3B1KR2 w - 2 31 + source: rust-worker + evaluations: 59161 + duration: 985.1999998092651 + metrics: null + - san: b1f3 + beforeFen: 1/2k/5/r6/p1p2p2p/3b7/2p2q5/2P4R3/8Pp1/11/1b3BK1R2 b - 3 31 + source: python-api + evaluations: 343848 + duration: 17201.400000095367 + metrics: + wallMs: 17088.81670003757 + evalsPerMs: 20.121229341715864 + rootMoves: 76 + negamaxNodes: 397333 + quiescenceNodes: 354391 + movegenCalls: 411453 + tacticalMovegenCalls: 122604 + legalContextCalls: 411453 + ttHits: 133592 + ttCutoffs: 119568 + betaCutoffs: 87872 + ttEntries: 364430 + negamaxTtHits: 114599 + quiescenceTtHits: 18993 + negamaxTtCutoffs: 107403 + quiescenceTtCutoffs: 12165 + negamaxBetaCutoffs: 43653 + quiescenceBetaCutoffs: 44219 + qsearchStandPatCutoffs: 219622 + qsearchDeltaPruneChecks: 46676 + qsearchDeltaPruneSkips: 37869 + qsearchNodesWithMoves: 100895 + qsearchGeneratedMoves: 221256 + pvsResearches: 1394 + negamaxFrontierFutilityChecks: 350657 + negamaxFrontierFutilitySkips: 83162 + nullMoveAttempts: 2105 + nullMoveCutoffs: 1082 + - san: g1f2 + beforeFen: 1/2k/5/r6/p1p2p2p/3b7/2p2q5/2P4R3/5b2Pp1/11/5BK1R2 w - 4 32 + source: rust-worker + evaluations: 29327 + duration: 534.4000000953674 + metrics: null + - san: f3c6 + beforeFen: 1/2k/5/r6/p1p2p2p/3b7/2p2q5/2P4R3/5b2Pp1/5K5/5B2R2 b - 5 32 + source: python-api + evaluations: 365397 + duration: 19393.599999904633 + metrics: + wallMs: 19362.77800006792 + evalsPerMs: 18.871104135920902 + rootMoves: 77 + negamaxNodes: 406588 + quiescenceNodes: 377970 + movegenCalls: 425918 + tacticalMovegenCalls: 120486 + legalContextCalls: 425918 + ttHits: 126988 + ttCutoffs: 113134 + betaCutoffs: 86634 + ttEntries: 388179 + negamaxTtHits: 107329 + quiescenceTtHits: 19659 + negamaxTtCutoffs: 100099 + quiescenceTtCutoffs: 13035 + negamaxBetaCutoffs: 41886 + quiescenceBetaCutoffs: 44748 + qsearchStandPatCutoffs: 244449 + qsearchDeltaPruneChecks: 47393 + qsearchDeltaPruneSkips: 40288 + qsearchNodesWithMoves: 101438 + qsearchGeneratedMoves: 236796 + pvsResearches: 1062 + negamaxFrontierFutilityChecks: 383945 + negamaxFrontierFutilitySkips: 102579 + nullMoveAttempts: 2003 + nullMoveCutoffs: 1058 + - san: h4f4 + beforeFen: 1/2k/5/r6/p1p2p2p/2bb7/2p2q5/2P4R3/8Pp1/5K5/5B2R2 w - 6 33 + source: rust-worker + evaluations: 45692 + duration: 670.6999998092651 + metrics: null + - san: d6f4 + beforeFen: 1/2k/5/r6/p1p2p2p/2bb7/2p2q5/2P2R5/8Pp1/5K5/5B2R2 b - 7 33 + source: python-api + evaluations: 201140 + duration: 9820.5 + metrics: + wallMs: 9801.560000050813 + evalsPerMs: 20.521223152126524 + rootMoves: 75 + negamaxNodes: 225260 + quiescenceNodes: 207978 + movegenCalls: 233903 + tacticalMovegenCalls: 73084 + legalContextCalls: 233903 + ttHits: 79172 + ttCutoffs: 70578 + betaCutoffs: 50210 + ttEntries: 209166 + negamaxTtHits: 67809 + quiescenceTtHits: 11363 + negamaxTtCutoffs: 63481 + quiescenceTtCutoffs: 7097 + negamaxBetaCutoffs: 22004 + quiescenceBetaCutoffs: 28206 + qsearchStandPatCutoffs: 127797 + qsearchDeltaPruneChecks: 21061 + qsearchDeltaPruneSkips: 17702 + qsearchNodesWithMoves: 59194 + qsearchGeneratedMoves: 139787 + pvsResearches: 685 + negamaxFrontierFutilityChecks: 203258 + negamaxFrontierFutilitySkips: 45139 + nullMoveAttempts: 1408 + nullMoveCutoffs: 961 + - san: i3k3 + beforeFen: 1/2k/5/r6/p1p2p2p/2b8/2p2q5/2P2b5/8Pp1/5K5/5B2R2 w - 0 34 + source: rust-worker + evaluations: 310677 + duration: 4211.200000286102 + metrics: null + - san: f4g5 + beforeFen: 1/2k/5/r6/p1p2p2p/2b8/2p2q5/2P2b5/9P1/5K5/5B2R2 b - 0 34 + source: python-api + evaluations: 288962 + duration: 14169.700000286102 + metrics: + wallMs: 14152.676799800247 + evalsPerMs: 20.417480317509863 + rootMoves: 77 + negamaxNodes: 425020 + quiescenceNodes: 290262 + movegenCalls: 337375 + tacticalMovegenCalls: 43010 + legalContextCalls: 337375 + ttHits: 140876 + ttCutoffs: 132669 + betaCutoffs: 36178 + ttEntries: 299302 + negamaxTtHits: 135377 + quiescenceTtHits: 5499 + negamaxTtCutoffs: 130291 + quiescenceTtCutoffs: 2378 + negamaxBetaCutoffs: 22153 + quiescenceBetaCutoffs: 14025 + qsearchStandPatCutoffs: 244874 + qsearchDeltaPruneChecks: 3856 + qsearchDeltaPruneSkips: 3493 + qsearchNodesWithMoves: 26796 + qsearchGeneratedMoves: 44391 + pvsResearches: 1032 + negamaxFrontierFutilityChecks: 467787 + negamaxFrontierFutilitySkips: 112450 + nullMoveAttempts: 572 + nullMoveCutoffs: 365 + - san: f2g2 + beforeFen: 1/2k/5/r6/p1p2p2p/2b8/2p2qb4/2P8/9P1/5K5/5B2R2 w - 1 35 + source: rust-worker + evaluations: 38346 + duration: 490.5 + metrics: null + - san: g5i1 + beforeFen: 1/2k/5/r6/p1p2p2p/2b8/2p2qb4/2P8/9P1/6K4/5B2R2 b - 2 35 + source: python-api + evaluations: 321608 + duration: 16019.400000095367 + metrics: + wallMs: 15997.879900038242 + evalsPerMs: 20.103163794799535 + rootMoves: 76 + negamaxNodes: 571205 + quiescenceNodes: 320581 + movegenCalls: 368895 + tacticalMovegenCalls: 35333 + legalContextCalls: 368895 + ttHits: 251992 + ttCutoffs: 239344 + betaCutoffs: 33882 + ttEntries: 332397 + negamaxTtHits: 246029 + quiescenceTtHits: 5963 + negamaxTtCutoffs: 237451 + quiescenceTtCutoffs: 1893 + negamaxBetaCutoffs: 21225 + quiescenceBetaCutoffs: 12657 + qsearchStandPatCutoffs: 283355 + qsearchDeltaPruneChecks: 4765 + qsearchDeltaPruneSkips: 4612 + qsearchNodesWithMoves: 23831 + qsearchGeneratedMoves: 35953 + pvsResearches: 788 + negamaxFrontierFutilityChecks: 649654 + negamaxFrontierFutilitySkips: 158882 + nullMoveAttempts: 343 + nullMoveCutoffs: 193 + - san: g2i1 + beforeFen: 1/2k/5/r6/p1p2p2p/2b8/2p2q5/2P8/9P1/6K4/5B2b2 w - 0 36 + source: rust-worker + evaluations: 20692 + duration: 203.30000019073486 + metrics: null + - san: f5f1 + beforeFen: 1/2k/5/r6/p1p2p2p/2b8/2p2q5/2P8/9P1/11/5B2K2 b - 0 36 + source: python-api + evaluations: 259117 + duration: 11644.400000095367 + metrics: + wallMs: 11627.994199749082 + evalsPerMs: 22.283894844528856 + rootMoves: 69 + negamaxNodes: 563458 + quiescenceNodes: 259284 + movegenCalls: 292007 + tacticalMovegenCalls: 11708 + legalContextCalls: 292007 + ttHits: 291250 + ttCutoffs: 283427 + betaCutoffs: 17817 + ttEntries: 272400 + negamaxTtHits: 288737 + quiescenceTtHits: 2513 + negamaxTtCutoffs: 283130 + quiescenceTtCutoffs: 297 + negamaxBetaCutoffs: 14853 + quiescenceBetaCutoffs: 2964 + qsearchStandPatCutoffs: 247279 + qsearchDeltaPruneChecks: 347 + qsearchDeltaPruneSkips: 287 + qsearchNodesWithMoves: 4382 + qsearchGeneratedMoves: 5351 + pvsResearches: 695 + negamaxFrontierFutilityChecks: 551712 + negamaxFrontierFutilitySkips: 42187 + nullMoveAttempts: 51 + nullMoveCutoffs: 30 + - san: i1k2 + beforeFen: 1/2k/5/r6/p1p2p2p/2b8/2p8/2P8/9P1/11/5q2K2 w - 0 37 + source: rust-worker + evaluations: 18018 + duration: 107.89999961853027 + metrics: null + - san: g7g5 + beforeFen: 1/2k/5/r6/p1p2p2p/2b8/2p8/2P8/9P1/9K1/5q5 b - 1 37 + source: python-api + evaluations: 106921 + duration: 4428.5 + metrics: + wallMs: 4416.149099823087 + evalsPerMs: 24.211365509439727 + rootMoves: 60 + negamaxNodes: 218936 + quiescenceNodes: 106916 + movegenCalls: 118929 + tacticalMovegenCalls: 3519 + legalContextCalls: 118929 + ttHits: 105659 + ttCutoffs: 103577 + betaCutoffs: 6017 + ttEntries: 112611 + negamaxTtHits: 104941 + quiescenceTtHits: 718 + negamaxTtCutoffs: 103515 + quiescenceTtCutoffs: 62 + negamaxBetaCutoffs: 5297 + quiescenceBetaCutoffs: 720 + qsearchStandPatCutoffs: 103335 + qsearchDeltaPruneChecks: 3 + qsearchDeltaPruneSkips: 0 + qsearchNodesWithMoves: 930 + qsearchGeneratedMoves: 1048 + pvsResearches: 241 + negamaxFrontierFutilityChecks: 207707 + negamaxFrontierFutilitySkips: 6989 + nullMoveAttempts: 21 + nullMoveCutoffs: 12 diff --git a/results/2.1.003/hexchess-game-20260329-210806.yaml b/results/2.1.003/hexchess-game-20260329-210806.yaml new file mode 100644 index 00000000..7b0e36ac --- /dev/null +++ b/results/2.1.003/hexchess-game-20260329-210806.yaml @@ -0,0 +1,1252 @@ +version: 1 +startFen: b/qbk/n1b1n/r5r/ppppppppp/11/5P5/4P1P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 1 +historyIndex: 62 +moves: + - san: e4e5 + beforeFen: b/qbk/n1b1n/r5r/ppppppppp/11/5P5/4P1P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 1 + source: manual + evaluations: null + duration: null + metrics: null + - san: h7h5 + beforeFen: b/qbk/n1b1n/r5r/ppppppppp/11/4PP5/6P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 b - 0 1 + source: python-api + evaluations: 812429 + duration: 37919.5 + metrics: + wallMs: 37854.75950001273 + evalsPerMs: 21.461739837489304 + rootMoves: 50 + negamaxNodes: 511658 + quiescenceNodes: 860918 + movegenCalls: 546527 + tacticalMovegenCalls: 445280 + legalContextCalls: 546527 + ttHits: 201885 + ttCutoffs: 186242 + betaCutoffs: 267192 + ttEntries: 830673 + negamaxTtHits: 146314 + quiescenceTtHits: 55571 + negamaxTtCutoffs: 137753 + quiescenceTtCutoffs: 48489 + negamaxBetaCutoffs: 86255 + quiescenceBetaCutoffs: 180937 + qsearchStandPatCutoffs: 367149 + qsearchDeltaPruneChecks: 52268 + qsearchDeltaPruneSkips: 45320 + qsearchNodesWithMoves: 378048 + qsearchGeneratedMoves: 976535 + pvsResearches: 2420 + negamaxFrontierFutilityChecks: 322309 + negamaxFrontierFutilitySkips: 30807 + nullMoveAttempts: 2367 + nullMoveCutoffs: 1823 + - san: g4g5 + beforeFen: b/qbk/n1b1n/r5r/pppppp1pp/11/4PP1p3/6P4/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w + h6 0 2 + source: rust-worker + evaluations: 8490961 + duration: 141525.09999999404 + metrics: null + - san: h5g5 + beforeFen: b/qbk/n1b1n/r5r/pppppp1pp/11/4PPPp3/11/3P1B1P3/2P2B2P2/1PRNQBKNRP1 b - 0 2 + source: python-api + evaluations: 1193536 + duration: 52456 + metrics: + wallMs: 52376.90509998356 + evalsPerMs: 22.787447973904335 + rootMoves: 53 + negamaxNodes: 582330 + quiescenceNodes: 1302178 + movegenCalls: 690560 + tacticalMovegenCalls: 514609 + legalContextCalls: 690560 + ttHits: 246333 + ttCutoffs: 234147 + betaCutoffs: 341982 + ttEntries: 1311912 + negamaxTtHits: 130306 + quiescenceTtHits: 116027 + negamaxTtCutoffs: 125505 + quiescenceTtCutoffs: 108642 + negamaxBetaCutoffs: 163776 + quiescenceBetaCutoffs: 178206 + qsearchStandPatCutoffs: 678927 + qsearchDeltaPruneChecks: 148590 + qsearchDeltaPruneSkips: 142984 + qsearchNodesWithMoves: 470874 + qsearchGeneratedMoves: 1573666 + pvsResearches: 1347 + negamaxFrontierFutilityChecks: 180938 + negamaxFrontierFutilitySkips: 14112 + nullMoveAttempts: 3461 + nullMoveCutoffs: 557 + - san: f5g5 + beforeFen: b/qbk/n1b1n/r5r/pppppp1pp/11/4PPp4/11/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w - 0 3 + source: rust-worker + evaluations: 8373371 + duration: 163475.40000000596 + metrics: null + - san: i7i5 + beforeFen: b/qbk/n1b1n/r5r/pppppp1pp/11/4P1P4/11/3P1B1P3/2P2B2P2/1PRNQBKNRP1 b - 0 3 + source: python-api + evaluations: 1536362 + duration: 78424.40000000596 + metrics: + wallMs: 78291.50449999725 + evalsPerMs: 19.62361063070456 + rootMoves: 52 + negamaxNodes: 657672 + quiescenceNodes: 1667430 + movegenCalls: 985475 + tacticalMovegenCalls: 841319 + legalContextCalls: 985475 + ttHits: 292647 + ttCutoffs: 270855 + betaCutoffs: 487292 + ttEntries: 1574207 + negamaxTtHits: 149073 + quiescenceTtHits: 143574 + negamaxTtCutoffs: 139787 + quiescenceTtCutoffs: 131068 + negamaxBetaCutoffs: 124568 + quiescenceBetaCutoffs: 362724 + qsearchStandPatCutoffs: 695043 + qsearchDeltaPruneChecks: 137735 + qsearchDeltaPruneSkips: 127107 + qsearchNodesWithMoves: 757768 + qsearchGeneratedMoves: 2303961 + pvsResearches: 4013 + negamaxFrontierFutilityChecks: 386799 + negamaxFrontierFutilitySkips: 53288 + nullMoveAttempts: 2875 + nullMoveCutoffs: 1990 + - san: c2c4 + beforeFen: b/qbk/n1b1n/r5r/pppppp2p/11/4P1P1p2/11/3P1B1P3/2P2B2P2/1PRNQBKNRP1 w i6 0 4 + source: rust-worker + evaluations: 8975837 + duration: 159192.30000001192 + metrics: null + - san: c7c5 + beforeFen: b/qbk/n1b1n/r5r/pppppp2p/11/4P1P1p2/2P8/3P1B1P3/5B2P2/1PRNQBKNRP1 b c3 0 4 + source: python-api + evaluations: 1758823 + duration: 75556 + metrics: + wallMs: 75414.74940002081 + evalsPerMs: 23.322002844174598 + rootMoves: 49 + negamaxNodes: 635323 + quiescenceNodes: 1851437 + movegenCalls: 1097512 + tacticalMovegenCalls: 958204 + legalContextCalls: 1097512 + ttHits: 246345 + ttCutoffs: 223432 + betaCutoffs: 544864 + ttEntries: 1794642 + negamaxTtHits: 140839 + quiescenceTtHits: 105506 + negamaxTtCutoffs: 130818 + quiescenceTtCutoffs: 92614 + negamaxBetaCutoffs: 117965 + quiescenceBetaCutoffs: 426899 + qsearchStandPatCutoffs: 800619 + qsearchDeltaPruneChecks: 167636 + qsearchDeltaPruneSkips: 156032 + qsearchNodesWithMoves: 880026 + qsearchGeneratedMoves: 2887853 + pvsResearches: 4690 + negamaxFrontierFutilityChecks: 389473 + negamaxFrontierFutilitySkips: 78206 + nullMoveAttempts: 2500 + nullMoveCutoffs: 1822 + - san: d3d5 + beforeFen: b/qbk/n1b1n/r5r/p1pppp2p/11/2p1P1P1p2/2P8/3P1B1P3/5B2P2/1PRNQBKNRP1 w + c6 0 5 + source: rust-worker + evaluations: 8664826 + duration: 151253 + metrics: null + - san: d7d6 + beforeFen: b/qbk/n1b1n/r5r/p1pppp2p/11/2pPP1P1p2/2P8/5B1P3/5B2P2/1PRNQBKNRP1 b d4 0 5 + source: python-api + evaluations: 1793548 + duration: 68586.59999999404 + metrics: + wallMs: 68475.12570000254 + evalsPerMs: 26.192693794499068 + rootMoves: 49 + negamaxNodes: 499899 + quiescenceNodes: 1881492 + movegenCalls: 969340 + tacticalMovegenCalls: 824726 + legalContextCalls: 969340 + ttHits: 220326 + ttCutoffs: 199985 + betaCutoffs: 487943 + ttEntries: 1875742 + negamaxTtHits: 119245 + quiescenceTtHits: 101081 + negamaxTtCutoffs: 112041 + quiescenceTtCutoffs: 87944 + negamaxBetaCutoffs: 132439 + quiescenceBetaCutoffs: 355504 + qsearchStandPatCutoffs: 968822 + qsearchDeltaPruneChecks: 204658 + qsearchDeltaPruneSkips: 198470 + qsearchNodesWithMoves: 783684 + qsearchGeneratedMoves: 3055515 + pvsResearches: 2281 + negamaxFrontierFutilityChecks: 163267 + negamaxFrontierFutilitySkips: 8941 + nullMoveAttempts: 2817 + nullMoveCutoffs: 918 + - san: e1d2 + beforeFen: b/qbk/n1b1n/r5r/p2ppp2p/3p7/2pPP1P1p2/2P8/5B1P3/5B2P2/1PRNQBKNRP1 w - 0 6 + source: rust-worker + evaluations: 4460449 + duration: 95089.10000002384 + metrics: null + - san: i5i4 + beforeFen: b/qbk/n1b1n/r5r/p2ppp2p/3p7/2pPP1P1p2/2P8/5B1P3/3Q1B2P2/1PRN1BKNRP1 b - 1 6 + source: python-api + evaluations: 6957404 + duration: 229737.90000000596 + metrics: + wallMs: 229094.97569999075 + evalsPerMs: 30.369081551186024 + rootMoves: 47 + negamaxNodes: 664003 + quiescenceNodes: 7358271 + movegenCalls: 4219265 + tacticalMovegenCalls: 4084466 + legalContextCalls: 4219265 + ttHits: 602219 + ttCutoffs: 557949 + betaCutoffs: 2137393 + ttEntries: 6829384 + negamaxTtHits: 169052 + quiescenceTtHits: 433167 + negamaxTtCutoffs: 157082 + quiescenceTtCutoffs: 400867 + negamaxBetaCutoffs: 121850 + quiescenceBetaCutoffs: 2015543 + qsearchStandPatCutoffs: 2872938 + qsearchDeltaPruneChecks: 1479713 + qsearchDeltaPruneSkips: 1450337 + qsearchNodesWithMoves: 3860340 + qsearchGeneratedMoves: 15435149 + pvsResearches: 5580 + negamaxFrontierFutilityChecks: 347797 + negamaxFrontierFutilitySkips: 14446 + nullMoveAttempts: 2233 + nullMoveCutoffs: 1671 + - san: h3h5 + beforeFen: b/qbk/n1b1n/r5r/p2ppp2p/3p7/2pPP1P4/2P5p2/5B1P3/3Q1B2P2/1PRN1BKNRP1 w - 0 7 + source: rust-worker + evaluations: 4755592 + duration: 196663.80000001192 + metrics: null + - san: k7k5 + beforeFen: b/qbk/n1b1n/r5r/p2ppp2p/3p7/2pPP1PP3/2P5p2/5B5/3Q1B2P2/1PRN1BKNRP1 b h4 0 7 + source: python-api + evaluations: 15353820 + duration: 487418.3000000119 + metrics: + wallMs: 486507.08119999035 + evalsPerMs: 31.55929398217422 + rootMoves: 50 + negamaxNodes: 849351 + quiescenceNodes: 16278157 + movegenCalls: 9117488 + tacticalMovegenCalls: 8947572 + legalContextCalls: 9117488 + ttHits: 1192920 + ttCutoffs: 1101633 + betaCutoffs: 4603402 + ttEntries: 14963939 + negamaxTtHits: 196565 + quiescenceTtHits: 996355 + negamaxTtCutoffs: 177296 + quiescenceTtCutoffs: 924337 + negamaxBetaCutoffs: 156213 + quiescenceBetaCutoffs: 4447189 + qsearchStandPatCutoffs: 6406248 + qsearchDeltaPruneChecks: 3932340 + qsearchDeltaPruneSkips: 3849515 + qsearchNodesWithMoves: 8468755 + qsearchGeneratedMoves: 34889523 + pvsResearches: 8375 + negamaxFrontierFutilityChecks: 429222 + negamaxFrontierFutilitySkips: 19695 + nullMoveAttempts: 1984 + nullMoveCutoffs: 1108 + - san: f2e3 + beforeFen: b/qbk/n1b1n/r5r/p2ppp3/3p7/2pPP1PP1p1/2P5p2/5B5/3Q1B2P2/1PRN1BKNRP1 w + k6 0 8 + source: rust-worker + evaluations: 5758742 + duration: 260136.79999998212 + metrics: null + - san: i8i7 + beforeFen: b/qbk/n1b1n/r5r/p2ppp3/3p7/2pPP1PP1p1/2P5p2/4BB5/3Q4P2/1PRN1BKNRP1 b - 1 8 + source: python-api + evaluations: 1080741 + duration: 33559.5 + metrics: + wallMs: 33494.35049999738 + evalsPerMs: 32.26636683102974 + rootMoves: 51 + negamaxNodes: 346202 + quiescenceNodes: 1132139 + movegenCalls: 644139 + tacticalMovegenCalls: 554156 + legalContextCalls: 644139 + ttHits: 135685 + ttCutoffs: 122032 + betaCutoffs: 317426 + ttEntries: 1123022 + negamaxTtHits: 75713 + quiescenceTtHits: 59972 + negamaxTtCutoffs: 70634 + quiescenceTtCutoffs: 51398 + negamaxBetaCutoffs: 82679 + quiescenceBetaCutoffs: 234747 + qsearchStandPatCutoffs: 526585 + qsearchDeltaPruneChecks: 472980 + qsearchDeltaPruneSkips: 433149 + qsearchNodesWithMoves: 518960 + qsearchGeneratedMoves: 2165216 + pvsResearches: 1304 + negamaxFrontierFutilityChecks: 149666 + negamaxFrontierFutilitySkips: 15483 + nullMoveAttempts: 3065 + nullMoveCutoffs: 1921 + - san: d5c5 + beforeFen: b/qbk/n1b1n/r6/p2ppp1r1/3p7/2pPP1PP1p1/2P5p2/4BB5/3Q4P2/1PRN1BKNRP1 w - 2 9 + source: rust-worker + evaluations: 4902196 + duration: 222723.79999998212 + metrics: null + - san: d6c5 + beforeFen: b/qbk/n1b1n/r6/p2ppp1r1/3p7/2P1P1PP1p1/2P5p2/4BB5/3Q4P2/1PRN1BKNRP1 b - 0 9 + source: python-api + evaluations: 3225371 + duration: 100482.79999998212 + metrics: + wallMs: 100281.9545000093 + evalsPerMs: 32.16302490394422 + rootMoves: 55 + negamaxNodes: 764493 + quiescenceNodes: 3495614 + movegenCalls: 1922250 + tacticalMovegenCalls: 1718689 + legalContextCalls: 1922250 + ttHits: 512721 + ttCutoffs: 421193 + betaCutoffs: 966017 + ttEntries: 3255046 + negamaxTtHits: 179590 + quiescenceTtHits: 333131 + negamaxTtCutoffs: 150950 + quiescenceTtCutoffs: 270243 + negamaxBetaCutoffs: 187668 + quiescenceBetaCutoffs: 778349 + qsearchStandPatCutoffs: 1506682 + qsearchDeltaPruneChecks: 829855 + qsearchDeltaPruneSkips: 805673 + qsearchNodesWithMoves: 1622769 + qsearchGeneratedMoves: 6735182 + pvsResearches: 3233 + negamaxFrontierFutilityChecks: 284643 + negamaxFrontierFutilitySkips: 35682 + nullMoveAttempts: 1576 + nullMoveCutoffs: 841 + - san: k1k3 + beforeFen: b/qbk/n1b1n/r6/p2ppp1r1/11/2p1P1PP1p1/2P5p2/4BB5/3Q4P2/1PRN1BKNRP1 w - 0 10 + source: rust-worker + evaluations: 18244123 + duration: 818011.7999999821 + metrics: null + - san: f11k3 + beforeFen: b/qbk/n1b1n/r6/p2ppp1r1/11/2p1P1PP1p1/2P5p2/4BB3P1/3Q4P2/1PRN1BKNR2 b + k2 0 10 + source: python-api + evaluations: 2541015 + duration: 74334.59999999404 + metrics: + wallMs: 74173.11819997849 + evalsPerMs: 34.25789641402371 + rootMoves: 53 + negamaxNodes: 611349 + quiescenceNodes: 2680684 + movegenCalls: 1546842 + tacticalMovegenCalls: 1360045 + legalContextCalls: 1546842 + ttHits: 283244 + ttCutoffs: 254559 + betaCutoffs: 763509 + ttEntries: 2602044 + negamaxTtHits: 126912 + quiescenceTtHits: 156332 + negamaxTtCutoffs: 114890 + quiescenceTtCutoffs: 139669 + negamaxBetaCutoffs: 144336 + quiescenceBetaCutoffs: 619173 + qsearchStandPatCutoffs: 1180970 + qsearchDeltaPruneChecks: 542570 + qsearchDeltaPruneSkips: 526426 + qsearchNodesWithMoves: 1288378 + qsearchGeneratedMoves: 4967529 + pvsResearches: 2257 + negamaxFrontierFutilityChecks: 318435 + negamaxFrontierFutilitySkips: 105325 + nullMoveAttempts: 3337 + nullMoveCutoffs: 1784 + - san: h1g4 + beforeFen: 1/qbk/n1b1n/r6/p2ppp1r1/11/2p1P1PP1p1/2P5p2/4BB3b1/3Q4P2/1PRN1BKNR2 w + - 0 11 + source: rust-worker + evaluations: 19579485 + duration: 924410.3999999762 + metrics: null + - san: d9f8 + beforeFen: 1/qbk/n1b1n/r6/p2ppp1r1/11/2p1P1PP1p1/2P3N1p2/4BB3b1/3Q4P2/1PRN1BK1R2 + b - 1 11 + source: python-api + evaluations: 5507590 + duration: 146706.59999999404 + metrics: + wallMs: 146405.48369998578 + evalsPerMs: 37.61874118927237 + rootMoves: 59 + negamaxNodes: 819506 + quiescenceNodes: 5824151 + movegenCalls: 3212771 + tacticalMovegenCalls: 2997386 + legalContextCalls: 3212771 + ttHits: 497227 + ttCutoffs: 454891 + betaCutoffs: 1603666 + ttEntries: 5514858 + negamaxTtHits: 152871 + quiescenceTtHits: 344356 + negamaxTtCutoffs: 138330 + quiescenceTtCutoffs: 316561 + negamaxBetaCutoffs: 182441 + quiescenceBetaCutoffs: 1421225 + qsearchStandPatCutoffs: 2510204 + qsearchDeltaPruneChecks: 1196574 + qsearchDeltaPruneSkips: 1157045 + qsearchNodesWithMoves: 2843932 + qsearchGeneratedMoves: 11457875 + pvsResearches: 5318 + negamaxFrontierFutilityChecks: 415163 + negamaxFrontierFutilitySkips: 70828 + nullMoveAttempts: 3887 + nullMoveCutoffs: 2350 + - san: g4k3 + beforeFen: 1/qbk/2b1n/r2n3/p2ppp1r1/11/2p1P1PP1p1/2P3N1p2/4BB3b1/3Q4P2/1PRN1BK1R2 + w - 2 12 + source: rust-worker + evaluations: 21968450 + duration: 1053760.099999994 + metrics: null + - san: f8e5 + beforeFen: 1/qbk/2b1n/r2n3/p2ppp1r1/11/2p1P1PP1p1/2P5p2/4BB3N1/3Q4P2/1PRN1BK1R2 + b - 0 12 + source: python-api + evaluations: 1236812 + duration: 44725.40000000596 + metrics: + wallMs: 44633.99619999109 + evalsPerMs: 27.710088840314214 + rootMoves: 54 + negamaxNodes: 694621 + quiescenceNodes: 1330458 + movegenCalls: 701069 + tacticalMovegenCalls: 519228 + legalContextCalls: 701069 + ttHits: 294915 + ttCutoffs: 276500 + betaCutoffs: 355083 + ttEntries: 1370806 + negamaxTtHits: 191577 + quiescenceTtHits: 103338 + negamaxTtCutoffs: 182854 + quiescenceTtCutoffs: 93646 + negamaxBetaCutoffs: 159477 + quiescenceBetaCutoffs: 195606 + qsearchStandPatCutoffs: 717584 + qsearchDeltaPruneChecks: 315926 + qsearchDeltaPruneSkips: 306317 + qsearchNodesWithMoves: 495215 + qsearchGeneratedMoves: 2022632 + pvsResearches: 1621 + negamaxFrontierFutilityChecks: 383257 + negamaxFrontierFutilitySkips: 137084 + nullMoveAttempts: 1487 + nullMoveCutoffs: 823 + - san: d2e4 + beforeFen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p1n1PP1p1/2P5p2/4BB3N1/3Q4P2/1PRN1BK1R2 w - 0 13 + source: rust-worker + evaluations: 17466742 + duration: 727842.1999999881 + metrics: null + - san: e5h4 + beforeFen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p1n1PP1p1/2P1Q3p2/4BB3N1/8P2/1PRN1BK1R2 b - 1 13 + source: python-api + evaluations: 674609 + duration: 30617.600000023842 + metrics: + wallMs: 30561.093399999663 + evalsPerMs: 22.074112047313314 + rootMoves: 59 + negamaxNodes: 410248 + quiescenceNodes: 709116 + movegenCalls: 425582 + tacticalMovegenCalls: 311595 + legalContextCalls: 425582 + ttHits: 118097 + ttCutoffs: 105540 + betaCutoffs: 210124 + ttEntries: 758622 + negamaxTtHits: 76693 + quiescenceTtHits: 41404 + negamaxTtCutoffs: 71033 + quiescenceTtCutoffs: 34507 + negamaxBetaCutoffs: 101448 + quiescenceBetaCutoffs: 108676 + qsearchStandPatCutoffs: 363014 + qsearchDeltaPruneChecks: 482857 + qsearchDeltaPruneSkips: 472067 + qsearchNodesWithMoves: 296517 + qsearchGeneratedMoves: 1387269 + pvsResearches: 1005 + negamaxFrontierFutilityChecks: 230105 + negamaxFrontierFutilitySkips: 70950 + nullMoveAttempts: 3465 + nullMoveCutoffs: 2340 + - san: e4g4 + beforeFen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p3PP1p1/2P1Q2np2/4BB3N1/8P2/1PRN1BK1R2 w - 2 14 + source: rust-worker + evaluations: 17239421 + duration: 745917.5 + metrics: null + - san: h4i1 + beforeFen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p3PP1p1/2P3Qnp2/4BB3N1/8P2/1PRN1BK1R2 b - 3 14 + source: python-api + evaluations: 853002 + duration: 44166.09999999404 + metrics: + wallMs: 44083.698600006755 + evalsPerMs: 19.349601487382216 + rootMoves: 58 + negamaxNodes: 651597 + quiescenceNodes: 891456 + movegenCalls: 608259 + tacticalMovegenCalls: 424305 + legalContextCalls: 608259 + ttHits: 198530 + ttCutoffs: 176878 + betaCutoffs: 300086 + ttEntries: 988998 + negamaxTtHits: 148943 + quiescenceTtHits: 49587 + negamaxTtCutoffs: 138424 + quiescenceTtCutoffs: 38454 + negamaxBetaCutoffs: 160260 + quiescenceBetaCutoffs: 139826 + qsearchStandPatCutoffs: 428697 + qsearchDeltaPruneChecks: 707322 + qsearchDeltaPruneSkips: 697515 + qsearchNodesWithMoves: 402860 + qsearchGeneratedMoves: 1738553 + pvsResearches: 1537 + negamaxFrontierFutilityChecks: 445336 + negamaxFrontierFutilitySkips: 225909 + nullMoveAttempts: 1477 + nullMoveCutoffs: 943 + - san: k3i1 + beforeFen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p3PP1p1/2P3Q1p2/4BB3N1/8P2/1PRN1BK1n2 w - 0 15 + source: rust-worker + evaluations: 36649786 + duration: 1756173.599999994 + metrics: null + - san: b7b5 + beforeFen: 1/qbk/2b1n/r6/p2ppp1r1/11/2p3PP1p1/2P3Q1p2/4BB5/8P2/1PRN1BK1N2 b - 0 15 + source: python-api + evaluations: 1239731 + duration: 44255.59999999404 + metrics: + wallMs: 44162.5892999873 + evalsPerMs: 28.071972673041532 + rootMoves: 48 + negamaxNodes: 434171 + quiescenceNodes: 1354016 + movegenCalls: 754239 + tacticalMovegenCalls: 636779 + legalContextCalls: 754239 + ttHits: 215416 + ttCutoffs: 192733 + betaCutoffs: 375133 + ttEntries: 1290894 + negamaxTtHits: 87628 + quiescenceTtHits: 127788 + negamaxTtCutoffs: 78448 + quiescenceTtCutoffs: 114285 + negamaxBetaCutoffs: 104550 + quiescenceBetaCutoffs: 270583 + qsearchStandPatCutoffs: 602952 + qsearchDeltaPruneChecks: 281796 + qsearchDeltaPruneSkips: 272951 + qsearchNodesWithMoves: 593509 + qsearchGeneratedMoves: 2258768 + pvsResearches: 2144 + negamaxFrontierFutilityChecks: 186763 + negamaxFrontierFutilitySkips: 19561 + nullMoveAttempts: 2689 + nullMoveCutoffs: 1405 + - san: c1d2 + beforeFen: 1/qbk/2b1n/r6/3ppp1r1/11/1pp3PP1p1/2P3Q1p2/4BB5/8P2/1PRN1BK1N2 w - 0 16 + source: rust-worker + evaluations: 18854984 + duration: 867161.900000006 + metrics: null + - san: b5b4 + beforeFen: 1/qbk/2b1n/r6/3ppp1r1/11/1pp3PP1p1/2P3Q1p2/4BB5/3R4P2/1P1N1BK1N2 b - 1 16 + source: python-api + evaluations: 1560318 + duration: 54216.90000000596 + metrics: + wallMs: 54108.1903000013 + evalsPerMs: 28.837002149745942 + rootMoves: 50 + negamaxNodes: 489360 + quiescenceNodes: 1677057 + movegenCalls: 850091 + tacticalMovegenCalls: 727853 + legalContextCalls: 850091 + ttHits: 226252 + ttCutoffs: 197845 + betaCutoffs: 423253 + ttEntries: 1617115 + negamaxTtHits: 92410 + quiescenceTtHits: 133842 + negamaxTtCutoffs: 81106 + quiescenceTtCutoffs: 116739 + negamaxBetaCutoffs: 108696 + quiescenceBetaCutoffs: 314557 + qsearchStandPatCutoffs: 832465 + qsearchDeltaPruneChecks: 291383 + qsearchDeltaPruneSkips: 278046 + qsearchNodesWithMoves: 688427 + qsearchGeneratedMoves: 2540151 + pvsResearches: 2347 + negamaxFrontierFutilityChecks: 278116 + negamaxFrontierFutilitySkips: 68241 + nullMoveAttempts: 3090 + nullMoveCutoffs: 2132 + - san: e3c5 + beforeFen: 1/qbk/2b1n/r6/3ppp1r1/11/2p3PP1p1/1pP3Q1p2/4BB5/3R4P2/1P1N1BK1N2 w - 0 17 + source: rust-worker + evaluations: 12692997 + duration: 640951.3000000119 + metrics: null + - san: b4c4 + beforeFen: 1/qbk/2b1n/r6/3ppp1r1/11/2B3PP1p1/1pP3Q1p2/5B5/3R4P2/1P1N1BK1N2 b - 0 17 + source: python-api + evaluations: 1443619 + duration: 42272.19999998808 + metrics: + wallMs: 42174.51010001241 + evalsPerMs: 34.22965664750129 + rootMoves: 49 + negamaxNodes: 469413 + quiescenceNodes: 1555830 + movegenCalls: 890113 + tacticalMovegenCalls: 742221 + legalContextCalls: 890113 + ttHits: 211732 + ttCutoffs: 188989 + betaCutoffs: 440169 + ttEntries: 1511329 + negamaxTtHits: 85816 + quiescenceTtHits: 125916 + negamaxTtCutoffs: 76778 + quiescenceTtCutoffs: 112211 + negamaxBetaCutoffs: 129374 + quiescenceBetaCutoffs: 310795 + qsearchStandPatCutoffs: 701398 + qsearchDeltaPruneChecks: 366587 + qsearchDeltaPruneSkips: 340218 + qsearchNodesWithMoves: 691175 + qsearchGeneratedMoves: 2512385 + pvsResearches: 1328 + negamaxFrontierFutilityChecks: 191325 + negamaxFrontierFutilitySkips: 43899 + nullMoveAttempts: 3606 + nullMoveCutoffs: 2064 + - san: c5a4 + beforeFen: 1/qbk/2b1n/r6/3ppp1r1/11/2B3PP1p1/2p3Q1p2/5B5/3R4P2/1P1N1BK1N2 w - 0 18 + source: rust-worker + evaluations: 20269515 + duration: 1148809.2000000179 + metrics: null + - san: c8e8 + beforeFen: 1/qbk/2b1n/r6/3ppp1r1/11/6PP1p1/B1p3Q1p2/5B5/3R4P2/1P1N1BK1N2 b - 1 18 + source: python-api + evaluations: 977278 + duration: 31676.90000000596 + metrics: + wallMs: 31615.655200002948 + evalsPerMs: 30.911205028574226 + rootMoves: 50 + negamaxNodes: 396868 + quiescenceNodes: 1083084 + movegenCalls: 601734 + tacticalMovegenCalls: 477293 + legalContextCalls: 601734 + ttHits: 190982 + ttCutoffs: 171674 + betaCutoffs: 296895 + ttEntries: 1040970 + negamaxTtHits: 73242 + quiescenceTtHits: 117740 + negamaxTtCutoffs: 65868 + quiescenceTtCutoffs: 105806 + negamaxBetaCutoffs: 107622 + quiescenceBetaCutoffs: 189273 + qsearchStandPatCutoffs: 499985 + qsearchDeltaPruneChecks: 266211 + qsearchDeltaPruneSkips: 251033 + qsearchNodesWithMoves: 441812 + qsearchGeneratedMoves: 1556764 + pvsResearches: 1269 + negamaxFrontierFutilityChecks: 167230 + negamaxFrontierFutilitySkips: 31537 + nullMoveAttempts: 3641 + nullMoveCutoffs: 2412 + - san: g4a5 + beforeFen: 1/qbk/2b1n/2r4/3ppp1r1/11/6PP1p1/B1p3Q1p2/5B5/3R4P2/1P1N1BK1N2 w - 2 19 + source: rust-worker + evaluations: 19938706 + duration: 1129732.099999994 + metrics: null + - san: e8e9 + beforeFen: 1/qbk/2b1n/2r4/3ppp1r1/11/Q5PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 b - 3 19 + source: python-api + evaluations: 614708 + duration: 23140.30000001192 + metrics: + wallMs: 23095.364500011783 + evalsPerMs: 26.616077005395884 + rootMoves: 46 + negamaxNodes: 288697 + quiescenceNodes: 657764 + movegenCalls: 428891 + tacticalMovegenCalls: 332327 + legalContextCalls: 428891 + ttHits: 86076 + ttCutoffs: 76715 + betaCutoffs: 210355 + ttEntries: 675521 + negamaxTtHits: 37607 + quiescenceTtHits: 48469 + negamaxTtCutoffs: 33659 + quiescenceTtCutoffs: 43056 + negamaxBetaCutoffs: 86006 + quiescenceBetaCutoffs: 124349 + qsearchStandPatCutoffs: 282381 + qsearchDeltaPruneChecks: 292700 + qsearchDeltaPruneSkips: 282088 + qsearchNodesWithMoves: 309286 + qsearchGeneratedMoves: 1051408 + pvsResearches: 968 + negamaxFrontierFutilityChecks: 131503 + negamaxFrontierFutilitySkips: 46340 + nullMoveAttempts: 3407 + nullMoveCutoffs: 2417 + - san: a5b5 + beforeFen: 1/qbk/1rb1n/7/3ppp1r1/11/Q5PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 w - 4 20 + source: rust-worker + evaluations: 8655830 + duration: 455712 + metrics: null + - san: f10d6 + beforeFen: 1/qbk/1rb1n/7/3ppp1r1/11/1Q4PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 b - 5 20 + source: python-api + evaluations: 1073277 + duration: 36655.59999999404 + metrics: + wallMs: 36577.90059997933 + evalsPerMs: 29.342225288911372 + rootMoves: 47 + negamaxNodes: 406215 + quiescenceNodes: 1157234 + movegenCalls: 684377 + tacticalMovegenCalls: 553794 + legalContextCalls: 684377 + ttHits: 154266 + ttCutoffs: 133483 + betaCutoffs: 336055 + ttEntries: 1142588 + negamaxTtHits: 57713 + quiescenceTtHits: 96553 + negamaxTtCutoffs: 49526 + quiescenceTtCutoffs: 83957 + negamaxBetaCutoffs: 116859 + quiescenceBetaCutoffs: 219196 + qsearchStandPatCutoffs: 519483 + qsearchDeltaPruneChecks: 440167 + qsearchDeltaPruneSkips: 420910 + qsearchNodesWithMoves: 514391 + qsearchGeneratedMoves: 1815251 + pvsResearches: 2393 + negamaxFrontierFutilityChecks: 181713 + negamaxFrontierFutilitySkips: 57906 + nullMoveAttempts: 3690 + nullMoveCutoffs: 2483 + - san: b5c5 + beforeFen: 1/q1k/1rb1n/7/3ppp1r1/3b7/1Q4PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 w - 6 21 + source: rust-worker + evaluations: 13305942 + duration: 583797.6000000238 + metrics: null + - san: e9c7 + beforeFen: 1/q1k/1rb1n/7/3ppp1r1/3b7/2Q3PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 b - 7 21 + source: python-api + evaluations: 1904674 + duration: 68849.59999999404 + metrics: + wallMs: 68709.92409999599 + evalsPerMs: 27.720507989909294 + rootMoves: 55 + negamaxNodes: 699350 + quiescenceNodes: 2098881 + movegenCalls: 1147819 + tacticalMovegenCalls: 979591 + legalContextCalls: 1147819 + ttHits: 404581 + ttCutoffs: 347935 + betaCutoffs: 570874 + ttEntries: 1964435 + negamaxTtHits: 177629 + quiescenceTtHits: 226952 + negamaxTtCutoffs: 153728 + quiescenceTtCutoffs: 194207 + negamaxBetaCutoffs: 148805 + quiescenceBetaCutoffs: 422069 + qsearchStandPatCutoffs: 925083 + qsearchDeltaPruneChecks: 644934 + qsearchDeltaPruneSkips: 615536 + qsearchNodesWithMoves: 919370 + qsearchGeneratedMoves: 3178433 + pvsResearches: 2918 + negamaxFrontierFutilityChecks: 382300 + negamaxFrontierFutilitySkips: 67331 + nullMoveAttempts: 3973 + nullMoveCutoffs: 2538 + - san: c5a3 + beforeFen: 1/q1k/2b1n/7/1r1ppp1r1/3b7/2Q3PP1p1/B1p5p2/5B5/3R4P2/1P1N1BK1N2 w - 8 22 + source: rust-worker + evaluations: 12915373 + duration: 629123.599999994 + metrics: null + - san: e10f10 + beforeFen: 1/q1k/2b1n/7/1r1ppp1r1/3b7/6PP1p1/B1p5p2/Q4B5/3R4P2/1P1N1BK1N2 b - 9 22 + source: python-api + evaluations: 810308 + duration: 26428.90000000596 + metrics: + wallMs: 26374.922699993476 + evalsPerMs: 30.72266824123054 + rootMoves: 60 + negamaxNodes: 365959 + quiescenceNodes: 857138 + movegenCalls: 489756 + tacticalMovegenCalls: 396769 + legalContextCalls: 489756 + ttHits: 141582 + ttCutoffs: 118285 + betaCutoffs: 243091 + ttEntries: 848524 + negamaxTtHits: 82242 + quiescenceTtHits: 59340 + negamaxTtCutoffs: 71455 + quiescenceTtCutoffs: 46830 + negamaxBetaCutoffs: 79594 + quiescenceBetaCutoffs: 163497 + qsearchStandPatCutoffs: 413539 + qsearchDeltaPruneChecks: 270590 + qsearchDeltaPruneSkips: 256041 + qsearchNodesWithMoves: 364112 + qsearchGeneratedMoves: 1307220 + pvsResearches: 1346 + negamaxFrontierFutilityChecks: 233684 + negamaxFrontierFutilitySkips: 76732 + nullMoveAttempts: 4057 + nullMoveCutoffs: 3247 + - san: b1b3 + beforeFen: 1/1qk/2b1n/7/1r1ppp1r1/3b7/6PP1p1/B1p5p2/Q4B5/3R4P2/1P1N1BK1N2 w - 10 23 + source: rust-worker + evaluations: 25172999 + duration: 1266578.900000006 + metrics: null + - san: k5k4 + beforeFen: 1/1qk/2b1n/7/1r1ppp1r1/3b7/6PP1p1/B1p5p2/QP3B5/3R4P2/3N1BK1N2 b - 0 23 + source: python-api + evaluations: 1148653 + duration: 34739.60000002384 + metrics: + wallMs: 34651.03239999735 + evalsPerMs: 33.14917104750068 + rootMoves: 56 + negamaxNodes: 528929 + quiescenceNodes: 1212722 + movegenCalls: 638022 + tacticalMovegenCalls: 529245 + legalContextCalls: 638022 + ttHits: 242248 + ttCutoffs: 205693 + betaCutoffs: 318582 + ttEntries: 1195302 + negamaxTtHits: 159336 + quiescenceTtHits: 82912 + negamaxTtCutoffs: 141624 + quiescenceTtCutoffs: 64069 + negamaxBetaCutoffs: 92591 + quiescenceBetaCutoffs: 225991 + qsearchStandPatCutoffs: 619408 + qsearchDeltaPruneChecks: 352960 + qsearchDeltaPruneSkips: 331291 + qsearchNodesWithMoves: 498193 + qsearchGeneratedMoves: 1829176 + pvsResearches: 2399 + negamaxFrontierFutilityChecks: 378439 + negamaxFrontierFutilitySkips: 102546 + nullMoveAttempts: 3349 + nullMoveCutoffs: 2509 + - san: b3c4 + beforeFen: 1/1qk/2b1n/7/1r1ppp1r1/3b7/6PP3/B1p5pp1/QP3B5/3R4P2/3N1BK1N2 w - 0 24 + source: rust-worker + evaluations: 19613399 + duration: 959871.5 + metrics: null + - san: d6c4 + beforeFen: 1/1qk/2b1n/7/1r1ppp1r1/3b7/6PP3/B1P5pp1/Q4B5/3R4P2/3N1BK1N2 b - 0 24 + source: python-api + evaluations: 818579 + duration: 32510 + metrics: + wallMs: 32440.710599999875 + evalsPerMs: 25.233078587372347 + rootMoves: 56 + negamaxNodes: 490908 + quiescenceNodes: 860899 + movegenCalls: 516571 + tacticalMovegenCalls: 407236 + legalContextCalls: 516571 + ttHits: 184084 + ttCutoffs: 160361 + betaCutoffs: 257220 + ttEntries: 881156 + negamaxTtHits: 129775 + quiescenceTtHits: 54309 + negamaxTtCutoffs: 118041 + quiescenceTtCutoffs: 42320 + negamaxBetaCutoffs: 93103 + quiescenceBetaCutoffs: 164117 + qsearchStandPatCutoffs: 411343 + qsearchDeltaPruneChecks: 243983 + qsearchDeltaPruneSkips: 230559 + qsearchNodesWithMoves: 382794 + qsearchGeneratedMoves: 1220426 + pvsResearches: 1563 + negamaxFrontierFutilityChecks: 365141 + negamaxFrontierFutilitySkips: 127935 + nullMoveAttempts: 3214 + nullMoveCutoffs: 2535 + - san: f1c4 + beforeFen: 1/1qk/2b1n/7/1r1ppp1r1/11/6PP3/B1b5pp1/Q4B5/3R4P2/3N1BK1N2 w - 0 25 + source: rust-worker + evaluations: 69303967 + duration: 3427247.099999994 + metrics: null + - san: c7c4 + beforeFen: 1/1qk/2b1n/7/1r1ppp1r1/11/6PP3/B1B5pp1/Q4B5/3R4P2/3N2K1N2 b - 0 25 + source: python-api + evaluations: 177353 + duration: 9108.40000000596 + metrics: + wallMs: 9085.126600024523 + evalsPerMs: 19.52124695758464 + rootMoves: 52 + negamaxNodes: 164671 + quiescenceNodes: 185716 + movegenCalls: 161883 + tacticalMovegenCalls: 105662 + legalContextCalls: 161883 + ttHits: 38712 + ttCutoffs: 30928 + betaCutoffs: 77325 + ttEntries: 213074 + negamaxTtHits: 26031 + quiescenceTtHits: 12681 + negamaxTtCutoffs: 22565 + quiescenceTtCutoffs: 8363 + negamaxBetaCutoffs: 48056 + quiescenceBetaCutoffs: 29269 + qsearchStandPatCutoffs: 71691 + qsearchDeltaPruneChecks: 123513 + qsearchDeltaPruneSkips: 116275 + qsearchNodesWithMoves: 95436 + qsearchGeneratedMoves: 266519 + pvsResearches: 499 + negamaxFrontierFutilityChecks: 88127 + negamaxFrontierFutilitySkips: 44523 + nullMoveAttempts: 3858 + nullMoveCutoffs: 3277 + - san: f3h2 + beforeFen: 1/1qk/2b1n/7/3ppp1r1/11/6PP3/B1r5pp1/Q4B5/3R4P2/3N2K1N2 w - 0 26 + source: rust-worker + evaluations: 31626873 + duration: 1632190.199999988 + metrics: null + - san: k4k3 + beforeFen: 1/1qk/2b1n/7/3ppp1r1/11/6PP3/B1r5pp1/Q10/3R3BP2/3N2K1N2 b - 1 26 + source: python-api + evaluations: 487567 + duration: 17971.40000000596 + metrics: + wallMs: 17918.949699989753 + evalsPerMs: 27.209574677263525 + rootMoves: 62 + negamaxNodes: 330876 + quiescenceNodes: 507603 + movegenCalls: 342093 + tacticalMovegenCalls: 243735 + legalContextCalls: 342093 + ttHits: 86119 + ttCutoffs: 71529 + betaCutoffs: 161983 + ttEntries: 527505 + negamaxTtHits: 59142 + quiescenceTtHits: 26977 + negamaxTtCutoffs: 51489 + quiescenceTtCutoffs: 20040 + negamaxBetaCutoffs: 73941 + quiescenceBetaCutoffs: 88042 + qsearchStandPatCutoffs: 243828 + qsearchDeltaPruneChecks: 158550 + qsearchDeltaPruneSkips: 148456 + qsearchNodesWithMoves: 212069 + qsearchGeneratedMoves: 625773 + pvsResearches: 1412 + negamaxFrontierFutilityChecks: 203453 + negamaxFrontierFutilitySkips: 67089 + nullMoveAttempts: 3969 + nullMoveCutoffs: 3137 + - san: h2k4 + beforeFen: 1/1qk/2b1n/7/3ppp1r1/11/6PP3/B1r5p2/Q8p1/3R3BP2/3N2K1N2 w - 0 27 + source: rust-worker + evaluations: 36344449 + duration: 1717403.800000012 + metrics: null + - san: g10e10 + beforeFen: 1/1qk/2b1n/7/3ppp1r1/11/6PP3/B1r5pB1/Q8p1/3R4P2/3N2K1N2 b - 1 27 + source: python-api + evaluations: 93434 + duration: 3605.5999999940395 + metrics: + wallMs: 3587.152200023411 + evalsPerMs: 26.046845740024697 + rootMoves: 8 + negamaxNodes: 61513 + quiescenceNodes: 96171 + movegenCalls: 65670 + tacticalMovegenCalls: 48194 + legalContextCalls: 65670 + ttHits: 13828 + ttCutoffs: 12054 + betaCutoffs: 31292 + ttEntries: 100625 + negamaxTtHits: 10386 + quiescenceTtHits: 3442 + negamaxTtCutoffs: 9317 + quiescenceTtCutoffs: 2737 + negamaxBetaCutoffs: 12846 + quiescenceBetaCutoffs: 18446 + qsearchStandPatCutoffs: 45240 + qsearchDeltaPruneChecks: 24826 + qsearchDeltaPruneSkips: 23018 + qsearchNodesWithMoves: 42382 + qsearchGeneratedMoves: 115243 + pvsResearches: 285 + negamaxFrontierFutilityChecks: 41949 + negamaxFrontierFutilitySkips: 13028 + nullMoveAttempts: 421 + nullMoveCutoffs: 352 + - san: g1h1 + beforeFen: 1/kq1/2b1n/7/3ppp1r1/11/6PP3/B1r5pB1/Q8p1/3R4P2/3N2K1N2 w - 2 28 + source: rust-worker + evaluations: 25037916 + duration: 1355147.400000006 + metrics: null + - san: i7k7 + beforeFen: 1/kq1/2b1n/7/3ppp1r1/11/6PP3/B1r5pB1/Q8p1/3R4P2/3N3KN2 b - 3 28 + source: python-api + evaluations: 607289 + duration: 27041.5 + metrics: + wallMs: 26981.309800001327 + evalsPerMs: 22.50776572751743 + rootMoves: 60 + negamaxNodes: 361775 + quiescenceNodes: 633317 + movegenCalls: 440569 + tacticalMovegenCalls: 318480 + legalContextCalls: 440569 + ttHits: 95261 + ttCutoffs: 75923 + betaCutoffs: 212409 + ttEntries: 662162 + negamaxTtHits: 59550 + quiescenceTtHits: 35711 + negamaxTtCutoffs: 49843 + quiescenceTtCutoffs: 26080 + negamaxBetaCutoffs: 93103 + quiescenceBetaCutoffs: 119306 + qsearchStandPatCutoffs: 288757 + qsearchDeltaPruneChecks: 169949 + qsearchDeltaPruneSkips: 160709 + qsearchNodesWithMoves: 285934 + qsearchGeneratedMoves: 813202 + pvsResearches: 1631 + negamaxFrontierFutilityChecks: 215649 + negamaxFrontierFutilitySkips: 83882 + nullMoveAttempts: 3354 + nullMoveCutoffs: 2487 + - san: k4g1 + beforeFen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r5pB1/Q8p1/3R4P2/3N3KN2 w - 4 29 + source: rust-worker + evaluations: 33928487 + duration: 1473705.599999994 + metrics: null + - san: i4i3 + beforeFen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r5p2/Q8p1/3R4P2/3N2BKN2 b - 5 29 + source: python-api + evaluations: 845816 + duration: 34153.09999999404 + metrics: + wallMs: 34068.70049997815 + evalsPerMs: 24.82677611963927 + rootMoves: 61 + negamaxNodes: 519873 + quiescenceNodes: 888734 + movegenCalls: 604623 + tacticalMovegenCalls: 446798 + legalContextCalls: 604623 + ttHits: 160009 + ttCutoffs: 136991 + betaCutoffs: 293494 + ttEntries: 919743 + negamaxTtHits: 105632 + quiescenceTtHits: 54377 + negamaxTtCutoffs: 94039 + quiescenceTtCutoffs: 42952 + negamaxBetaCutoffs: 120923 + quiescenceBetaCutoffs: 172571 + qsearchStandPatCutoffs: 398984 + qsearchDeltaPruneChecks: 247307 + qsearchDeltaPruneSkips: 234387 + qsearchNodesWithMoves: 405842 + qsearchGeneratedMoves: 1155974 + pvsResearches: 2415 + negamaxFrontierFutilityChecks: 302708 + negamaxFrontierFutilitySkips: 93127 + nullMoveAttempts: 3393 + nullMoveCutoffs: 2135 + - san: i1g4 + beforeFen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r8/Q7pp1/3R4P2/3N2BKN2 w - 0 30 + source: rust-worker + evaluations: 37259890 + duration: 1657395.7999999821 + metrics: null + - san: k3k2 + beforeFen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r3N4/Q7pp1/3R4P2/3N2BK3 b - 1 30 + source: python-api + evaluations: 816400 + duration: 29734.90000000596 + metrics: + wallMs: 29672.815999976592 + evalsPerMs: 27.513398121723398 + rootMoves: 62 + negamaxNodes: 496813 + quiescenceNodes: 867866 + movegenCalls: 559990 + tacticalMovegenCalls: 409090 + legalContextCalls: 559990 + ttHits: 173740 + ttCutoffs: 147741 + betaCutoffs: 276697 + ttEntries: 893480 + negamaxTtHits: 109289 + quiescenceTtHits: 64451 + negamaxTtCutoffs: 96231 + quiescenceTtCutoffs: 51510 + negamaxBetaCutoffs: 120641 + quiescenceBetaCutoffs: 156056 + qsearchStandPatCutoffs: 407266 + qsearchDeltaPruneChecks: 316523 + qsearchDeltaPruneSkips: 301026 + qsearchNodesWithMoves: 373472 + qsearchGeneratedMoves: 1265737 + pvsResearches: 1849 + negamaxFrontierFutilityChecks: 322668 + negamaxFrontierFutilitySkips: 130715 + nullMoveAttempts: 3499 + nullMoveCutoffs: 2242 + - san: i2k2 + beforeFen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r3N4/Q7p2/3R4Pp1/3N2BK3 w - 0 31 + source: rust-worker + evaluations: 47082614 + duration: 2561976.800000012 + metrics: null + - san: i3k2 + beforeFen: 1/kq1/2b1n/7/3ppp2r/11/6PP3/B1r3N4/Q7p2/3R5P1/3N2BK3 b - 0 31 + source: python-api + evaluations: 537865 + duration: 24692.30000001192 + metrics: + wallMs: 24649.88290000474 + evalsPerMs: 21.820184792841207 + rootMoves: 65 + negamaxNodes: 401064 + quiescenceNodes: 566449 + movegenCalls: 456764 + tacticalMovegenCalls: 298937 + legalContextCalls: 456764 + ttHits: 106299 + ttCutoffs: 87898 + betaCutoffs: 219749 + ttEntries: 618689 + negamaxTtHits: 68161 + quiescenceTtHits: 38138 + negamaxTtCutoffs: 59286 + quiescenceTtCutoffs: 28612 + negamaxBetaCutoffs: 123724 + quiescenceBetaCutoffs: 96025 + qsearchStandPatCutoffs: 238900 + qsearchDeltaPruneChecks: 293054 + qsearchDeltaPruneSkips: 270783 + qsearchNodesWithMoves: 262019 + qsearchGeneratedMoves: 864579 + pvsResearches: 1079 + negamaxFrontierFutilityChecks: 202000 + negamaxFrontierFutilitySkips: 94359 + nullMoveAttempts: 3739 + nullMoveCutoffs: 2461 diff --git a/results/2.1.003/measurement-capture-storm-qsearch-delta-prune-v2.yaml b/results/2.1.003/measurement-capture-storm-qsearch-delta-prune-v2.yaml new file mode 100644 index 00000000..7d1e3594 --- /dev/null +++ b/results/2.1.003/measurement-capture-storm-qsearch-delta-prune-v2.yaml @@ -0,0 +1,103 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:35:56.836138+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summaries: + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 353.1545 + units: 8261 + unitsLabel: evals + unitsPerMs: 23.392028 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 4 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5c8 + score: -19.200000000000003 + metrics: + wallMs: 351.0706997476518 + evalsPerMs: 23.530872858196293 + rootMoves: 36 + negamaxNodes: 15371 + quiescenceNodes: 8592 + movegenCalls: 12437 + tacticalMovegenCalls: 2373 + legalContextCalls: 12437 + ttHits: 6331 + ttCutoffs: 5652 + betaCutoffs: 2414 + negamaxTtHits: 5692 + quiescenceTtHits: 639 + negamaxTtCutoffs: 5308 + quiescenceTtCutoffs: 344 + negamaxBetaCutoffs: 1857 + quiescenceBetaCutoffs: 557 + qsearchStandPatCutoffs: 5875 + qsearchDeltaPruneChecks: 194 + qsearchDeltaPruneSkips: 133 + qsearchNodesWithMoves: 1068 + qsearchGeneratedMoves: 1463 + pvsResearches: 200 + negamaxFrontierFutilityChecks: 9808 + negamaxFrontierFutilitySkips: 1642 + ttEntries: 9217 + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 1149.3522 + units: 19437 + unitsLabel: evals + unitsPerMs: 16.911265 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 5 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5g4 + score: -19.599999999999994 + metrics: + wallMs: 1144.3749000318348 + evalsPerMs: 16.98481852359685 + rootMoves: 36 + negamaxNodes: 53280 + quiescenceNodes: 19485 + movegenCalls: 39678 + tacticalMovegenCalls: 9559 + legalContextCalls: 39678 + ttHits: 25801 + ttCutoffs: 23283 + betaCutoffs: 10478 + negamaxTtHits: 24674 + quiescenceTtHits: 1127 + negamaxTtCutoffs: 23162 + quiescenceTtCutoffs: 121 + negamaxBetaCutoffs: 9696 + quiescenceBetaCutoffs: 782 + qsearchStandPatCutoffs: 9805 + qsearchDeltaPruneChecks: 217 + qsearchDeltaPruneSkips: 46 + qsearchNodesWithMoves: 1036 + qsearchGeneratedMoves: 1051 + pvsResearches: 283 + negamaxFrontierFutilityChecks: 27750 + negamaxFrontierFutilitySkips: 2782 + ttEntries: 21469 +depths: +- 4 +- 5 +filter: capture-storm-qsearch diff --git a/results/2.1.003/measurement-capture-storm-qsearch-frontier-futility-v2.yaml b/results/2.1.003/measurement-capture-storm-qsearch-frontier-futility-v2.yaml new file mode 100644 index 00000000..3bbd35ab --- /dev/null +++ b/results/2.1.003/measurement-capture-storm-qsearch-frontier-futility-v2.yaml @@ -0,0 +1,103 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:07:05.410289+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summaries: + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 341.7885 + units: 7900 + unitsLabel: evals + unitsPerMs: 23.113709 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 4 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5c8 + score: -19.200000000000003 + metrics: + wallMs: 341.21929993852973 + evalsPerMs: 23.1522660102262 + rootMoves: 36 + negamaxNodes: 15028 + quiescenceNodes: 8267 + movegenCalls: 11862 + tacticalMovegenCalls: 2146 + legalContextCalls: 11862 + ttHits: 6371 + ttCutoffs: 5691 + betaCutoffs: 2284 + negamaxTtHits: 5693 + quiescenceTtHits: 678 + negamaxTtCutoffs: 5313 + quiescenceTtCutoffs: 378 + negamaxBetaCutoffs: 1803 + quiescenceBetaCutoffs: 481 + qsearchStandPatCutoffs: 5743 + qsearchDeltaPruneChecks: 103 + qsearchDeltaPruneSkips: 83 + qsearchNodesWithMoves: 991 + qsearchGeneratedMoves: 1361 + pvsResearches: 171 + negamaxFrontierFutilityChecks: 9672 + negamaxFrontierFutilitySkips: 1642 + ttEntries: 8932 + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 1129.237 + units: 19437 + unitsLabel: evals + unitsPerMs: 17.212507 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 5 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5g4 + score: -19.599999999999994 + metrics: + wallMs: 1163.2786998525262 + evalsPerMs: 16.708807616321103 + rootMoves: 36 + negamaxNodes: 53280 + quiescenceNodes: 19485 + movegenCalls: 39678 + tacticalMovegenCalls: 9559 + legalContextCalls: 39678 + ttHits: 25801 + ttCutoffs: 23283 + betaCutoffs: 10478 + negamaxTtHits: 24674 + quiescenceTtHits: 1127 + negamaxTtCutoffs: 23162 + quiescenceTtCutoffs: 121 + negamaxBetaCutoffs: 9696 + quiescenceBetaCutoffs: 782 + qsearchStandPatCutoffs: 9805 + qsearchDeltaPruneChecks: 136 + qsearchDeltaPruneSkips: 46 + qsearchNodesWithMoves: 1036 + qsearchGeneratedMoves: 1051 + pvsResearches: 283 + negamaxFrontierFutilityChecks: 27750 + negamaxFrontierFutilitySkips: 2782 + ttEntries: 21469 +depths: +- 4 +- 5 +filter: capture-storm-qsearch diff --git a/results/2.1.003/measurement-capture-storm-qsearch-frontier-futility.yaml b/results/2.1.003/measurement-capture-storm-qsearch-frontier-futility.yaml new file mode 100644 index 00000000..0f827967 --- /dev/null +++ b/results/2.1.003/measurement-capture-storm-qsearch-frontier-futility.yaml @@ -0,0 +1,103 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:01:29.179146+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summaries: + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 344.9062 + units: 7900 + unitsLabel: evals + unitsPerMs: 22.904778 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 4 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5c8 + score: -19.200000000000003 + metrics: + wallMs: 341.64789970964193 + evalsPerMs: 23.123221324392784 + rootMoves: 36 + negamaxNodes: 15028 + quiescenceNodes: 8267 + movegenCalls: 11862 + tacticalMovegenCalls: 2146 + legalContextCalls: 11862 + ttHits: 6371 + ttCutoffs: 5691 + betaCutoffs: 2284 + negamaxTtHits: 5693 + quiescenceTtHits: 678 + negamaxTtCutoffs: 5313 + quiescenceTtCutoffs: 378 + negamaxBetaCutoffs: 1803 + quiescenceBetaCutoffs: 481 + qsearchStandPatCutoffs: 5743 + qsearchDeltaPruneChecks: 103 + qsearchDeltaPruneSkips: 83 + qsearchNodesWithMoves: 991 + qsearchGeneratedMoves: 1361 + pvsResearches: 171 + negamaxFrontierFutilityChecks: 1643 + negamaxFrontierFutilitySkips: 1642 + ttEntries: 8932 + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 1149.0761 + units: 19437 + unitsLabel: evals + unitsPerMs: 16.915329 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 5 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5g4 + score: -19.599999999999994 + metrics: + wallMs: 1172.661299817264 + evalsPerMs: 16.575118495876747 + rootMoves: 36 + negamaxNodes: 53280 + quiescenceNodes: 19485 + movegenCalls: 39678 + tacticalMovegenCalls: 9559 + legalContextCalls: 39678 + ttHits: 25801 + ttCutoffs: 23283 + betaCutoffs: 10478 + negamaxTtHits: 24674 + quiescenceTtHits: 1127 + negamaxTtCutoffs: 23162 + quiescenceTtCutoffs: 121 + negamaxBetaCutoffs: 9696 + quiescenceBetaCutoffs: 782 + qsearchStandPatCutoffs: 9805 + qsearchDeltaPruneChecks: 136 + qsearchDeltaPruneSkips: 46 + qsearchNodesWithMoves: 1036 + qsearchGeneratedMoves: 1051 + pvsResearches: 283 + negamaxFrontierFutilityChecks: 2804 + negamaxFrontierFutilitySkips: 2782 + ttEntries: 21469 +depths: +- 4 +- 5 +filter: capture-storm-qsearch diff --git a/results/2.1.003/measurement-capture-storm-qsearch-leaf-fastpath.yaml b/results/2.1.003/measurement-capture-storm-qsearch-leaf-fastpath.yaml new file mode 100644 index 00000000..911c4548 --- /dev/null +++ b/results/2.1.003/measurement-capture-storm-qsearch-leaf-fastpath.yaml @@ -0,0 +1,108 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T17:14:05.673372+00:00' +mode: search +repeat: 3 +topCount: 3 +diagnostics: true +cases: +- name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summaries: + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 212.487 + units: 7900 + unitsLabel: evals + unitsPerMs: 37.178745 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 4 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5c8 + score: -19.200000000000003 + metrics: + wallMs: 211.88190020620823 + evalsPerMs: 37.28492142231848 + rootMoves: 36 + negamaxNodes: 15028 + quiescenceNodes: 8267 + movegenCalls: 5493 + tacticalMovegenCalls: 2146 + legalContextCalls: 5493 + ttHits: 6371 + ttCutoffs: 5691 + betaCutoffs: 2284 + ttEntries: 8932 + negamaxTtHits: 5693 + quiescenceTtHits: 678 + negamaxTtCutoffs: 5313 + quiescenceTtCutoffs: 378 + negamaxBetaCutoffs: 1803 + quiescenceBetaCutoffs: 481 + qsearchStandPatCutoffs: 5743 + qsearchDeltaPruneChecks: 103 + qsearchDeltaPruneSkips: 83 + qsearchNodesWithMoves: 991 + qsearchGeneratedMoves: 1361 + pvsResearches: 171 + negamaxFrontierFutilityChecks: 9672 + negamaxFrontierFutilitySkips: 1642 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 500.5845 + units: 13862 + unitsLabel: evals + unitsPerMs: 27.691628 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 5 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5g4 + score: -19.599999999999994 + metrics: + wallMs: 499.1560000926256 + evalsPerMs: 27.770877235629154 + rootMoves: 36 + negamaxNodes: 36986 + quiescenceNodes: 13972 + movegenCalls: 13876 + tacticalMovegenCalls: 5362 + legalContextCalls: 13876 + ttHits: 19171 + ttCutoffs: 17367 + betaCutoffs: 5127 + ttEntries: 14560 + negamaxTtHits: 18282 + quiescenceTtHits: 889 + negamaxTtCutoffs: 17197 + quiescenceTtCutoffs: 170 + negamaxBetaCutoffs: 4625 + quiescenceBetaCutoffs: 502 + qsearchStandPatCutoffs: 8440 + qsearchDeltaPruneChecks: 286 + qsearchDeltaPruneSkips: 19 + qsearchNodesWithMoves: 850 + qsearchGeneratedMoves: 876 + pvsResearches: 203 + negamaxFrontierFutilityChecks: 24576 + negamaxFrontierFutilitySkips: 2793 + nullMoveAttempts: 755 + nullMoveCutoffs: 677 +depths: +- 4 +- 5 +filter: capture-storm-qsearch diff --git a/results/2.1.003/measurement-capture-storm-qsearch-null-move-v1.yaml b/results/2.1.003/measurement-capture-storm-qsearch-null-move-v1.yaml new file mode 100644 index 00000000..2b7504dc --- /dev/null +++ b/results/2.1.003/measurement-capture-storm-qsearch-null-move-v1.yaml @@ -0,0 +1,108 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:47:22.189435+00:00' +mode: search +repeat: 3 +topCount: 3 +diagnostics: true +cases: +- name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summaries: + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 350.9524 + units: 7900 + unitsLabel: evals + unitsPerMs: 22.510175 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 4 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5c8 + score: -19.200000000000003 + metrics: + wallMs: 350.3656000830233 + evalsPerMs: 22.547875699349483 + rootMoves: 36 + negamaxNodes: 15028 + quiescenceNodes: 8267 + movegenCalls: 11862 + tacticalMovegenCalls: 2146 + legalContextCalls: 11862 + ttHits: 6371 + ttCutoffs: 5691 + betaCutoffs: 2284 + ttEntries: 8932 + negamaxTtHits: 5693 + quiescenceTtHits: 678 + negamaxTtCutoffs: 5313 + quiescenceTtCutoffs: 378 + negamaxBetaCutoffs: 1803 + quiescenceBetaCutoffs: 481 + qsearchStandPatCutoffs: 5743 + qsearchDeltaPruneChecks: 103 + qsearchDeltaPruneSkips: 83 + qsearchNodesWithMoves: 991 + qsearchGeneratedMoves: 1361 + pvsResearches: 171 + negamaxFrontierFutilityChecks: 9672 + negamaxFrontierFutilitySkips: 1642 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 729.4915 + units: 13862 + unitsLabel: evals + unitsPerMs: 19.002278 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 5 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5g4 + score: -19.599999999999994 + metrics: + wallMs: 718.1969000957906 + evalsPerMs: 19.301113661380512 + rootMoves: 36 + negamaxNodes: 36986 + quiescenceNodes: 13972 + movegenCalls: 24475 + tacticalMovegenCalls: 5362 + legalContextCalls: 24475 + ttHits: 19171 + ttCutoffs: 17367 + betaCutoffs: 5127 + ttEntries: 14560 + negamaxTtHits: 18282 + quiescenceTtHits: 889 + negamaxTtCutoffs: 17197 + quiescenceTtCutoffs: 170 + negamaxBetaCutoffs: 4625 + quiescenceBetaCutoffs: 502 + qsearchStandPatCutoffs: 8440 + qsearchDeltaPruneChecks: 286 + qsearchDeltaPruneSkips: 19 + qsearchNodesWithMoves: 850 + qsearchGeneratedMoves: 876 + pvsResearches: 203 + negamaxFrontierFutilityChecks: 24576 + negamaxFrontierFutilitySkips: 2793 + nullMoveAttempts: 755 + nullMoveCutoffs: 677 +depths: +- 4 +- 5 +filter: capture-storm-qsearch diff --git a/results/2.1.003/measurement-capture-storm-qsearch.yaml b/results/2.1.003/measurement-capture-storm-qsearch.yaml new file mode 100644 index 00000000..b69a8a1d --- /dev/null +++ b/results/2.1.003/measurement-capture-storm-qsearch.yaml @@ -0,0 +1,99 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T11:06:25.218737+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summaries: + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 360.2468 + units: 8880 + unitsLabel: evals + unitsPerMs: 24.649768 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 4 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5c8 + score: -19.200000000000003 + metrics: + wallMs: 348.5974003560841 + evalsPerMs: 25.473511824612828 + rootMoves: 36 + negamaxNodes: 16672 + quiescenceNodes: 9247 + movegenCalls: 12842 + tacticalMovegenCalls: 2146 + legalContextCalls: 12842 + ttHits: 7064 + ttCutoffs: 6355 + betaCutoffs: 2281 + negamaxTtHits: 6372 + quiescenceTtHits: 692 + negamaxTtCutoffs: 5977 + quiescenceTtCutoffs: 378 + negamaxBetaCutoffs: 1803 + quiescenceBetaCutoffs: 478 + qsearchStandPatCutoffs: 6723 + qsearchDeltaPruneChecks: 103 + qsearchDeltaPruneSkips: 83 + qsearchNodesWithMoves: 991 + qsearchGeneratedMoves: 1361 + pvsResearches: 173 + ttEntries: 9903 + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 1125.8271 + units: 20123 + unitsLabel: evals + unitsPerMs: 17.87397 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 5 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5g4 + score: -19.599999999999994 + metrics: + wallMs: 1122.6053000427783 + evalsPerMs: 17.925267232600085 + rootMoves: 36 + negamaxNodes: 56199 + quiescenceNodes: 20167 + movegenCalls: 40385 + tacticalMovegenCalls: 9567 + legalContextCalls: 40385 + ttHits: 28040 + ttCutoffs: 25503 + betaCutoffs: 10487 + negamaxTtHits: 26909 + quiescenceTtHits: 1131 + negamaxTtCutoffs: 25382 + quiescenceTtCutoffs: 121 + negamaxBetaCutoffs: 9705 + quiescenceBetaCutoffs: 782 + qsearchStandPatCutoffs: 10479 + qsearchDeltaPruneChecks: 136 + qsearchDeltaPruneSkips: 46 + qsearchNodesWithMoves: 1036 + qsearchGeneratedMoves: 1051 + pvsResearches: 283 + ttEntries: 22145 +depths: +- 4 +- 5 +filter: capture-storm-qsearch diff --git a/results/2.1.003/measurement-harvested-qsearch-heavy-delta-prune-v2.yaml b/results/2.1.003/measurement-harvested-qsearch-heavy-delta-prune-v2.yaml new file mode 100644 index 00000000..ac32656d --- /dev/null +++ b/results/2.1.003/measurement-harvested-qsearch-heavy-delta-prune-v2.yaml @@ -0,0 +1,109 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:37:03.603433+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 135.6613 + units: 3060 + unitsLabel: evals + unitsPerMs: 22.556175 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 2 + topMoves: + - san: b7b5 + score: -1.6799999999999997 + - san: c7c5 + score: -1.6799999999999997 + - san: d6f10 + score: -1.2800000000000011 + metrics: + wallMs: 128.82639979943633 + evalsPerMs: 23.752895406251884 + rootMoves: 51 + negamaxNodes: 2496 + quiescenceNodes: 3076 + movegenCalls: 3110 + tacticalMovegenCalls: 622 + legalContextCalls: 3110 + ttHits: 39 + ttCutoffs: 25 + betaCutoffs: 219 + negamaxTtHits: 12 + quiescenceTtHits: 27 + negamaxTtCutoffs: 9 + quiescenceTtCutoffs: 16 + negamaxBetaCutoffs: 0 + quiescenceBetaCutoffs: 219 + qsearchStandPatCutoffs: 2438 + qsearchDeltaPruneChecks: 27 + qsearchDeltaPruneSkips: 12 + qsearchNodesWithMoves: 401 + qsearchGeneratedMoves: 1111 + pvsResearches: 45 + negamaxFrontierFutilityChecks: 2230 + negamaxFrontierFutilitySkips: 0 + ttEntries: 2879 + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 1591.6088 + units: 43916 + unitsLabel: evals + unitsPerMs: 27.592207 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 3 + topMoves: + - san: b7b5 + score: -2.0 + - san: c7c5 + score: -2.0 + - san: d6e8 + score: -1.6799999999999997 + metrics: + wallMs: 1601.960999891162 + evalsPerMs: 27.413900839648203 + rootMoves: 51 + negamaxNodes: 12374 + quiescenceNodes: 45631 + movegenCalls: 39579 + tacticalMovegenCalls: 29365 + legalContextCalls: 39579 + ttHits: 4585 + ttCutoffs: 3876 + betaCutoffs: 15370 + negamaxTtHits: 2405 + quiescenceTtHits: 2180 + negamaxTtCutoffs: 2161 + quiescenceTtCutoffs: 1715 + negamaxBetaCutoffs: 2296 + quiescenceBetaCutoffs: 13074 + qsearchStandPatCutoffs: 14551 + qsearchDeltaPruneChecks: 3772 + qsearchDeltaPruneSkips: 2479 + qsearchNodesWithMoves: 23913 + qsearchGeneratedMoves: 67279 + pvsResearches: 152 + negamaxFrontierFutilityChecks: 6845 + negamaxFrontierFutilitySkips: 0 + ttEntries: 40454 +depths: +- 2 +- 3 +filter: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy diff --git a/results/2.1.003/measurement-harvested-qsearch-heavy-frontier-futility-v2.yaml b/results/2.1.003/measurement-harvested-qsearch-heavy-frontier-futility-v2.yaml new file mode 100644 index 00000000..d0cdfbc5 --- /dev/null +++ b/results/2.1.003/measurement-harvested-qsearch-heavy-frontier-futility-v2.yaml @@ -0,0 +1,109 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:10:44.861720+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 125.3752 + units: 3071 + unitsLabel: evals + unitsPerMs: 24.494477 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 2 + topMoves: + - san: b7b5 + score: -1.6799999999999997 + - san: c7c5 + score: -1.6799999999999997 + - san: d6f10 + score: -1.2800000000000011 + metrics: + wallMs: 121.10750004649162 + evalsPerMs: 25.357636800537392 + rootMoves: 51 + negamaxNodes: 2496 + quiescenceNodes: 3087 + movegenCalls: 3110 + tacticalMovegenCalls: 622 + legalContextCalls: 3110 + ttHits: 39 + ttCutoffs: 25 + betaCutoffs: 219 + negamaxTtHits: 12 + quiescenceTtHits: 27 + negamaxTtCutoffs: 9 + quiescenceTtCutoffs: 16 + negamaxBetaCutoffs: 0 + quiescenceBetaCutoffs: 219 + qsearchStandPatCutoffs: 2449 + qsearchDeltaPruneChecks: 1 + qsearchDeltaPruneSkips: 1 + qsearchNodesWithMoves: 401 + qsearchGeneratedMoves: 1111 + pvsResearches: 45 + negamaxFrontierFutilityChecks: 2230 + negamaxFrontierFutilitySkips: 0 + ttEntries: 2890 + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 1433.634 + units: 45842 + unitsLabel: evals + unitsPerMs: 31.976083 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 3 + topMoves: + - san: b7b5 + score: -2.0 + - san: c7c5 + score: -2.0 + - san: d6e8 + score: -1.6799999999999997 + metrics: + wallMs: 1429.4250002130866 + evalsPerMs: 32.070238027994655 + rootMoves: 51 + negamaxNodes: 12374 + quiescenceNodes: 47719 + movegenCalls: 39683 + tacticalMovegenCalls: 29453 + legalContextCalls: 39683 + ttHits: 4808 + ttCutoffs: 4022 + betaCutoffs: 15414 + negamaxTtHits: 2405 + quiescenceTtHits: 2403 + negamaxTtCutoffs: 2145 + quiescenceTtCutoffs: 1877 + negamaxBetaCutoffs: 2296 + quiescenceBetaCutoffs: 13118 + qsearchStandPatCutoffs: 16389 + qsearchDeltaPruneChecks: 596 + qsearchDeltaPruneSkips: 535 + qsearchNodesWithMoves: 23997 + qsearchGeneratedMoves: 67578 + pvsResearches: 152 + negamaxFrontierFutilityChecks: 6845 + negamaxFrontierFutilitySkips: 0 + ttEntries: 42315 +depths: +- 2 +- 3 +filter: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy diff --git a/results/2.1.003/measurement-harvested-qsearch-heavy-frontier-futility.yaml b/results/2.1.003/measurement-harvested-qsearch-heavy-frontier-futility.yaml new file mode 100644 index 00000000..8cc60326 --- /dev/null +++ b/results/2.1.003/measurement-harvested-qsearch-heavy-frontier-futility.yaml @@ -0,0 +1,109 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:02:31.684822+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 134.0215 + units: 3071 + unitsLabel: evals + unitsPerMs: 22.914234 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 2 + topMoves: + - san: b7b5 + score: -1.6799999999999997 + - san: c7c5 + score: -1.6799999999999997 + - san: d6f10 + score: -1.2800000000000011 + metrics: + wallMs: 133.76470003277063 + evalsPerMs: 22.958224398870886 + rootMoves: 51 + negamaxNodes: 2496 + quiescenceNodes: 3087 + movegenCalls: 3110 + tacticalMovegenCalls: 622 + legalContextCalls: 3110 + ttHits: 39 + ttCutoffs: 25 + betaCutoffs: 219 + negamaxTtHits: 12 + quiescenceTtHits: 27 + negamaxTtCutoffs: 9 + quiescenceTtCutoffs: 16 + negamaxBetaCutoffs: 0 + quiescenceBetaCutoffs: 219 + qsearchStandPatCutoffs: 2449 + qsearchDeltaPruneChecks: 1 + qsearchDeltaPruneSkips: 1 + qsearchNodesWithMoves: 401 + qsearchGeneratedMoves: 1111 + pvsResearches: 45 + negamaxFrontierFutilityChecks: 0 + negamaxFrontierFutilitySkips: 0 + ttEntries: 2890 + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 1578.1246 + units: 45842 + unitsLabel: evals + unitsPerMs: 29.048403 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 3 + topMoves: + - san: b7b5 + score: -2.0 + - san: c7c5 + score: -2.0 + - san: d6e8 + score: -1.6799999999999997 + metrics: + wallMs: 1575.763300061226 + evalsPerMs: 29.091932778367678 + rootMoves: 51 + negamaxNodes: 12374 + quiescenceNodes: 47719 + movegenCalls: 39683 + tacticalMovegenCalls: 29453 + legalContextCalls: 39683 + ttHits: 4808 + ttCutoffs: 4022 + betaCutoffs: 15414 + negamaxTtHits: 2405 + quiescenceTtHits: 2403 + negamaxTtCutoffs: 2145 + quiescenceTtCutoffs: 1877 + negamaxBetaCutoffs: 2296 + quiescenceBetaCutoffs: 13118 + qsearchStandPatCutoffs: 16389 + qsearchDeltaPruneChecks: 596 + qsearchDeltaPruneSkips: 535 + qsearchNodesWithMoves: 23997 + qsearchGeneratedMoves: 67578 + pvsResearches: 152 + negamaxFrontierFutilityChecks: 0 + negamaxFrontierFutilitySkips: 0 + ttEntries: 42315 +depths: +- 2 +- 3 +filter: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy diff --git a/results/2.1.003/measurement-harvested-qsearch-heavy-leaf-fastpath.yaml b/results/2.1.003/measurement-harvested-qsearch-heavy-leaf-fastpath.yaml new file mode 100644 index 00000000..8de65c4d --- /dev/null +++ b/results/2.1.003/measurement-harvested-qsearch-heavy-leaf-fastpath.yaml @@ -0,0 +1,114 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T17:15:51.703295+00:00' +mode: search +repeat: 3 +topCount: 3 +diagnostics: true +cases: +- name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 59.5139 + units: 3071 + unitsLabel: evals + unitsPerMs: 51.601391 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 2 + topMoves: + - san: b7b5 + score: -1.6799999999999997 + - san: c7c5 + score: -1.6799999999999997 + - san: d6f10 + score: -1.2800000000000011 + metrics: + wallMs: 84.45809967815876 + evalsPerMs: 36.36122540884227 + rootMoves: 51 + negamaxNodes: 2496 + quiescenceNodes: 3087 + movegenCalls: 721 + tacticalMovegenCalls: 622 + legalContextCalls: 721 + ttHits: 39 + ttCutoffs: 25 + betaCutoffs: 219 + ttEntries: 2890 + negamaxTtHits: 12 + quiescenceTtHits: 27 + negamaxTtCutoffs: 9 + quiescenceTtCutoffs: 16 + negamaxBetaCutoffs: 0 + quiescenceBetaCutoffs: 219 + qsearchStandPatCutoffs: 2449 + qsearchDeltaPruneChecks: 1 + qsearchDeltaPruneSkips: 1 + qsearchNodesWithMoves: 401 + qsearchGeneratedMoves: 1111 + pvsResearches: 45 + negamaxFrontierFutilityChecks: 2230 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 1218.7598 + units: 45842 + unitsLabel: evals + unitsPerMs: 37.613646 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 3 + topMoves: + - san: b7b5 + score: -2.0 + - san: c7c5 + score: -2.0 + - san: d6e8 + score: -1.6799999999999997 + metrics: + wallMs: 1203.4658999182284 + evalsPerMs: 38.09164846558163 + rootMoves: 51 + negamaxNodes: 12374 + quiescenceNodes: 47719 + movegenCalls: 31951 + tacticalMovegenCalls: 29453 + legalContextCalls: 31951 + ttHits: 4808 + ttCutoffs: 4022 + betaCutoffs: 15414 + ttEntries: 42315 + negamaxTtHits: 2405 + quiescenceTtHits: 2403 + negamaxTtCutoffs: 2145 + quiescenceTtCutoffs: 1877 + negamaxBetaCutoffs: 2296 + quiescenceBetaCutoffs: 13118 + qsearchStandPatCutoffs: 16389 + qsearchDeltaPruneChecks: 596 + qsearchDeltaPruneSkips: 535 + qsearchNodesWithMoves: 23997 + qsearchGeneratedMoves: 67578 + pvsResearches: 152 + negamaxFrontierFutilityChecks: 6845 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 +depths: +- 2 +- 3 +filter: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy diff --git a/results/2.1.003/measurement-harvested-qsearch-heavy-null-move-v1.yaml b/results/2.1.003/measurement-harvested-qsearch-heavy-null-move-v1.yaml new file mode 100644 index 00000000..c1fac157 --- /dev/null +++ b/results/2.1.003/measurement-harvested-qsearch-heavy-null-move-v1.yaml @@ -0,0 +1,114 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:48:22.411534+00:00' +mode: search +repeat: 3 +topCount: 3 +diagnostics: true +cases: +- name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 143.2639 + units: 3071 + unitsLabel: evals + unitsPerMs: 21.435965 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 2 + topMoves: + - san: b7b5 + score: -1.6799999999999997 + - san: c7c5 + score: -1.6799999999999997 + - san: d6f10 + score: -1.2800000000000011 + metrics: + wallMs: 145.16380010172725 + evalsPerMs: 21.155412009384698 + rootMoves: 51 + negamaxNodes: 2496 + quiescenceNodes: 3087 + movegenCalls: 3110 + tacticalMovegenCalls: 622 + legalContextCalls: 3110 + ttHits: 39 + ttCutoffs: 25 + betaCutoffs: 219 + ttEntries: 2890 + negamaxTtHits: 12 + quiescenceTtHits: 27 + negamaxTtCutoffs: 9 + quiescenceTtCutoffs: 16 + negamaxBetaCutoffs: 0 + quiescenceBetaCutoffs: 219 + qsearchStandPatCutoffs: 2449 + qsearchDeltaPruneChecks: 1 + qsearchDeltaPruneSkips: 1 + qsearchNodesWithMoves: 401 + qsearchGeneratedMoves: 1111 + pvsResearches: 45 + negamaxFrontierFutilityChecks: 2230 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 1599.9977 + units: 45842 + unitsLabel: evals + unitsPerMs: 28.651291 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 3 + topMoves: + - san: b7b5 + score: -2.0 + - san: c7c5 + score: -2.0 + - san: d6e8 + score: -1.6799999999999997 + metrics: + wallMs: 1600.149200297892 + evalsPerMs: 28.648578514719638 + rootMoves: 51 + negamaxNodes: 12374 + quiescenceNodes: 47719 + movegenCalls: 39683 + tacticalMovegenCalls: 29453 + legalContextCalls: 39683 + ttHits: 4808 + ttCutoffs: 4022 + betaCutoffs: 15414 + ttEntries: 42315 + negamaxTtHits: 2405 + quiescenceTtHits: 2403 + negamaxTtCutoffs: 2145 + quiescenceTtCutoffs: 1877 + negamaxBetaCutoffs: 2296 + quiescenceBetaCutoffs: 13118 + qsearchStandPatCutoffs: 16389 + qsearchDeltaPruneChecks: 596 + qsearchDeltaPruneSkips: 535 + qsearchNodesWithMoves: 23997 + qsearchGeneratedMoves: 67578 + pvsResearches: 152 + negamaxFrontierFutilityChecks: 6845 + negamaxFrontierFutilitySkips: 0 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 +depths: +- 2 +- 3 +filter: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy diff --git a/results/2.1.003/measurement-harvested-qsearch-heavy.yaml b/results/2.1.003/measurement-harvested-qsearch-heavy.yaml new file mode 100644 index 00000000..2e3b7095 --- /dev/null +++ b/results/2.1.003/measurement-harvested-qsearch-heavy.yaml @@ -0,0 +1,105 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T11:07:50.359948+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + summaries: + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 135.7508 + units: 3071 + unitsLabel: evals + unitsPerMs: 22.622334 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 2 + topMoves: + - san: b7b5 + score: -1.6799999999999997 + - san: c7c5 + score: -1.6799999999999997 + - san: d6f10 + score: -1.2800000000000011 + metrics: + wallMs: 126.042400021106 + evalsPerMs: 24.364816914671223 + rootMoves: 51 + negamaxNodes: 2496 + quiescenceNodes: 3087 + movegenCalls: 3110 + tacticalMovegenCalls: 622 + legalContextCalls: 3110 + ttHits: 39 + ttCutoffs: 25 + betaCutoffs: 219 + negamaxTtHits: 12 + quiescenceTtHits: 27 + negamaxTtCutoffs: 9 + quiescenceTtCutoffs: 16 + negamaxBetaCutoffs: 0 + quiescenceBetaCutoffs: 219 + qsearchStandPatCutoffs: 2449 + qsearchDeltaPruneChecks: 1 + qsearchDeltaPruneSkips: 1 + qsearchNodesWithMoves: 401 + qsearchGeneratedMoves: 1111 + pvsResearches: 45 + ttEntries: 2890 + - name: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy + category: harvested + mode: search + medianMs: 1536.8101 + units: 45842 + unitsLabel: evals + unitsPerMs: 29.82932 + notes: 'Harvested from hexchess-game-20260324-175232.yaml before ply 34 (b17 b7b5). + tags: slow-search, qsearch-heavy, movegen-heavy, pruning-heavy. wallMs=62024.1, + negamaxNodes=521388, quiescenceNodes=1852281, ttHits=264785, movegenCalls=1396834.' + depth: 3 + topMoves: + - san: b7b5 + score: -2.0 + - san: c7c5 + score: -2.0 + - san: d6e8 + score: -1.6799999999999997 + metrics: + wallMs: 1520.8632997237146 + evalsPerMs: 30.142091013918094 + rootMoves: 51 + negamaxNodes: 12374 + quiescenceNodes: 47719 + movegenCalls: 39683 + tacticalMovegenCalls: 29453 + legalContextCalls: 39683 + ttHits: 4808 + ttCutoffs: 4022 + betaCutoffs: 15414 + negamaxTtHits: 2405 + quiescenceTtHits: 2403 + negamaxTtCutoffs: 2145 + quiescenceTtCutoffs: 1877 + negamaxBetaCutoffs: 2296 + quiescenceBetaCutoffs: 13118 + qsearchStandPatCutoffs: 16389 + qsearchDeltaPruneChecks: 596 + qsearchDeltaPruneSkips: 535 + qsearchNodesWithMoves: 23997 + qsearchGeneratedMoves: 67578 + pvsResearches: 152 + ttEntries: 42315 +depths: +- 2 +- 3 +filter: harvested-hexchess-game-20260324-175232-ply-034-qsearch-heavy diff --git a/results/2.1.003/measurement-initial-position-delta-prune-v2.yaml b/results/2.1.003/measurement-initial-position-delta-prune-v2.yaml new file mode 100644 index 00000000..bd0fca7c --- /dev/null +++ b/results/2.1.003/measurement-initial-position-delta-prune-v2.yaml @@ -0,0 +1,103 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:39:28.673576+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: initial-position + category: opening + notes: High-branching opening baseline. + summaries: + - name: initial-position + category: opening + mode: search + medianMs: 7154.9718 + units: 134025 + unitsLabel: evals + unitsPerMs: 18.73173 + notes: High-branching opening baseline. + depth: 4 + topMoves: + - san: d3d5 + score: -0.0 + - san: h3h5 + score: -0.0 + - san: c2c4 + score: -0.0 + metrics: + wallMs: 7149.469899944961 + evalsPerMs: 18.74614508147405 + rootMoves: 51 + negamaxNodes: 155774 + quiescenceNodes: 135686 + movegenCalls: 151783 + tacticalMovegenCalls: 28235 + legalContextCalls: 151783 + ttHits: 35087 + ttCutoffs: 33888 + betaCutoffs: 18643 + negamaxTtHits: 32861 + quiescenceTtHits: 2226 + negamaxTtCutoffs: 32227 + quiescenceTtCutoffs: 1661 + negamaxBetaCutoffs: 8274 + quiescenceBetaCutoffs: 10369 + qsearchStandPatCutoffs: 105790 + qsearchDeltaPruneChecks: 2440 + qsearchDeltaPruneSkips: 1999 + qsearchNodesWithMoves: 19308 + qsearchGeneratedMoves: 37728 + pvsResearches: 738 + negamaxFrontierFutilityChecks: 139389 + negamaxFrontierFutilitySkips: 6899 + ttEntries: 135557 + - name: initial-position + category: opening + mode: search + medianMs: 45649.7115 + units: 972925 + unitsLabel: evals + unitsPerMs: 21.31284 + notes: High-branching opening baseline. + depth: 5 + topMoves: + - san: d3d5 + score: -0.32000000000000006 + - san: h3h5 + score: -0.32000000000000006 + - san: c2c4 + score: -0.32000000000000006 + metrics: + wallMs: 45602.42550028488 + evalsPerMs: 21.334939738982133 + rootMoves: 51 + negamaxNodes: 555428 + quiescenceNodes: 1041909 + movegenCalls: 1080421 + tacticalMovegenCalls: 636332 + legalContextCalls: 1080421 + ttHits: 190792 + ttCutoffs: 180324 + betaCutoffs: 385792 + negamaxTtHits: 115788 + quiescenceTtHits: 75004 + negamaxTtCutoffs: 111340 + quiescenceTtCutoffs: 68984 + negamaxBetaCutoffs: 124686 + quiescenceBetaCutoffs: 261106 + qsearchStandPatCutoffs: 336593 + qsearchDeltaPruneChecks: 102957 + qsearchDeltaPruneSkips: 82939 + qsearchNodesWithMoves: 526899 + qsearchGeneratedMoves: 1252473 + pvsResearches: 2289 + negamaxFrontierFutilityChecks: 264660 + negamaxFrontierFutilitySkips: 17057 + ttEntries: 988782 +depths: +- 4 +- 5 +filter: initial-position diff --git a/results/2.1.003/measurement-initial-position-frontier-futility-v2.yaml b/results/2.1.003/measurement-initial-position-frontier-futility-v2.yaml new file mode 100644 index 00000000..0cb65d70 --- /dev/null +++ b/results/2.1.003/measurement-initial-position-frontier-futility-v2.yaml @@ -0,0 +1,103 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:10:24.460997+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: initial-position + category: opening + notes: High-branching opening baseline. + summaries: + - name: initial-position + category: opening + mode: search + medianMs: 7093.8528 + units: 134821 + unitsLabel: evals + unitsPerMs: 19.005328 + notes: High-branching opening baseline. + depth: 4 + topMoves: + - san: d3d5 + score: -0.0 + - san: h3h5 + score: -0.0 + - san: c2c4 + score: -0.0 + metrics: + wallMs: 7087.624300271273 + evalsPerMs: 19.022029708154797 + rootMoves: 51 + negamaxNodes: 155774 + quiescenceNodes: 136519 + movegenCalls: 151795 + tacticalMovegenCalls: 28246 + legalContextCalls: 151795 + ttHits: 35137 + ttCutoffs: 33924 + betaCutoffs: 18648 + negamaxTtHits: 32861 + quiescenceTtHits: 2276 + negamaxTtCutoffs: 32226 + quiescenceTtCutoffs: 1698 + negamaxBetaCutoffs: 8274 + quiescenceBetaCutoffs: 10374 + qsearchStandPatCutoffs: 106575 + qsearchDeltaPruneChecks: 1206 + qsearchDeltaPruneSkips: 1177 + qsearchNodesWithMoves: 19316 + qsearchGeneratedMoves: 37747 + pvsResearches: 738 + negamaxFrontierFutilityChecks: 139389 + negamaxFrontierFutilitySkips: 6899 + ttEntries: 136337 + - name: initial-position + category: opening + mode: search + medianMs: 45558.1325 + units: 999007 + unitsLabel: evals + unitsPerMs: 21.928182 + notes: High-branching opening baseline. + depth: 5 + topMoves: + - san: d3d5 + score: -0.32000000000000006 + - san: h3h5 + score: -0.32000000000000006 + - san: c2c4 + score: -0.32000000000000006 + metrics: + wallMs: 45233.68790000677 + evalsPerMs: 22.085464316073384 + rootMoves: 51 + negamaxNodes: 555330 + quiescenceNodes: 1069975 + movegenCalls: 1082741 + tacticalMovegenCalls: 638607 + legalContextCalls: 1082741 + ttHits: 192707 + ttCutoffs: 182165 + betaCutoffs: 386924 + negamaxTtHits: 115681 + quiescenceTtHits: 77026 + negamaxTtCutoffs: 111197 + quiescenceTtCutoffs: 70968 + negamaxBetaCutoffs: 124680 + quiescenceBetaCutoffs: 262244 + qsearchStandPatCutoffs: 360400 + qsearchDeltaPruneChecks: 62952 + qsearchDeltaPruneSkips: 58130 + qsearchNodesWithMoves: 528846 + qsearchGeneratedMoves: 1257882 + pvsResearches: 2286 + negamaxFrontierFutilityChecks: 264694 + negamaxFrontierFutilitySkips: 17059 + ttEntries: 1014471 +depths: +- 4 +- 5 +filter: initial-position diff --git a/results/2.1.003/measurement-initial-position-frontier-futility.yaml b/results/2.1.003/measurement-initial-position-frontier-futility.yaml new file mode 100644 index 00000000..949a371b --- /dev/null +++ b/results/2.1.003/measurement-initial-position-frontier-futility.yaml @@ -0,0 +1,103 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:04:58.913270+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: initial-position + category: opening + notes: High-branching opening baseline. + summaries: + - name: initial-position + category: opening + mode: search + medianMs: 7176.3933 + units: 134821 + unitsLabel: evals + unitsPerMs: 18.786735 + notes: High-branching opening baseline. + depth: 4 + topMoves: + - san: d3d5 + score: -0.0 + - san: h3h5 + score: -0.0 + - san: c2c4 + score: -0.0 + metrics: + wallMs: 7170.108899939805 + evalsPerMs: 18.80320116213742 + rootMoves: 51 + negamaxNodes: 155774 + quiescenceNodes: 136519 + movegenCalls: 151795 + tacticalMovegenCalls: 28246 + legalContextCalls: 151795 + ttHits: 35137 + ttCutoffs: 33924 + betaCutoffs: 18648 + negamaxTtHits: 32861 + quiescenceTtHits: 2276 + negamaxTtCutoffs: 32226 + quiescenceTtCutoffs: 1698 + negamaxBetaCutoffs: 8274 + quiescenceBetaCutoffs: 10374 + qsearchStandPatCutoffs: 106575 + qsearchDeltaPruneChecks: 1206 + qsearchDeltaPruneSkips: 1177 + qsearchNodesWithMoves: 19316 + qsearchGeneratedMoves: 37747 + pvsResearches: 738 + negamaxFrontierFutilityChecks: 6935 + negamaxFrontierFutilitySkips: 6899 + ttEntries: 136337 + - name: initial-position + category: opening + mode: search + medianMs: 46619.0414 + units: 999007 + unitsLabel: evals + unitsPerMs: 21.429162 + notes: High-branching opening baseline. + depth: 5 + topMoves: + - san: d3d5 + score: -0.32000000000000006 + - san: h3h5 + score: -0.32000000000000006 + - san: c2c4 + score: -0.32000000000000006 + metrics: + wallMs: 46566.97520008311 + evalsPerMs: 21.453121997028855 + rootMoves: 51 + negamaxNodes: 555330 + quiescenceNodes: 1069975 + movegenCalls: 1082741 + tacticalMovegenCalls: 638607 + legalContextCalls: 1082741 + ttHits: 192707 + ttCutoffs: 182165 + betaCutoffs: 386924 + negamaxTtHits: 115681 + quiescenceTtHits: 77026 + negamaxTtCutoffs: 111197 + quiescenceTtCutoffs: 70968 + negamaxBetaCutoffs: 124680 + quiescenceBetaCutoffs: 262244 + qsearchStandPatCutoffs: 360400 + qsearchDeltaPruneChecks: 62952 + qsearchDeltaPruneSkips: 58130 + qsearchNodesWithMoves: 528846 + qsearchGeneratedMoves: 1257882 + pvsResearches: 2286 + negamaxFrontierFutilityChecks: 17388 + negamaxFrontierFutilitySkips: 17059 + ttEntries: 1014471 +depths: +- 4 +- 5 +filter: initial-position diff --git a/results/2.1.003/measurement-initial-position-leaf-fastpath.yaml b/results/2.1.003/measurement-initial-position-leaf-fastpath.yaml new file mode 100644 index 00000000..ffab9463 --- /dev/null +++ b/results/2.1.003/measurement-initial-position-leaf-fastpath.yaml @@ -0,0 +1,108 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T17:15:43.978157+00:00' +mode: search +repeat: 3 +topCount: 3 +diagnostics: true +cases: +- name: initial-position + category: opening + notes: High-branching opening baseline. + summaries: + - name: initial-position + category: opening + mode: search + medianMs: 3188.9537 + units: 134821 + unitsLabel: evals + unitsPerMs: 42.277503 + notes: High-branching opening baseline. + depth: 4 + topMoves: + - san: d3d5 + score: -0.0 + - san: h3h5 + score: -0.0 + - san: c2c4 + score: -0.0 + metrics: + wallMs: 3182.730299886316 + evalsPerMs: 42.36017107852829 + rootMoves: 51 + negamaxNodes: 155774 + quiescenceNodes: 136519 + movegenCalls: 40073 + tacticalMovegenCalls: 28246 + legalContextCalls: 40073 + ttHits: 35137 + ttCutoffs: 33924 + betaCutoffs: 18648 + ttEntries: 136337 + negamaxTtHits: 32861 + quiescenceTtHits: 2276 + negamaxTtCutoffs: 32226 + quiescenceTtCutoffs: 1698 + negamaxBetaCutoffs: 8274 + quiescenceBetaCutoffs: 10374 + qsearchStandPatCutoffs: 106575 + qsearchDeltaPruneChecks: 1206 + qsearchDeltaPruneSkips: 1177 + qsearchNodesWithMoves: 19316 + qsearchGeneratedMoves: 37747 + pvsResearches: 738 + negamaxFrontierFutilityChecks: 139389 + negamaxFrontierFutilitySkips: 6899 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - name: initial-position + category: opening + mode: search + medianMs: 21756.185 + units: 665456 + unitsLabel: evals + unitsPerMs: 30.58698 + notes: High-branching opening baseline. + depth: 5 + topMoves: + - san: d3d5 + score: -0.32000000000000006 + - san: h3h5 + score: -0.32000000000000006 + - san: c2c4 + score: -0.32000000000000006 + metrics: + wallMs: 21695.99250005558 + evalsPerMs: 30.671839511296625 + rootMoves: 51 + negamaxNodes: 391552 + quiescenceNodes: 691299 + movegenCalls: 467305 + tacticalMovegenCalls: 390386 + legalContextCalls: 467305 + ttHits: 121118 + ttCutoffs: 114008 + betaCutoffs: 231272 + ttEntries: 669829 + negamaxTtHits: 91484 + quiescenceTtHits: 29634 + negamaxTtCutoffs: 88165 + quiescenceTtCutoffs: 25843 + negamaxBetaCutoffs: 68818 + quiescenceBetaCutoffs: 162454 + qsearchStandPatCutoffs: 275070 + qsearchDeltaPruneChecks: 37568 + qsearchDeltaPruneSkips: 34205 + qsearchNodesWithMoves: 324483 + qsearchGeneratedMoves: 775113 + pvsResearches: 1692 + negamaxFrontierFutilityChecks: 242858 + negamaxFrontierFutilitySkips: 19465 + nullMoveAttempts: 1692 + nullMoveCutoffs: 1383 +depths: +- 4 +- 5 +filter: initial-position diff --git a/results/2.1.003/measurement-initial-position-null-move-v1.yaml b/results/2.1.003/measurement-initial-position-null-move-v1.yaml new file mode 100644 index 00000000..e5461613 --- /dev/null +++ b/results/2.1.003/measurement-initial-position-null-move-v1.yaml @@ -0,0 +1,108 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:50:00.353871+00:00' +mode: search +repeat: 3 +topCount: 3 +diagnostics: true +cases: +- name: initial-position + category: opening + notes: High-branching opening baseline. + summaries: + - name: initial-position + category: opening + mode: search + medianMs: 7053.1786 + units: 134821 + unitsLabel: evals + unitsPerMs: 19.114928 + notes: High-branching opening baseline. + depth: 4 + topMoves: + - san: d3d5 + score: -0.0 + - san: h3h5 + score: -0.0 + - san: c2c4 + score: -0.0 + metrics: + wallMs: 7027.559800073504 + evalsPerMs: 19.184610851492128 + rootMoves: 51 + negamaxNodes: 155774 + quiescenceNodes: 136519 + movegenCalls: 151795 + tacticalMovegenCalls: 28246 + legalContextCalls: 151795 + ttHits: 35137 + ttCutoffs: 33924 + betaCutoffs: 18648 + ttEntries: 136337 + negamaxTtHits: 32861 + quiescenceTtHits: 2276 + negamaxTtCutoffs: 32226 + quiescenceTtCutoffs: 1698 + negamaxBetaCutoffs: 8274 + quiescenceBetaCutoffs: 10374 + qsearchStandPatCutoffs: 106575 + qsearchDeltaPruneChecks: 1206 + qsearchDeltaPruneSkips: 1177 + qsearchNodesWithMoves: 19316 + qsearchGeneratedMoves: 37747 + pvsResearches: 738 + negamaxFrontierFutilityChecks: 139389 + negamaxFrontierFutilitySkips: 6899 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - name: initial-position + category: opening + mode: search + medianMs: 29571.1113 + units: 665456 + unitsLabel: evals + unitsPerMs: 22.503584 + notes: High-branching opening baseline. + depth: 5 + topMoves: + - san: d3d5 + score: -0.32000000000000006 + - san: h3h5 + score: -0.32000000000000006 + - san: c2c4 + score: -0.32000000000000006 + metrics: + wallMs: 29572.809800039977 + evalsPerMs: 22.50229195330301 + rootMoves: 51 + negamaxNodes: 391552 + quiescenceNodes: 691299 + movegenCalls: 692391 + tacticalMovegenCalls: 390386 + legalContextCalls: 692391 + ttHits: 121118 + ttCutoffs: 114008 + betaCutoffs: 231272 + ttEntries: 669829 + negamaxTtHits: 91484 + quiescenceTtHits: 29634 + negamaxTtCutoffs: 88165 + quiescenceTtCutoffs: 25843 + negamaxBetaCutoffs: 68818 + quiescenceBetaCutoffs: 162454 + qsearchStandPatCutoffs: 275070 + qsearchDeltaPruneChecks: 37568 + qsearchDeltaPruneSkips: 34205 + qsearchNodesWithMoves: 324483 + qsearchGeneratedMoves: 775113 + pvsResearches: 1692 + negamaxFrontierFutilityChecks: 242858 + negamaxFrontierFutilitySkips: 19465 + nullMoveAttempts: 1692 + nullMoveCutoffs: 1383 +depths: +- 4 +- 5 +filter: initial-position diff --git a/results/2.1.003/measurement-initial-position.yaml b/results/2.1.003/measurement-initial-position.yaml new file mode 100644 index 00000000..ca9c163b --- /dev/null +++ b/results/2.1.003/measurement-initial-position.yaml @@ -0,0 +1,99 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T11:10:14.209357+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: initial-position + category: opening + notes: High-branching opening baseline. + summaries: + - name: initial-position + category: opening + mode: search + medianMs: 7157.5902 + units: 140300 + unitsLabel: evals + unitsPerMs: 19.601569 + notes: High-branching opening baseline. + depth: 4 + topMoves: + - san: d3d5 + score: -0.0 + - san: h3h5 + score: -0.0 + - san: c2c4 + score: -0.0 + metrics: + wallMs: 7151.882099919021 + evalsPerMs: 19.6172137683294 + rootMoves: 51 + negamaxNodes: 162671 + quiescenceNodes: 141994 + movegenCalls: 157279 + tacticalMovegenCalls: 28238 + legalContextCalls: 157279 + ttHits: 36537 + ttCutoffs: 35325 + betaCutoffs: 18645 + negamaxTtHits: 34266 + quiescenceTtHits: 2271 + negamaxTtCutoffs: 33631 + quiescenceTtCutoffs: 1694 + negamaxBetaCutoffs: 8274 + quiescenceBetaCutoffs: 10371 + qsearchStandPatCutoffs: 112062 + qsearchDeltaPruneChecks: 1205 + qsearchDeltaPruneSkips: 1176 + qsearchNodesWithMoves: 19308 + qsearchGeneratedMoves: 37724 + pvsResearches: 736 + ttEntries: 141817 + - name: initial-position + category: opening + mode: search + medianMs: 45708.8869 + units: 1012033 + unitsLabel: evals + unitsPerMs: 22.140837 + notes: High-branching opening baseline. + depth: 5 + topMoves: + - san: d3d5 + score: -0.32000000000000006 + - san: h3h5 + score: -0.32000000000000006 + - san: c2c4 + score: -0.32000000000000006 + metrics: + wallMs: 45657.01609989628 + evalsPerMs: 22.165990825718875 + rootMoves: 51 + negamaxNodes: 572449 + quiescenceNodes: 1082998 + movegenCalls: 1095773 + tacticalMovegenCalls: 638608 + legalContextCalls: 1095773 + ttHits: 196814 + ttCutoffs: 186250 + betaCutoffs: 386926 + negamaxTtHits: 119781 + quiescenceTtHits: 77033 + negamaxTtCutoffs: 115285 + quiescenceTtCutoffs: 70965 + negamaxBetaCutoffs: 124681 + quiescenceBetaCutoffs: 262245 + qsearchStandPatCutoffs: 373425 + qsearchDeltaPruneChecks: 62952 + qsearchDeltaPruneSkips: 58130 + qsearchNodesWithMoves: 528843 + qsearchGeneratedMoves: 1257887 + pvsResearches: 2286 + ttEntries: 1027483 +depths: +- 4 +- 5 +filter: initial-position diff --git a/results/2.1.003/measurement-tt-transposition-midgame-delta-prune-v2.yaml b/results/2.1.003/measurement-tt-transposition-midgame-delta-prune-v2.yaml new file mode 100644 index 00000000..fd2a1334 --- /dev/null +++ b/results/2.1.003/measurement-tt-transposition-midgame-delta-prune-v2.yaml @@ -0,0 +1,105 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:36:33.969797+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: tt-transposition-midgame + category: middlegame + notes: Symmetric tactical middlegame intended to increase transposition-table reuse. + summaries: + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 868.8144 + units: 20004 + unitsLabel: evals + unitsPerMs: 23.02448 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 4 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 867.4626001156867 + evalsPerMs: 23.060360178447144 + rootMoves: 57 + negamaxNodes: 20332 + quiescenceNodes: 20869 + movegenCalls: 26543 + tacticalMovegenCalls: 8824 + legalContextCalls: 26543 + ttHits: 4074 + ttCutoffs: 3479 + betaCutoffs: 6868 + negamaxTtHits: 2899 + quiescenceTtHits: 1175 + negamaxTtCutoffs: 2614 + quiescenceTtCutoffs: 865 + negamaxBetaCutoffs: 3565 + quiescenceBetaCutoffs: 3303 + qsearchStandPatCutoffs: 11180 + qsearchDeltaPruneChecks: 4163 + qsearchDeltaPruneSkips: 3377 + qsearchNodesWithMoves: 6305 + qsearchGeneratedMoves: 17040 + pvsResearches: 47 + negamaxFrontierFutilityChecks: 24027 + negamaxFrontierFutilitySkips: 15813 + ttEntries: 22373 + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 4860.7954 + units: 80343 + unitsLabel: evals + unitsPerMs: 16.528776 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 5 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 4861.974599771202 + evalsPerMs: 16.524767530414668 + rootMoves: 57 + negamaxNodes: 134022 + quiescenceNodes: 83466 + movegenCalls: 139336 + tacticalMovegenCalls: 40587 + legalContextCalls: 139336 + ttHits: 39753 + ttCutoffs: 38558 + betaCutoffs: 38241 + negamaxTtHits: 35848 + quiescenceTtHits: 3905 + negamaxTtCutoffs: 35274 + quiescenceTtCutoffs: 3284 + negamaxBetaCutoffs: 30865 + quiescenceBetaCutoffs: 7376 + qsearchStandPatCutoffs: 39595 + qsearchDeltaPruneChecks: 13097 + qsearchDeltaPruneSkips: 8268 + qsearchNodesWithMoves: 19884 + qsearchGeneratedMoves: 33318 + pvsResearches: 124 + negamaxFrontierFutilityChecks: 73884 + negamaxFrontierFutilitySkips: 28154 + ttEntries: 93420 +depths: +- 4 +- 5 +filter: tt-transposition-midgame diff --git a/results/2.1.003/measurement-tt-transposition-midgame-frontier-futility-v2.yaml b/results/2.1.003/measurement-tt-transposition-midgame-frontier-futility-v2.yaml new file mode 100644 index 00000000..4d5e619a --- /dev/null +++ b/results/2.1.003/measurement-tt-transposition-midgame-frontier-futility-v2.yaml @@ -0,0 +1,105 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:07:42.561054+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: tt-transposition-midgame + category: middlegame + notes: Symmetric tactical middlegame intended to increase transposition-table reuse. + summaries: + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 866.4002 + units: 20556 + unitsLabel: evals + unitsPerMs: 23.725756 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 4 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 862.3503004200757 + evalsPerMs: 23.837180772113815 + rootMoves: 57 + negamaxNodes: 20418 + quiescenceNodes: 21658 + movegenCalls: 26714 + tacticalMovegenCalls: 8950 + legalContextCalls: 26714 + ttHits: 4359 + ttCutoffs: 3757 + betaCutoffs: 6931 + negamaxTtHits: 2943 + quiescenceTtHits: 1416 + negamaxTtCutoffs: 2655 + quiescenceTtCutoffs: 1102 + negamaxBetaCutoffs: 3565 + quiescenceBetaCutoffs: 3366 + qsearchStandPatCutoffs: 11606 + qsearchDeltaPruneChecks: 2869 + qsearchDeltaPruneSkips: 2743 + qsearchNodesWithMoves: 6384 + qsearchGeneratedMoves: 17362 + pvsResearches: 47 + negamaxFrontierFutilityChecks: 24111 + negamaxFrontierFutilitySkips: 15813 + ttEntries: 22877 + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 4924.041 + units: 80745 + unitsLabel: evals + unitsPerMs: 16.398117 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 5 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 4967.168100178242 + evalsPerMs: 16.255741374466982 + rootMoves: 57 + negamaxNodes: 134023 + quiescenceNodes: 84078 + movegenCalls: 139338 + tacticalMovegenCalls: 40587 + legalContextCalls: 139338 + ttHits: 39969 + ttCutoffs: 38767 + betaCutoffs: 38241 + negamaxTtHits: 35849 + quiescenceTtHits: 4120 + negamaxTtCutoffs: 35273 + quiescenceTtCutoffs: 3494 + negamaxBetaCutoffs: 30866 + quiescenceBetaCutoffs: 7375 + qsearchStandPatCutoffs: 39997 + qsearchDeltaPruneChecks: 9838 + qsearchDeltaPruneSkips: 7655 + qsearchNodesWithMoves: 19883 + qsearchGeneratedMoves: 33311 + pvsResearches: 124 + negamaxFrontierFutilityChecks: 73884 + negamaxFrontierFutilitySkips: 28154 + ttEntries: 93817 +depths: +- 4 +- 5 +filter: tt-transposition-midgame diff --git a/results/2.1.003/measurement-tt-transposition-midgame-frontier-futility.yaml b/results/2.1.003/measurement-tt-transposition-midgame-frontier-futility.yaml new file mode 100644 index 00000000..3b2421d4 --- /dev/null +++ b/results/2.1.003/measurement-tt-transposition-midgame-frontier-futility.yaml @@ -0,0 +1,105 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:02:08.471481+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: tt-transposition-midgame + category: middlegame + notes: Symmetric tactical middlegame intended to increase transposition-table reuse. + summaries: + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 863.6003 + units: 20556 + unitsLabel: evals + unitsPerMs: 23.802678 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 4 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 853.12689980492 + evalsPerMs: 24.094891398572045 + rootMoves: 57 + negamaxNodes: 20418 + quiescenceNodes: 21658 + movegenCalls: 26714 + tacticalMovegenCalls: 8950 + legalContextCalls: 26714 + ttHits: 4359 + ttCutoffs: 3757 + betaCutoffs: 6931 + negamaxTtHits: 2943 + quiescenceTtHits: 1416 + negamaxTtCutoffs: 2655 + quiescenceTtCutoffs: 1102 + negamaxBetaCutoffs: 3565 + quiescenceBetaCutoffs: 3366 + qsearchStandPatCutoffs: 11606 + qsearchDeltaPruneChecks: 2869 + qsearchDeltaPruneSkips: 2743 + qsearchNodesWithMoves: 6384 + qsearchGeneratedMoves: 17362 + pvsResearches: 47 + negamaxFrontierFutilityChecks: 16031 + negamaxFrontierFutilitySkips: 15813 + ttEntries: 22877 + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 4859.3575 + units: 80745 + unitsLabel: evals + unitsPerMs: 16.616394 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 5 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 4856.747999787331 + evalsPerMs: 16.625322129856375 + rootMoves: 57 + negamaxNodes: 134023 + quiescenceNodes: 84078 + movegenCalls: 139338 + tacticalMovegenCalls: 40587 + legalContextCalls: 139338 + ttHits: 39969 + ttCutoffs: 38767 + betaCutoffs: 38241 + negamaxTtHits: 35849 + quiescenceTtHits: 4120 + negamaxTtCutoffs: 35273 + quiescenceTtCutoffs: 3494 + negamaxBetaCutoffs: 30866 + quiescenceBetaCutoffs: 7375 + qsearchStandPatCutoffs: 39997 + qsearchDeltaPruneChecks: 9838 + qsearchDeltaPruneSkips: 7655 + qsearchNodesWithMoves: 19883 + qsearchGeneratedMoves: 33311 + pvsResearches: 124 + negamaxFrontierFutilityChecks: 29636 + negamaxFrontierFutilitySkips: 28154 + ttEntries: 93817 +depths: +- 4 +- 5 +filter: tt-transposition-midgame diff --git a/results/2.1.003/measurement-tt-transposition-midgame-leaf-fastpath.yaml b/results/2.1.003/measurement-tt-transposition-midgame-leaf-fastpath.yaml new file mode 100644 index 00000000..71a12e5b --- /dev/null +++ b/results/2.1.003/measurement-tt-transposition-midgame-leaf-fastpath.yaml @@ -0,0 +1,110 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T17:14:25.219539+00:00' +mode: search +repeat: 3 +topCount: 3 +diagnostics: true +cases: +- name: tt-transposition-midgame + category: middlegame + notes: Symmetric tactical middlegame intended to increase transposition-table reuse. + summaries: + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 552.4634 + units: 20556 + unitsLabel: evals + unitsPerMs: 37.207895 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 4 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 550.5667999386787 + evalsPerMs: 37.336068942568815 + rootMoves: 57 + negamaxNodes: 20418 + quiescenceNodes: 21658 + movegenCalls: 14885 + tacticalMovegenCalls: 8950 + legalContextCalls: 14885 + ttHits: 4359 + ttCutoffs: 3757 + betaCutoffs: 6931 + ttEntries: 22877 + negamaxTtHits: 2943 + quiescenceTtHits: 1416 + negamaxTtCutoffs: 2655 + quiescenceTtCutoffs: 1102 + negamaxBetaCutoffs: 3565 + quiescenceBetaCutoffs: 3366 + qsearchStandPatCutoffs: 11606 + qsearchDeltaPruneChecks: 2869 + qsearchDeltaPruneSkips: 2743 + qsearchNodesWithMoves: 6384 + qsearchGeneratedMoves: 17362 + pvsResearches: 47 + negamaxFrontierFutilityChecks: 24111 + negamaxFrontierFutilitySkips: 15813 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 2763.5909 + units: 72364 + unitsLabel: evals + unitsPerMs: 26.184773 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 5 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 2759.440999943763 + evalsPerMs: 26.22415192115895 + rootMoves: 57 + negamaxNodes: 111740 + quiescenceNodes: 75990 + movegenCalls: 67232 + tacticalMovegenCalls: 34044 + legalContextCalls: 67232 + ttHits: 35385 + ttCutoffs: 34329 + betaCutoffs: 29593 + ttEntries: 81459 + negamaxTtHits: 31147 + quiescenceTtHits: 4238 + negamaxTtCutoffs: 30609 + quiescenceTtCutoffs: 3720 + negamaxBetaCutoffs: 22029 + quiescenceBetaCutoffs: 7564 + qsearchStandPatCutoffs: 38226 + qsearchDeltaPruneChecks: 9709 + qsearchDeltaPruneSkips: 7113 + qsearchNodesWithMoves: 18539 + qsearchGeneratedMoves: 34540 + pvsResearches: 131 + negamaxFrontierFutilityChecks: 71328 + negamaxFrontierFutilitySkips: 28204 + nullMoveAttempts: 1184 + nullMoveCutoffs: 501 +depths: +- 4 +- 5 +filter: tt-transposition-midgame diff --git a/results/2.1.003/measurement-tt-transposition-midgame-null-move-v1.yaml b/results/2.1.003/measurement-tt-transposition-midgame-null-move-v1.yaml new file mode 100644 index 00000000..149371ce --- /dev/null +++ b/results/2.1.003/measurement-tt-transposition-midgame-null-move-v1.yaml @@ -0,0 +1,110 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T13:47:58.606425+00:00' +mode: search +repeat: 3 +topCount: 3 +diagnostics: true +cases: +- name: tt-transposition-midgame + category: middlegame + notes: Symmetric tactical middlegame intended to increase transposition-table reuse. + summaries: + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 897.7618 + units: 20556 + unitsLabel: evals + unitsPerMs: 22.896942 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 4 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 901.2339003384113 + evalsPerMs: 22.808729223657995 + rootMoves: 57 + negamaxNodes: 20418 + quiescenceNodes: 21658 + movegenCalls: 26714 + tacticalMovegenCalls: 8950 + legalContextCalls: 26714 + ttHits: 4359 + ttCutoffs: 3757 + betaCutoffs: 6931 + ttEntries: 22877 + negamaxTtHits: 2943 + quiescenceTtHits: 1416 + negamaxTtCutoffs: 2655 + quiescenceTtCutoffs: 1102 + negamaxBetaCutoffs: 3565 + quiescenceBetaCutoffs: 3366 + qsearchStandPatCutoffs: 11606 + qsearchDeltaPruneChecks: 2869 + qsearchDeltaPruneSkips: 2743 + qsearchNodesWithMoves: 6384 + qsearchGeneratedMoves: 17362 + pvsResearches: 47 + negamaxFrontierFutilityChecks: 24111 + negamaxFrontierFutilitySkips: 15813 + nullMoveAttempts: 0 + nullMoveCutoffs: 0 + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 3998.3462 + units: 72366 + unitsLabel: evals + unitsPerMs: 18.098983 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 5 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 3993.520400021225 + evalsPerMs: 18.120853971251876 + rootMoves: 57 + negamaxNodes: 111743 + quiescenceNodes: 75990 + movegenCalls: 114677 + tacticalMovegenCalls: 34044 + legalContextCalls: 114677 + ttHits: 35386 + ttCutoffs: 34330 + betaCutoffs: 29593 + ttEntries: 81459 + negamaxTtHits: 31148 + quiescenceTtHits: 4238 + negamaxTtCutoffs: 30610 + quiescenceTtCutoffs: 3720 + negamaxBetaCutoffs: 22029 + quiescenceBetaCutoffs: 7564 + qsearchStandPatCutoffs: 38226 + qsearchDeltaPruneChecks: 9709 + qsearchDeltaPruneSkips: 7113 + qsearchNodesWithMoves: 18539 + qsearchGeneratedMoves: 34540 + pvsResearches: 131 + negamaxFrontierFutilityChecks: 71328 + negamaxFrontierFutilitySkips: 28204 + nullMoveAttempts: 1184 + nullMoveCutoffs: 501 +depths: +- 4 +- 5 +filter: tt-transposition-midgame diff --git a/results/2.1.003/measurement-tt-transposition-midgame.yaml b/results/2.1.003/measurement-tt-transposition-midgame.yaml new file mode 100644 index 00000000..bd1131b2 --- /dev/null +++ b/results/2.1.003/measurement-tt-transposition-midgame.yaml @@ -0,0 +1,101 @@ +version: 1 +kind: pyengine2-benchmark-run +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T11:07:05.859662+00:00' +mode: search +repeat: 3 +topCount: 3 +cases: +- name: tt-transposition-midgame + category: middlegame + notes: Symmetric tactical middlegame intended to increase transposition-table reuse. + summaries: + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 1208.8564 + units: 29818 + unitsLabel: evals + unitsPerMs: 24.666288 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 4 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 1201.3954003341496 + evalsPerMs: 24.819472416580407 + rootMoves: 57 + negamaxNodes: 36231 + quiescenceNodes: 30919 + movegenCalls: 35976 + tacticalMovegenCalls: 8951 + legalContextCalls: 35976 + ttHits: 10949 + ttCutoffs: 10308 + betaCutoffs: 6931 + negamaxTtHits: 9514 + quiescenceTtHits: 1435 + negamaxTtCutoffs: 9207 + quiescenceTtCutoffs: 1101 + negamaxBetaCutoffs: 3565 + quiescenceBetaCutoffs: 3366 + qsearchStandPatCutoffs: 20867 + qsearchDeltaPruneChecks: 2869 + qsearchDeltaPruneSkips: 2743 + qsearchNodesWithMoves: 6384 + qsearchGeneratedMoves: 17362 + pvsResearches: 47 + ttEntries: 32119 + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 5336.4156 + units: 97117 + unitsLabel: evals + unitsPerMs: 18.19892 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 5 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 5351.873999927193 + evalsPerMs: 18.146353968968846 + rootMoves: 57 + negamaxNodes: 161851 + quiescenceNodes: 100431 + movegenCalls: 155717 + tacticalMovegenCalls: 40541 + legalContextCalls: 155717 + ttHits: 51364 + ttCutoffs: 50156 + betaCutoffs: 38211 + negamaxTtHits: 47257 + quiescenceTtHits: 4107 + negamaxTtCutoffs: 46676 + quiescenceTtCutoffs: 3480 + negamaxBetaCutoffs: 30864 + quiescenceBetaCutoffs: 7347 + qsearchStandPatCutoffs: 56410 + qsearchDeltaPruneChecks: 9825 + qsearchDeltaPruneSkips: 7650 + qsearchNodesWithMoves: 19836 + qsearchGeneratedMoves: 33221 + pvsResearches: 124 + ttEntries: 110184 +depths: +- 4 +- 5 +filter: tt-transposition-midgame diff --git a/results/2.1.003/stage1-baseline-leaf-fastpath.yaml b/results/2.1.003/stage1-baseline-leaf-fastpath.yaml new file mode 100644 index 00000000..5b63e0f5 --- /dev/null +++ b/results/2.1.003/stage1-baseline-leaf-fastpath.yaml @@ -0,0 +1,279 @@ +version: 1 +kind: pyengine2-benchmark-suite +suite: stage1-baseline +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T17:12:16.414144+00:00' +topCount: 3 +diagnostics: false +entries: +- mode: eval + filter: quiet-endgame-eval + repeat: 50 + cases: + - name: quiet-endgame-eval + category: endgame + notes: Quiet low-material position intended to make evaluation cost easier to + isolate. + summary: + name: quiet-endgame-eval + category: endgame + mode: eval + medianMs: 0.0025 + units: 50 + unitsLabel: evals + unitsPerMs: 19998.916446 + notes: Quiet low-material position intended to make evaluation cost easier to + isolate. + staticEval: 90.0 +- mode: moves + filter: slider-mobility-open + repeat: 10 + cases: + - name: slider-mobility-open + category: middlegame + notes: Open-board slider position intended to stress bishop, rook, and queen generation. + summary: + name: slider-mobility-open + category: middlegame + mode: moves + medianMs: 0.0423 + units: 114 + unitsLabel: moves + unitsPerMs: 2695.022357 + notes: Open-board slider position intended to stress bishop, rook, and queen + generation. + sampleMoves: + - a1b3 + - a1a2 + - a1b2 +- mode: tactical-moves + filter: capture-storm-qsearch + repeat: 10 + cases: + - name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summary: + name: capture-storm-qsearch + category: tactics + mode: tactical-moves + medianMs: 0.00745 + units: 3 + unitsLabel: moves + unitsPerMs: 402.678351 + notes: Capture-dense position intended to stress tactical generation and qsearch. + sampleMoves: + - f5f7 + - f5g6 + - f5h5 +- mode: search + filter: tt-transposition-midgame + repeat: 3 + cases: + - name: tt-transposition-midgame + category: middlegame + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + summaries: + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 541.3522 + units: 20556 + unitsLabel: evals + unitsPerMs: 37.971583 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 4 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 539.1106000170112 + evalsPerMs: 38.12946731032811 + rootMoves: 57 + negamaxNodes: 20418 + quiescenceNodes: 21658 + movegenCalls: 14885 + tacticalMovegenCalls: 8950 + legalContextCalls: 14885 + ttHits: 4359 + ttCutoffs: 3757 + betaCutoffs: 6931 + ttEntries: 22877 + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 2762.122 + units: 72364 + unitsLabel: evals + unitsPerMs: 26.198698 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 5 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 2804.742000065744 + evalsPerMs: 25.800590570649195 + rootMoves: 57 + negamaxNodes: 111740 + quiescenceNodes: 75990 + movegenCalls: 67232 + tacticalMovegenCalls: 34044 + legalContextCalls: 67232 + ttHits: 35385 + ttCutoffs: 34329 + betaCutoffs: 29593 + ttEntries: 81459 + depths: + - 4 + - 5 +- mode: search + filter: capture-storm-qsearch + repeat: 3 + cases: + - name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summaries: + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 212.1574 + units: 7900 + unitsLabel: evals + unitsPerMs: 37.236505 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 4 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5c8 + score: -19.200000000000003 + metrics: + wallMs: 213.113599922508 + evalsPerMs: 37.06943152793902 + rootMoves: 36 + negamaxNodes: 15028 + quiescenceNodes: 8267 + movegenCalls: 5493 + tacticalMovegenCalls: 2146 + legalContextCalls: 5493 + ttHits: 6371 + ttCutoffs: 5691 + betaCutoffs: 2284 + ttEntries: 8932 + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 506.4297 + units: 13862 + unitsLabel: evals + unitsPerMs: 27.372012 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 5 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5g4 + score: -19.599999999999994 + metrics: + wallMs: 506.4558000303805 + evalsPerMs: 27.37060173695013 + rootMoves: 36 + negamaxNodes: 36986 + quiescenceNodes: 13972 + movegenCalls: 13876 + tacticalMovegenCalls: 5362 + legalContextCalls: 13876 + ttHits: 19171 + ttCutoffs: 17367 + betaCutoffs: 5127 + ttEntries: 14560 + depths: + - 4 + - 5 +- mode: search + filter: initial-position + repeat: 3 + cases: + - name: initial-position + category: opening + notes: High-branching opening baseline. + summaries: + - name: initial-position + category: opening + mode: search + medianMs: 3209.968 + units: 134821 + unitsLabel: evals + unitsPerMs: 42.00073 + notes: High-branching opening baseline. + depth: 4 + topMoves: + - san: d3d5 + score: -0.0 + - san: h3h5 + score: -0.0 + - san: c2c4 + score: -0.0 + metrics: + wallMs: 3204.1182997636497 + evalsPerMs: 42.07741019111092 + rootMoves: 51 + negamaxNodes: 155774 + quiescenceNodes: 136519 + movegenCalls: 40073 + tacticalMovegenCalls: 28246 + legalContextCalls: 40073 + ttHits: 35137 + ttCutoffs: 33924 + betaCutoffs: 18648 + ttEntries: 136337 + - name: initial-position + category: opening + mode: search + medianMs: 22012.0274 + units: 665456 + unitsLabel: evals + unitsPerMs: 30.231472 + notes: High-branching opening baseline. + depth: 5 + topMoves: + - san: d3d5 + score: -0.32000000000000006 + - san: h3h5 + score: -0.32000000000000006 + - san: c2c4 + score: -0.32000000000000006 + metrics: + wallMs: 21981.43280018121 + evalsPerMs: 30.273549774904307 + rootMoves: 51 + negamaxNodes: 391552 + quiescenceNodes: 691299 + movegenCalls: 467305 + tacticalMovegenCalls: 390386 + legalContextCalls: 467305 + ttHits: 121118 + ttCutoffs: 114008 + betaCutoffs: 231272 + ttEntries: 669829 + depths: + - 4 + - 5 diff --git a/results/2.1.003/stage1-baseline-null-move.yaml b/results/2.1.003/stage1-baseline-null-move.yaml new file mode 100644 index 00000000..47801923 --- /dev/null +++ b/results/2.1.003/stage1-baseline-null-move.yaml @@ -0,0 +1,279 @@ +version: 1 +kind: pyengine2-benchmark-suite +suite: stage1-baseline +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-26T14:24:20.648361+00:00' +topCount: 3 +diagnostics: false +entries: +- mode: eval + filter: quiet-endgame-eval + repeat: 50 + cases: + - name: quiet-endgame-eval + category: endgame + notes: Quiet low-material position intended to make evaluation cost easier to + isolate. + summary: + name: quiet-endgame-eval + category: endgame + mode: eval + medianMs: 0.0019 + units: 50 + unitsLabel: evals + unitsPerMs: 26317.201569 + notes: Quiet low-material position intended to make evaluation cost easier to + isolate. + staticEval: 90.0 +- mode: moves + filter: slider-mobility-open + repeat: 10 + cases: + - name: slider-mobility-open + category: middlegame + notes: Open-board slider position intended to stress bishop, rook, and queen generation. + summary: + name: slider-mobility-open + category: middlegame + mode: moves + medianMs: 0.0428 + units: 114 + unitsLabel: moves + unitsPerMs: 2663.53112 + notes: Open-board slider position intended to stress bishop, rook, and queen + generation. + sampleMoves: + - a1b3 + - a1a2 + - a1b2 +- mode: tactical-moves + filter: capture-storm-qsearch + repeat: 10 + cases: + - name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summary: + name: capture-storm-qsearch + category: tactics + mode: tactical-moves + medianMs: 0.007 + units: 3 + unitsLabel: moves + unitsPerMs: 428.58242 + notes: Capture-dense position intended to stress tactical generation and qsearch. + sampleMoves: + - f5f7 + - f5g6 + - f5h5 +- mode: search + filter: tt-transposition-midgame + repeat: 3 + cases: + - name: tt-transposition-midgame + category: middlegame + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + summaries: + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 862.7077 + units: 20556 + unitsLabel: evals + unitsPerMs: 23.827306 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 4 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 851.2915000319481 + evalsPerMs: 24.14684041744638 + rootMoves: 57 + negamaxNodes: 20418 + quiescenceNodes: 21658 + movegenCalls: 26714 + tacticalMovegenCalls: 8950 + legalContextCalls: 26714 + ttHits: 4359 + ttCutoffs: 3757 + betaCutoffs: 6931 + ttEntries: 22877 + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 3891.1126 + units: 72366 + unitsLabel: evals + unitsPerMs: 18.597766 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 5 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 3881.480500102043 + evalsPerMs: 18.643916927599538 + rootMoves: 57 + negamaxNodes: 111743 + quiescenceNodes: 75990 + movegenCalls: 114677 + tacticalMovegenCalls: 34044 + legalContextCalls: 114677 + ttHits: 35386 + ttCutoffs: 34330 + betaCutoffs: 29593 + ttEntries: 81459 + depths: + - 4 + - 5 +- mode: search + filter: capture-storm-qsearch + repeat: 3 + cases: + - name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summaries: + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 335.9218 + units: 7900 + unitsLabel: evals + unitsPerMs: 23.517378 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 4 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5c8 + score: -19.200000000000003 + metrics: + wallMs: 335.96810000017285 + evalsPerMs: 23.514137205276143 + rootMoves: 36 + negamaxNodes: 15028 + quiescenceNodes: 8267 + movegenCalls: 11862 + tacticalMovegenCalls: 2146 + legalContextCalls: 11862 + ttHits: 6371 + ttCutoffs: 5691 + betaCutoffs: 2284 + ttEntries: 8932 + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 701.7605 + units: 13862 + unitsLabel: evals + unitsPerMs: 19.753178 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 5 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5g4 + score: -19.599999999999994 + metrics: + wallMs: 690.6518000178039 + evalsPerMs: 20.070895347905644 + rootMoves: 36 + negamaxNodes: 36986 + quiescenceNodes: 13972 + movegenCalls: 24475 + tacticalMovegenCalls: 5362 + legalContextCalls: 24475 + ttHits: 19171 + ttCutoffs: 17367 + betaCutoffs: 5127 + ttEntries: 14560 + depths: + - 4 + - 5 +- mode: search + filter: initial-position + repeat: 3 + cases: + - name: initial-position + category: opening + notes: High-branching opening baseline. + summaries: + - name: initial-position + category: opening + mode: search + medianMs: 6954.9863 + units: 134821 + unitsLabel: evals + unitsPerMs: 19.384797 + notes: High-branching opening baseline. + depth: 4 + topMoves: + - san: d3d5 + score: -0.0 + - san: h3h5 + score: -0.0 + - san: c2c4 + score: -0.0 + metrics: + wallMs: 6949.039000086486 + evalsPerMs: 19.4013877312132 + rootMoves: 51 + negamaxNodes: 155774 + quiescenceNodes: 136519 + movegenCalls: 151795 + tacticalMovegenCalls: 28246 + legalContextCalls: 151795 + ttHits: 35137 + ttCutoffs: 33924 + betaCutoffs: 18648 + ttEntries: 136337 + - name: initial-position + category: opening + mode: search + medianMs: 28935.6774 + units: 665456 + unitsLabel: evals + unitsPerMs: 22.997768 + notes: High-branching opening baseline. + depth: 5 + topMoves: + - san: d3d5 + score: -0.32000000000000006 + - san: h3h5 + score: -0.32000000000000006 + - san: c2c4 + score: -0.32000000000000006 + metrics: + wallMs: 28944.870799779892 + evalsPerMs: 22.99046365081928 + rootMoves: 51 + negamaxNodes: 391552 + quiescenceNodes: 691299 + movegenCalls: 692391 + tacticalMovegenCalls: 390386 + legalContextCalls: 692391 + ttHits: 121118 + ttCutoffs: 114008 + betaCutoffs: 231272 + ttEntries: 669829 + depths: + - 4 + - 5 diff --git a/results/2.1.003/stage1-baseline-python314-check.yaml b/results/2.1.003/stage1-baseline-python314-check.yaml new file mode 100644 index 00000000..e41386bd --- /dev/null +++ b/results/2.1.003/stage1-baseline-python314-check.yaml @@ -0,0 +1,279 @@ +version: 1 +kind: pyengine2-benchmark-suite +suite: stage1-baseline +pyengine2Version: 2.1.003 +benchmarkFile: G:\work\Training\hexchess\pyengine2\benchmark\benchmarks.yaml +generatedAt: '2026-03-29T09:54:58.568793+00:00' +topCount: 3 +diagnostics: false +entries: +- mode: eval + filter: quiet-endgame-eval + repeat: 50 + cases: + - name: quiet-endgame-eval + category: endgame + notes: Quiet low-material position intended to make evaluation cost easier to + isolate. + summary: + name: quiet-endgame-eval + category: endgame + mode: eval + medianMs: 0.0021 + units: 50 + unitsLabel: evals + unitsPerMs: 23809.342513 + notes: Quiet low-material position intended to make evaluation cost easier to + isolate. + staticEval: 90.0 +- mode: moves + filter: slider-mobility-open + repeat: 10 + cases: + - name: slider-mobility-open + category: middlegame + notes: Open-board slider position intended to stress bishop, rook, and queen generation. + summary: + name: slider-mobility-open + category: middlegame + mode: moves + medianMs: 0.04415 + units: 114 + unitsLabel: moves + unitsPerMs: 2582.106368 + notes: Open-board slider position intended to stress bishop, rook, and queen + generation. + sampleMoves: + - a1b3 + - a1a2 + - a1b2 +- mode: tactical-moves + filter: capture-storm-qsearch + repeat: 10 + cases: + - name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summary: + name: capture-storm-qsearch + category: tactics + mode: tactical-moves + medianMs: 0.0076 + units: 3 + unitsLabel: moves + unitsPerMs: 394.73686 + notes: Capture-dense position intended to stress tactical generation and qsearch. + sampleMoves: + - f5f7 + - f5g6 + - f5h5 +- mode: search + filter: tt-transposition-midgame + repeat: 3 + cases: + - name: tt-transposition-midgame + category: middlegame + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + summaries: + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 594.217 + units: 20556 + unitsLabel: evals + unitsPerMs: 34.593423 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 4 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 592.453299992485 + evalsPerMs: 34.69640560743057 + rootMoves: 57 + negamaxNodes: 20418 + quiescenceNodes: 21658 + movegenCalls: 14885 + tacticalMovegenCalls: 8950 + legalContextCalls: 14885 + ttHits: 4359 + ttCutoffs: 3757 + betaCutoffs: 6931 + ttEntries: 22877 + - name: tt-transposition-midgame + category: middlegame + mode: search + medianMs: 2938.8028 + units: 72364 + unitsLabel: evals + unitsPerMs: 24.623632 + notes: Symmetric tactical middlegame intended to increase transposition-table + reuse. + depth: 5 + topMoves: + - san: f5f7 + score: -130.0 + - san: g5l1 + score: -119.92 + - san: f5h3 + score: -109.84 + metrics: + wallMs: 2962.4777999997605 + evalsPerMs: 24.42684971344118 + rootMoves: 57 + negamaxNodes: 111740 + quiescenceNodes: 75990 + movegenCalls: 67232 + tacticalMovegenCalls: 34044 + legalContextCalls: 67232 + ttHits: 35385 + ttCutoffs: 34329 + betaCutoffs: 29593 + ttEntries: 81459 + depths: + - 4 + - 5 +- mode: search + filter: capture-storm-qsearch + repeat: 3 + cases: + - name: capture-storm-qsearch + category: tactics + notes: Capture-dense position intended to stress tactical generation and qsearch. + summaries: + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 223.1998 + units: 7900 + unitsLabel: evals + unitsPerMs: 35.394297 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 4 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5c8 + score: -19.200000000000003 + metrics: + wallMs: 222.5402000185568 + evalsPerMs: 35.4992041857662 + rootMoves: 36 + negamaxNodes: 15028 + quiescenceNodes: 8267 + movegenCalls: 5493 + tacticalMovegenCalls: 2146 + legalContextCalls: 5493 + ttHits: 6371 + ttCutoffs: 5691 + betaCutoffs: 2284 + ttEntries: 8932 + - name: capture-storm-qsearch + category: tactics + mode: search + medianMs: 543.0092 + units: 13862 + unitsLabel: evals + unitsPerMs: 25.528113 + notes: Capture-dense position intended to stress tactical generation and qsearch. + depth: 5 + topMoves: + - san: f5f7 + score: -79.68 + - san: f5h3 + score: -69.6 + - san: f5g4 + score: -19.599999999999994 + metrics: + wallMs: 627.2247000015341 + evalsPerMs: 22.100532711747633 + rootMoves: 36 + negamaxNodes: 36986 + quiescenceNodes: 13972 + movegenCalls: 13876 + tacticalMovegenCalls: 5362 + legalContextCalls: 13876 + ttHits: 19171 + ttCutoffs: 17367 + betaCutoffs: 5127 + ttEntries: 14560 + depths: + - 4 + - 5 +- mode: search + filter: initial-position + repeat: 3 + cases: + - name: initial-position + category: opening + notes: High-branching opening baseline. + summaries: + - name: initial-position + category: opening + mode: search + medianMs: 3381.902 + units: 134821 + unitsLabel: evals + unitsPerMs: 39.865437 + notes: High-branching opening baseline. + depth: 4 + topMoves: + - san: d3d5 + score: -0.0 + - san: h3h5 + score: -0.0 + - san: c2c4 + score: -0.0 + metrics: + wallMs: 3375.0927000073716 + evalsPerMs: 39.94586578309554 + rootMoves: 51 + negamaxNodes: 155774 + quiescenceNodes: 136519 + movegenCalls: 40073 + tacticalMovegenCalls: 28246 + legalContextCalls: 40073 + ttHits: 35137 + ttCutoffs: 33924 + betaCutoffs: 18648 + ttEntries: 136337 + - name: initial-position + category: opening + mode: search + medianMs: 23801.6768 + units: 665456 + unitsLabel: evals + unitsPerMs: 27.958366 + notes: High-branching opening baseline. + depth: 5 + topMoves: + - san: d3d5 + score: -0.32000000000000006 + - san: h3h5 + score: -0.32000000000000006 + - san: c2c4 + score: -0.32000000000000006 + metrics: + wallMs: 23763.856000005035 + evalsPerMs: 28.002862835049118 + rootMoves: 51 + negamaxNodes: 391552 + quiescenceNodes: 691299 + movegenCalls: 467305 + tacticalMovegenCalls: 390386 + legalContextCalls: 467305 + ttHits: 121118 + ttCutoffs: 114008 + betaCutoffs: 231272 + ttEntries: 669829 + depths: + - 4 + - 5