Every number on this site comes from one of a few places, and this page says which one, and what each of them does not claim. What makes a position closed is on the method page; this one is about the values, the graph, the queue and the API.
What a position row shows
A position is one row in the graph. Scores are centipawns from the side to move, the chessdb.cn convention used everywhere on this site.
eval_cp: the latest engine analysis of this position. It is what one search reported, and nothing more.backed_evalandbacked_move: the negamax over the graph, built from the analyses that really exist below this position, and the edge the value came through.backed_movepoints at where to look; it is not a recommendation an engine made here.statusandclosure: for a solved position, the verdict and the gate it closed through. Anything still open carriesUNKNOWNand no closure.backed_plies: how deep the backing chain runs, counted in plies below this position.backed_nodes: the analysis size of the weakest link on that chain. A long chain is worth what its thinnest search is worth.
A position headlines its best known value: proven status first, then the backed value, then the point eval. The point eval never headlines while something better is known, and it stays available as own search context in the tooltip and in the API point field. One position, one number.
How a backed value is built
Backing is a negamax over the graph, and it runs under four rules.
- The best informed child always backs up. There is no depth gate between a parent and its children: a child analysed at 128M nodes moves a parent analysed at 10B. Ties go to the heavier support first, then to the shallower chain, so the same graph always produces the same value.
- A multipv showcase bound grants permission, never a value. When the last analysis of a position published two or more lines, the engine asserted that no other move is better for the mover than the worst line of that showcase. That bound lifts the partial coverage guards, so the negamax runs over the informed children as if the table were complete. It never competes as a value of its own: the number is always a real child's, and a bound with no informed child under it backs nothing.
- A mate band value against the mover backs nothing under partial coverage without an anchor. A position with no evaluation of its own whose only known reply loses knows nothing about itself: the mover still has the rest of the legal moves unopened and is not going to choose that loss. A gain for the mover still travels on a single child, as always.
- Every backed value terminates in a real engine analysis, never in a loop. That terminating analysis is the anchor, and where the chip on the value is a link, the link goes to it.
One value never displaces another for free. While a position still has replies nobody has analysed, a favourable value with no engine nodes behind it, the band of a line a visitor walked, does not push aside a measured evaluation: the position keeps its own number and the analysis that would settle it is queued. The same when a favourable child carries far less search than the pass that produced the parent's own evaluation: the value propagates, the gap is recorded as an open question, and a deeper pass is bought for that child.
Repetition
The explorer is a transposition graph, not a tree. Positions are deduplicated by FEN with the counters erased, so the graph itself cannot say that a position occurred twice. Only a walk can.
A repetition therefore belongs to a path, not to a position. The same position reached by another move order is not a repetition, and nothing stored on the position says otherwise. The repetition chip appears when the line you are currently playing revisits a position it has already been through.
During a graph walk a cycle contributes exactly 0, with zero quality. Zero is what the line is worth; zero quality is what the claim deserves, because nobody has ever searched whether the repetition is forced, so it is an assertion about a walk over pointers and not a measurement. It can never settle a position that is not fully covered: while replies nobody has opened are still there, "the mover has nothing better than repeating" is a guess and not a verdict, so the position keeps its own measure and buys the analysis that answers the question either way.
Where the coverage is complete, a 0 that wins against fully analysed siblings is a real drawing line, and a parent standing on it is standing on the truth. A position published on a repetition draw shows that same draw on the row it comes from, wearing the repetition chip: a header quoting a draw that no row displays would be a bug.
Repetitions are switched off in navigation rather than merely labelled. A move that would re-enter the line you are playing renders as a disabled row with the chip, and a stored line is shown only up to its first self crossing. Reach that position through the line above it instead.
The queue
One commons, and it is public at the queue page: one row per account, read from the same predicates the ordering uses, so the page and the queue cannot disagree without it being a bug in one place.
- Every account advances by the nodes it already has queued, so the first request of a newcomer is served before the thousandth of a flooder. The unit is nodes and not rows, so one 10B request yields to the seventy-eight 128M requests it costs, and a big batch interleaves instead of walling the queue.
- Running a worker gives exactly one advantage: while it runs, your own worker serves your own requests first. It is affinity and not priority, and it scales with the CPU you are plugging in right now.
- The cap is per person: 5,000 queued requests, pending rows only. Cancelled rows do not count, running rows do not count, and clearing your queue gives the allowance back immediately.
- Backing a request charges it to the best placed of its requesters, which is what makes backing move things. Authorship never moves; only the charge does.
Asking for a position somebody else already asked for joins their request instead of queueing a duplicate, and every account that asked is notified when the analysis lands. Repeated requests buy genuinely deeper searches, up the ladder of 128M, 512M, 2B and 10B nodes.
Contributing and attribution
Every completed analysis records the authenticated account that delivered it, and the boards on the front page group by that stamp.
Machine names are chosen by the worker, and two accounts can announce the same one, so attribution never rests on a machine name where it can be avoided. Rows older than the stamp fall back to the machine map, and only for unambiguous machines: a disputed name attributes to nobody. Those nodes still count for the fleet, because they were really searched, and the page says out loud what belongs to nobody.
Contributing compute needs an account and the worker, and the instructions for both are on the method page. Contributing without hardware needs neither: every unsolved position has a request button, and that request rides the same queue as everything else.
API
Request: POST /atomicdb/api/request with fen. budget picks a rung of the ladder and is optional, honoured for the accounts the explorer offers the depth slider to. username and password put the request on your account, which is what buys the notification when it lands, the affinity with your own workers and your place in the fair share. Without them the request is anonymous, which works, and is served like a click without a session. A FEN the tree does not have is seeded rather than refused. Session cookies are deliberately ignored here, so a page open in your browser cannot spend your queue behind your back.
There is no hourly limit on this door, same as the explorer button: what governs both is the per-person cap on queued requests above, and the per-account sharing of the service order. Every call still leaves a receipt.
Your queue: POST /atomicdb/api/my-queue/ with username and password (your OpenBench credentials, same as a worker) returns your PENDING and LEASED requests: task ids, position keys, budgets, state, and the bump / cancel paths each row accepts. A logged-in browser can simply GET it. The ids are what scripted withdraw needed (P3, voted 28-Aug), and they plug into POST /atomicdb/api/queue-bump/<id>/ and POST /atomicdb/api/queue-cancel/<id>/ with the same credentials (form or JSON; undo=1 on cancel restores the row). The profile-page buttons are separate, session-guarded routes.
Query: GET /atomicdb/api/query?fen=... returns the position row (status, closure, score, point, backed_plies, best_move, the trust fields and the move list) plus an analysis block, which is null where no engine has looked yet. Inside that block, lines is the current pass, previous is the earlier pass, kept whenever it was wider than the one that replaced it, and passes is a compact summary per pass, newest first, which is what shows how the evaluation moved as the search went deeper. A position the tree does not have returns 404 here.
A request nobody has started yet is still yours to take back. Withdraw sits on the position and on every waiting row of your contributor page, and Clear my queue, at the foot of that list, empties everything you have waiting at once. Both are signed in controls rather than credential calls: they post to /atomicdb/queue/cancel/<task>/ and /atomicdb/queue/clear/ from a session. A request a worker has already started cannot be withdrawn, because the search is already running, and withdrawing a request somebody else also asked for only takes your name off: the request stays in the queue under them.
Reading a page
Every value carries where it came from.
- backed: the negamax of what the subtree already knows, with the depth of the chain in the chip. Where the chip is a link, it jumps to the position the value comes from.
- walked: the same shape of value, carried up a line a visitor walked. No engine search supports it yet, and verification is queued automatically.
- repetition: on a move row, the value of that move comes back to the position you are looking at, so the line repeats and the move is worth no more than 0 whatever its own page claims. In the header, the chain that leads here returns to a position it has already been through. On a disabled row, the move would re-enter the line you are playing.
- A plain number with no chip is the position's own analysis: an engine searched this position itself, and that is what it reported.
The line under the header says what the table below is made of: how many moves an engine searched itself, how many were seeded from an engine line running through this position, and how many are queued.
Moves sort by best known value in the mover's perspective and by nothing else, so a value from a 10B node search sits beside one from a 128M node search and neither is hidden behind the other. That is why a deeply analysed value can disagree with a shallow sibling row: the two numbers were bought with very different amounts of search, and the shallow one is the one likely to move. The gap is not papered over, it is queued.