tms9900-gcc, 32K expansion. The chess is EA5-shaped; a paged378 cart
copies it into RAM so MAME (and js99er) can boot it. Spectrum 32-column
board, C64 colours. make ti99 / make ti99 test.
make/common.mk assigned VICE_HOME and the other emulator homes with :=,
and a makefile assignment beats the environment - so exporting VICE_HOME
was silently blanked and "make plus4 test" ran a bare xplus4 that is not
on PATH. They are ?= now. The value is a prefix, so it needs its
trailing slash.
A port name only selects a port, so give it an empty recipe rather than
let make print "Nothing to be done for `plus4'" in front of a test run
that is about to work perfectly well.
recipes/ gets the variables that are easy to lose and fail quietly:
RETRO68 for mac68k, PATH and ZCCCFG for spectrum - zcc compiles and
links the whole program without ZCCCFG and only the .sna step fails,
which reads like a broken install - and the emulator homes for running.
Also that Basilisk holding cc65-Chess.dsk open fails the mac68k build
at hformat with a lock error that looks like a broken toolchain.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Mac 68k: the two kings were placed with unrelated absolute offsets and
the black one floated 23 pixels high. Both text lines now centre on the
kings' own centre, measuring out gszAbout's trailing spaces - it doubles
as the Oric's menu scroller, and counting them pushed the visible text
half a pad left. Text is "Macintosh 68k version, 2026.", since the
client is dated and not the engine, and "press a key." is gone because
a mouse click works too.
Plus/4: the splash claimed to be the Commodore 64 version, copied from
platC64.c when the port was added in 4e20bcf, October 2023. The
shorter string needed centring, and plat_colorStringXY's own x had to
move with it or the colour would sit two columns off the text.
c64, c64.chr, plus4: the default: debug block is commented out but its
break was not, so it sat unreachable and warned on every build.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
board_ApplyMove's log-globals write (added with the ZX Spectrum) and
gGotoTile with its test in human_ProcessInput (added with the Mac 68k)
were unconditional code in src/ for features nine other ports do not
have. 137 bytes on every cc65 target - which cost the Atari a whole
DLIST page, on a machine neither of those compilers can even target.
The Spectrum asks the undo ring itself now. gGotoTile stays, because a
mouse has to move a cursor that is a file static in human.c and no port
can reach it, but behind PLAT_CURSOR_JUMP, defined only in mac68k.mk.
Every 6502 target recovers 141 bytes (cx16 137 - its 65C02 codegen is
cheaper on the same source), so all of them end up slightly better than
before those two ports landed. Atari DLIST is back at $7F00 with 42
bytes of padding. AGENTS.md carries the re-measured numbers, the rule
that a port may not add unconditional bytes to src/, and the log
contract that made pre-filling the globals look like a fix.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
plat_AddToLogWin keeps its own scrollback and read gTile at append time,
which is why board_ApplyMove was made to fill the log globals for every
port. undo_FindUndoLine(0) is the move just pushed at every point this
is reached - after a redo too, which ApplyMove never sees - so the port
asks for it itself. The duplicate-line check went with it: it existed
to swallow the wrong line a redo used to produce off stale globals.
The splash was missing the second king entirely, and gszAbout is 36
visible characters on a 32-column display - putch clips at x>31 rather
than wrapping, so the year fell off the right edge and it read
"...S. Wessels,". Two centred rows now, kings five rows either side.
Net 76 bytes smaller.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The opening is no longer "1 MHz 8-bit machines." Origin, then the faster
6502s, then the ports cc65 does not cover. Seed table and platform count
match.
A port is no longer a cl65 -t name. GNU Make dispatches from make/ports
and make/toolchains, so Spectrum (z88dk) and the host term build sit next
to the cc65 targets. Products land in build/<port>/; make help / make list
show the verbs and which compilers this machine has. make apple2 po is one
invocation.
platSpectrum.c is a full plat.h: board, menus, B/A/D, and Think. Squares
are 3x2 characters on a 32-column display. SEARCH_ARENA is overridable so
a tighter machine can shrink the move list, and the log globals are written
when a move is applied so a smashed undo ring still shows the last ply.
Atari highlight XORs instead of filling, so A/D no longer erase the
piece; rank-1 B numbers stay inside the 192-row lookup; arrows work
without Opt/Cmd; black log lines invert like the Oric. Plus/4 copies
the charset with ROM paged in so text appears at all, and inverts
black's log the same way. c64.chr walks the undo stack for the log.
C64, Plus/4 and CX16 treat both STOP and ESC as backup. Search polls
M / RUN-STOP every 64 nodes so AI-vs-AI can be interrupted mid-think.
CX16 no longer wipes the log on every DrawBoard (undo was flashing
clear-then-redraw) and the menu ticker uses RDTIM — $A03B is the r39
clock and is frozen on R49. GetSeed uses the same call.
Free space remasured from a clean optsize link of all seven targets.
Atari still 874 below the framebuffer, 38 bytes of DLIST pad left.
Apple II 656 / 2024. optspeed still overflows both tight machines.
The ladder table gives level 1 a rating; it never said who that rating is
for. State the target explicitly - beat a rank amateur, lose to a seasoned
beginner - and tie it to the mechanism, since the line falls exactly where
the second ply would be: at 400 nodes level 1 plays a one-ply move, so
quiescence keeps it from dropping pieces to a capture and it still mates in
one 55 of 60, while anything needing a quiet move to arrange, including a
mate in one against itself, is invisible. Found by losing a game to a
human at this level and asking why.
Also records the one place the label overpromises, which is time rather
than strength: 400 nodes is the fastest setting and still 11 seconds a move
on a stock C64, and the budget cannot be cut because 300 draws won endings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Product docs no longer narrate the journey. Search and evaluation
candidates that were measured and stopped live at the end of the
rework log. Emulator how-tos move from scratch/ to recipes/.
Window 50 around the previous iteration, full window on either failure.
Same-depth completed iterations match baseline move and score. Level 1
spends 22% more nodes; level 4 saves 10% and changes thirteen moves.
That is the PVS shape again, below the floor. Default off.
Probe may only promote a stored move found in the generated list.
32-, 64- and 128-entry tables all produce real cutoff-first hits and
no measurable node saving. No target code. RAM size is still open;
the instrument says do not spend it.
A 6x64 saturating table, cleared every search. Switch-off is exact. The
switch on saves 3.55% of L3 nodes and 2.49% at L4, and changes ten L4
moves. Ordering is already near-minimal. Default off.
Rank every previously searched root move, not only the winner. Switch-off
is exact. The switch on spends nodes at levels 1-3, saves 0.24% at level
4, and changes nine L4 moves. Compiling it on takes an Atari display-list
page. Default off.
Carry the last completed PV and try it first while the new search stays
on that line. Switch-off is exact. The switch on saves 1.36% of L4
nodes, spends 0.41% more at L3, and changes two L4 moves. Compiling it
on overflows Atari and Apple II. Default off.
Relinked all seven targets. Apple II has 852 bytes in MAIN and 2,025 in
BSS. Atari still has 1,387 below the framebuffer. The other rows had
drifted and are brought current.
The 1,024-byte persistent ring now lives at $AF00-$B2FF, in the hole
between the GR.8 screen and the 2K stack. Other targets are unchanged.
Framebuffer headroom is 1,387 bytes. Verified under Altirra and on the ATR.
Doses 0 / −16 / −48 were declared first. The eval-time scan of the ten
home squares links on Atari and takes a display-list page; incremental
make/unmake does not link. Dose 16 is +1.95σ against a same-day
control that matches the published ladder. Dose 48 is worse. Defaults
off.
One fit of the shipping constant family on positions the engine actually
reaches. book.epd even/odd openings are train and locked val, pawn stays
100, tables keep their shape. The freeze is bishop 325; val mse is noise.
A null is done, so no gauntlet and no shipping change.
22-13-29 (57.0%) at 18,000 nodes, 33 openings, no fifty-move draws.
Previous 15,000-node pairing was 22-27-15 (46.1%) with a weak Black
side; Black is now 11-4-17. Confirmation, not a regression.
Record the 400/1,200/18,000/65,000 split, the 11.0s/39.7s C64 means, and
the L3/L4 Stockfish rows. Harder is a real granted-node gain; Very Hard
is noise. Sargon L4 confirmation still running.
Keep Very Easy and Easy at 400 and 1,200 so those menu levels get the
measured 17.2% back as wall time. Raise Harder 15,000 to 18,000 and
Very Hard 60,000 to 65,000, still inside 16 bits and off the 65,535
edge. Depth caps stay 3/4/5/6.
c64phased.c times old and new Harder/Very Hard budgets on fixed
opening, middlegame and endgame positions.
Add mine_failures.py for first durable SF swings on our losses. Sample L3
gauntlet: queen moves lead. E2/E3 left open with that direction; E1/E4/E5
already rejected on measured gates.
One-ply extension when in check changes move order under fixed budgets,
drops mate-in-one at level 1 below the floor (11/12→10/12), and costs an
Atari display-list page. SEARCH_CHECK_EXT defaults off and compiles out.
Colour-aware corner drive converts at level 4's budget on the host but the
working C is hundreds of CODE bytes over Atari. Slim forms still overflow and
levels 1–3 stay at zero. Default EVAL_KBN_ON off; suite forces it for gates.
Board-scan form fitted Atari (82 free when on) but host nodes are ~1.38x
dearer; equal-time self-play is 182-244-86 over 512. Equal nodes only
228-208-76. Default EVAL_PAWNSTRUCT_ON off and drop the bit from EVAL_ALL.
Native suite still forces the switch on so purpose tests stay live.
Incremental make/unmake file counts cost ~750 CODE bytes and pushed the
Atari past the framebuffer. A pawn-only board scan at eval time fits:
6502 ports use pawnstruct.s (~248 CODE, 23 BSS), host keeps the C
reference. Doses are powers of two (-8 doubled, -16 isolated).
Atari DLIST at $7E00, 82 bytes below the framebuffer; all seven optsize
targets link; native suite green.
Rebuild the Phase 4 pawn-structure signal as file counts updated on
make/unmake, with the aggregate score added in eval_Position rather than
folded into geEvalScore. Dual switch: EVAL_PAWNSTRUCT in geEvalTerms and
EVAL_PAWNSTRUCT_ON for on-target node pricing. Passed pawns stay separate.
Purpose tests cover doubled, isolated, promotion, capture and live switch;
the fuzzer checks file counts and the structure total after move/undo/redo.
Zero page is fully used ($1A) on every measured target; only Atari has spare
beyond the runtime block, so no common ZP placement is available. Piece lists
remain low priority given the Phase 20 profile and C3's blocked capture path.
Phase C ends with C1–C3 rejected on measurement and C4–C5 deferred. Shipping
is still the Phase B engine.