Skip to content

Improve free jump detection: add log scan as third fallback - #89

Merged
goldjohn6 merged 6 commits into
boardgamers:masterfrom
mmunson99:master
Jun 15, 2026
Merged

goldjohn6 merged 6 commits into
boardgamers:masterfrom
mmunson99:master

Conversation

@mmunson99

Copy link
Copy Markdown
Contributor

The topology check misses cases where the free-jumped city is reachable via the normal network (e.g. Sapporo is connected to the mainland via Hakodate-Admori). Scan the game log for any Build move with freeJump:true by the player — that flag is stored in the log even on older server builds that don't track usedFreeJump in engine state.

The topology check misses cases where the free-jumped city is reachable
via the normal network (e.g. Sapporo is connected to the mainland via
Hakodate-Admori). Scan the game log for any Build move with
freeJump:true by the player — that flag is stored in the log even on
older server builds that don't track usedFreeJump in engine state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coyotte508

Copy link
Copy Markdown
Member

If it's only on older games we can ignore & just handle new games

Comment on lines -1045 to 1049
// Fallback: detect from network topology for game states where
// usedFreeJump wasn't tracked (games started before that field existed).
// 2. Network topology — works when the two networks are still disconnected.
if (player.cities.length >= 2) {
return countNetworks(this.G!.map.connections, player.cities.map(c => c.name)) >= 2;
if (countNetworks(this.G!.map.connections, player.cities.map(c => c.name)) >= 2) return true;
}
// 3. Log scan — works for explicit round 2+ free jumps on older server builds
// where usedFreeJump wasn't tracked: the freeJump:true flag is still stored
// in the move data even if the engine ignored it.
if (this.G?.log) {
for (const entry of this.G.log) {
if (entry.type === 'move' && (entry as any).player === playerIndex) {
const move = (entry as any).move;
if (move?.name === MoveName.Build && move?.data?.freeJump === true) {
return true;
}
}
}
}

@coyotte508 coyotte508 May 27, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually would just rely on player.usedFreeJump. For existing games, they can be cancelled or I can manually set it in db

( & would delete the countNetworks code)

@mmunson99

mmunson99 commented May 27, 2026 via email

Copy link
Copy Markdown
Contributor Author

mmunson99 and others added 5 commits June 12, 2026 22:42
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Engine flag and topology check are sufficient now that PR boardgamers#85 is merged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ostrophes

Prettier (singleQuote: true) flips a string to double quotes when it contains
more single quotes than double quotes, to avoid escaping. The two expanded
mapSpecificRules strings used escaped single quotes ('10', 'X'), which the
prettier-check CI job rejects. Use double-quoted form so the check passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ESLint (quotes: single) requires single quotes; Prettier flips a string to
double quotes when it contains apostrophes, to avoid escaping. The two
expanded mapSpecificRules strings used '10' and 'X', making the two checks
mutually unsatisfiable. Remove the inner quote marks so the single-quoted
strings need no escaping, satisfying both prettier-check and eslint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@goldjohn6
goldjohn6 merged commit e3fb40c into boardgamers:master Jun 15, 2026
3 checks passed
goldjohn6 added a commit that referenced this pull request Jun 16, 2026
…emen rules dialog (#95)

* Fix Japan free jump: track usage explicitly, not via network topology

Free-jump availability was gated on countNetworks(ownedCities) < 2 as a
proxy for "has the player started a second network". But Power Grid networks
connect *through* unowned cities, so a single intended network routinely
shows as multiple components — wrongly hiding the free jump even though the
player never spent it (Sapporo unreachable while the indicator still showed
the jump as available). Prior fixes (#89, #94) layered more detection
heuristics on top; this removes the proxy and relies solely on the explicit
player.usedFreeJump flag.

- available-moves: offer the jump whenever !usedFreeJump
- undo: return the jump only when the undone build was the one that spent it
  (a round-1 second starting-city build, or a freeJump:true move), fixing a
  latent bug where undoing any normal build could hand the jump back once the
  network had become fully connected
- remove the now-unused countNetworks import
- add regression tests for both availability and post-use suppression

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Bremen: clarify asymmetric district-cost example, drop confusing river note

The flat district-cost connection rules confused players, especially the
direction-dependent (asymmetric) cost. Add a short worked example to the
in-game rules dialog. Also remove the "Weser and Lesum rivers can be crossed
without extra cost" line: the online map shows no rivers, so the note caused
confusion rather than clarity (the zero-cost crossings remain in the map
data and code comments).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants