M9: navigeringslägen, linjenät och terminal
All checks were successful
release / build-release (push) Successful in 1m34s

internal/nav med resources/data/network.json (76 stationer, 11 linjer,
Yamanote som ringlinje). Tåg bedöms från lineId + terminus mot banans
station/to: rätt, fel håll, för långt bort (fler än 12 stationer) eller
ingen trafik; correct räknas ut för nätkopplade banor, 1-4 rätta tåg.
Tågresan visar linjens riktiga stationer. Nya förlustorsaker "Fel håll"
och "För långt bort". Listläge (nästa tåg nere till vänster) och
skyltläge (+50 % poäng) växlas med N på bankartan och sparas; -mode.
Terminalen: biljettautomaten visar linjetavlan på nätbanor. Perronger
P p Q q R r. Bana 006 Ikebukuro med fyra perronger. Banorna 001-005
kopplade till nätet. Skript: waitover och pick calm; poängraden
radbryts; skärmdumpar uppdaterade.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-24 13:07:36 +02:00
parent de61568e44
commit f762f9554e
53 changed files with 3041 additions and 122 deletions

View File

@@ -12,6 +12,7 @@ import (
"gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/lang"
"gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/level"
"gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/nav"
"gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/progress"
"gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/res"
"gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/rng"
@@ -45,6 +46,7 @@ type Game struct {
Catalog *progress.Catalog
Levels []*level.Level // alla banor, sorterade på id
Audio *Audio // nil = tyst
Mode nav.Mode // navigeringsläge (= State.NavMode), växlas på bankartan
savePath string // "" = spara inte
fixedSeed uint64 // >0: alla banor startar med denna seed (tester/skärmdumpar)
@@ -69,6 +71,7 @@ type Options struct {
Mute bool // inget ljud
SavePath string // sparfil ("" = standardplatsen)
NoSave bool // läs sparfilen men skriv aldrig
Mode string // navigeringsläge från start: "list" eller "signs" (tomt = sparfilens)
}
// New laddar resurser, sparfil och bygger spelet.
@@ -109,6 +112,10 @@ func New(opt Options) (*Game, error) {
}
g.State = st
g.Know, g.Wallet, g.Profile, g.Progress = st.Know, st.Wallet, st.Profile, st.Progress
g.Mode = nav.ParseMode(st.NavMode)
if opt.Mode != "" {
g.Mode = nav.ParseMode(opt.Mode)
}
if !opt.NoSave {
g.savePath = path
}
@@ -233,10 +240,21 @@ func (g *Game) runOptions(id string, seed rng.Seed) sim.RunOptions {
return sim.RunOptions{
Dict: g.Assets.Dict, Know: g.Know, Wallet: g.Wallet, Debuffs: g.Profile.Debuffs, Seed: seed,
Extra: eff.Stats, FogRadius: eff.FogRadius, Landmarks: eff.Landmarks, FreeGates: eff.FreeGates,
RevealAll: eff.Reveal[id], InfiniteBattery: eff.Battery,
RevealAll: eff.Reveal[id], InfiniteBattery: eff.Battery, Mode: g.Mode,
}
}
// toggleMode växlar navigeringsläge och sparar.
func (g *Game) toggleMode() {
if g.Mode == nav.List {
g.Mode = nav.Signs
} else {
g.Mode = nav.List
}
g.State.NavMode = g.Mode.String()
g.Save()
}
// startLevel startar (eller återupptar) en bana och sparar seeden så att en
// laddad omgång ger samma slump.
func (g *Game) startLevel(id string) (*LevelScene, error) {