The saloon deals a second hand: two names the port answered wrong - #287
Merged
Conversation
Dust's card games are written against two primitives the engine had under
names it did not answer to, and both games break on both.
`indextoprop` walks the one prop table and `result()` names the FILE the prop
came from. Blackjack and poker both clear the table between rounds with the
pair:
for count = 1 to countprops ()
temp = indextoprop (count)
if result () = "salgames.prp"
propvisible (temp, false)
Every card, both score readouts and the WINNER banner, hidden in one pass and
by file so the saloon hides its own props and not the interface band's. Only
`hittest` wrote `result()`, so the comparison was never true and a second hand
was dealt on top of the first one's cards and its result.
The name it answers is now the one the prop is REGISTERED under, not its
sprite group's. Those come apart for a `propinstance` copy, which shares the
group it draws with, and the dealer's score readout is one — salgames.prp
ships a single `bjscores` group and `initgame` instances `bjscores2` off it.
Reporting the group hid the player's readout twice and never named the
dealer's, so the opponent's last total stayed on the table. Poker's per-seat
hand names are 27 more of the same shape (`nopair2`/`nopair3`/`nopair4` off one
`nopair`), which is why its banner was stale too.
`variable (name)` resolves a computed name the way a name written out in full
does: the running block's locals first, then the globals. Poker's `hasxkind`
counts faces into thirteen locals and reads them back with it —
local card2, card3, … card14
…
for count = 2 to 14
if variable ("card" @ numtostring (count)) = num
— and a globals-only lookup answered 0 for all thirteen, so the classifier
never found a pair. Every hand at the showdown scored as its high card: four
aces came out a "straight", most hands read "nopair" over a table of visible
pairs and flushes. The winner still looked right, because all four hands were
mis-scored the same way and the comparison is between them. The SETTER still
creates a global for a name the block did not declare local, so Dust's crowd
storing a walk phase under its own instance name (`variable (me, 1)`) reaches
the table the next `switch variable (me)` reads.
Titanic is untouched, and checked rather than assumed. No TAOOT script calls
`indextoprop` between a `hittest` and its `result()`; its callers feed the name
straight back into name-resolving commands, which resolve by the same key the
walk now returns. blkjack.stg is the only Titanic file using `variable`, always
as `who @ "…"` against playercount/dealertotal/… while its blocks declare
thecard/x/y/cardwidth/cardcount — no name in either set collides.
dust/tests/salgames.ts runs the game's own scripts: the clear-the-table loop
over two open shops with the dealer's instance standing, a round-trip
invariant that every index's name resolves back to that prop, `calcscore` over
ten hands, and `makehands` over 40 seeds for four whole hands out of one deck.
The `adjust4ace` test added to taoot/tests/auto/interp.ts is the guard on the
Titanic side: its loops write by computed name and its soft-17 rule reads
`dealertotal` written out, so it fails if either half moves.
Dust 0.3.7.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Dust's card games are written against two primitives the engine had under names it did not answer to, and both games break on both. Reported from play: a second round of blackjack still had round one's cards and result on the table, and poker's showdown showed a hand name that did not match the cards under it.
indextoprop/result()Blackjack and poker both clear the table between rounds with the pair:
Every card, both score readouts and the WINNER banner, hidden in one pass and by file — so the saloon hides its own props and not the interface band's. Only
hittestwroteresult(), so the comparison was never true and nothing was hidden.The name it answers is now the one the prop is registered under, not its sprite group's. Those come apart for a
propinstancecopy, which shares the group it draws with, and the dealer's score readout is one:salgames.prpships a singlebjscoresgroup andinitgameinstancesbjscores2off it. Reporting the group hid the player's readout twice and never named the dealer's, so the opponent's last total stayed on the table. Poker's per-seat hand names are 27 more of the same shape (nopair2/nopair3/nopair4off onenopair), which is why its banner was stale too.variable (name)It now resolves a computed name the way a name written out in full does — the running block's locals first, then the globals. Poker's
hasxkindcounts faces into thirteen locals and reads them back with it:A globals-only lookup answered 0 for all thirteen, so the classifier never found a pair. Every hand at the showdown scored as its high card: four aces came out a
"straight", most hands read"nopair"over a table of visible pairs and flushes. The winner still looked right, because all four hands were mis-scored the same way and the comparison is between them.The setter still creates a global for a name the block did not declare local, so Dust's crowd storing a walk phase under its own instance name (
variable (me, 1), extra.cst) reaches the table the nextswitch variable (me)reads.Titanic is untouched
Checked rather than assumed:
indextopropbetween ahittestand itsresult(). Its callers feed the name straight back into name-resolving commands (sendtoprop,propowner,propscript), which resolve by the same key the walk now returns.blkjack.stgis the only Titanic file usingvariable, always aswho @ "…"againstplayercount/dealertotal/…, while its blocks declarethecard/x/y/cardwidth/cardcount. No name in either set collides.Tests
dust/tests/salgames.tsruns the game's own scripts out ofSALGAMES.FLT:calcscoreover ten hands, one per category;makehandsover 40 seeds — four whole hands, all real cards, no card in two hands.All three fail on
master. Theadjust4acetest added totaoot/tests/auto/interp.tsis the guard on the Titanic side: its loops write by computed name and its soft-17 rule readsdealertotalwritten out, so it fails if either half of thevariablecontract moves. Confirmed by breaking each fix in turn.538 tests pass,
tscclean,npm run build:dustclean.Releases as Dust 0.3.7 (
dust-v0.3.7on the merged commit).🤖 Generated with Claude Code