hardware/board_setup_planner.h

Physical setup ordering for match review (review-docs PLAN §6.3).

The one genuinely new algorithm in physical review. Given where the 32 pieces are now (by identity) and where they must end up, it emits an ORDER of physical operations that never places a piece on a still-occupied square. It solves ordering only — path collisions are left to the existing planMove()/executeMove() pipeline, which already handles blocker parking and A* routing.

The target of a setup is a piece-*identity* snapshot, never a FEN: a FEN can describe positions the board cannot physically hold (two queens — §2.2), whereas every identity snapshot is a state the board actually reached, so it is realizable by construction.

Pure and hardware-free: no gantry, no serial, fully unit-testable.

Enums

enum class SetupOp

Values:

enumerator Move
enumerator Store
enumerator Retrieve

Functions

SetupPlan planSetup(const BoardIdentity &current, const BoardIdentity &target)

Order the moves that turn current into target without ever placing a piece on an occupied square (review-docs §6.3):

  1. evacuate — pieces whose target is storage go to their slot first (frees squares);

  2. relocate — repeatedly execute any pending move whose destination is empty;

  3. break cycles — when nothing is executable, a dependency cycle exists; park one of its pieces to its storage slot (always available) and continue. Each break strictly reduces board-resident pending pieces, so it terminates;

  4. populate — pieces coming from storage land once their destination is free.

Returns a plan with ok=false if current double-books a square.

int setupCost(const SetupPlan &plan)
bool assignIdentitiesByType(const int currentTypeAt[64], const BoardIdentity &target, BoardIdentity &assignedCurrent)

Type-only identity assignment for a board whose identities are unknown (SLOT_UNKNOWN after a hand-set board or a desync, §6.3). Assign each physical piece to a target identity of the same (color, type), minimizing total gantry travel — a min-cost assignment per (color, type) class, each ≤ 8 pieces, so it is exact and cheap. The result is a concrete BoardIdentity that planSetup can realize.

Parameters:
  • currentTypeAt – per square (a8=0 … h1=63): engine piece 0..11, or -1 if empty

  • target – the desired identity snapshot (its on-board counts per class must match the physical board — otherwise the assignment is ambiguous and this returns false)

  • assignedCurrent – filled with the inferred current identity on success

Returns:

true if a consistent assignment exists

int slotToPieceType(int slot)

Variables

constexpr int OFF_BOARD = -1
constexpr int kBoardOpCost = 1
constexpr int kStorageOpCost = 2
struct BoardIdentity
#include <board_setup_planner.h>

Where each of the 32 slot-identities sits: for side (0=white, 1=black) and StartingSlot (0..15), the board square it occupies, or OFF_BOARD if it is in storage. This is exactly the reverse map a PieceTracker maintains.

Public Functions

inline BoardIdentity()

Public Members

int square[2][16]

Public Static Functions

static inline BoardIdentity fromTracker(const PieceTracker &t)
struct SetupStep
#include <board_setup_planner.h>

Public Members

SetupOp op
int side
int slot
int from
int to
struct SetupPlan
#include <board_setup_planner.h>

Public Members

bool ok = false
std::vector<SetupStep> steps