M11: oändligt läge och New Game+
All checks were successful
release / build-release (push) Successful in 1m34s

internal/endless lottar mål ur en seed: en av storyns nätkopplade
stationer (aldrig samma två gånger i rad) med ett resmål som minst ett
tåg går rakt till men inte alla; banan kopieras, bedöms om mot nätet,
sällskapet växer var tredje mål och tidsgränsen krymper. O på bankartan
(eller -endless) startar en omgång; klarade mål ger poäng och XP, Enter
ger nästa mål, förlust eller Esc avslutar och omgången hamnar i
sparfilens poänglista (fem bästa). G två gånger startar New Game+: items,
banresultat, pengar och debuffar nollställs, skills, XP och japanskan
behålls, sällskapet är en person större per varv. Docs, wiki, tester och
skärmdumpar uppdaterade.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-24 23:20:12 +02:00
parent 46bd330dfc
commit 36a45563ec
22 changed files with 556 additions and 19 deletions

View File

@@ -9,6 +9,7 @@ import (
"fmt"
"os"
"path/filepath"
"sort"
"time"
"gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/lang"
@@ -40,6 +41,38 @@ type State struct {
Progress *progress.Progress `json:"progress"`
Current *RunRef `json:"current,omitempty"`
NavMode string `json:"navMode,omitempty"` // "list" (standard) eller "signs"
Endless []EndlessRecord `json:"endless,omitempty"` // oändligt läge: bästa omgångarna, högst poäng först
}
// EndlessRecord är en avslutad omgång i oändligt läge.
type EndlessRecord struct {
Score int `json:"score"`
Goals int `json:"goals"` // antal klarade mål
Seed [2]uint64 `json:"seed"`
When time.Time `json:"when"`
}
// MaxEndlessRecords är hur många omgångar som sparas i listan.
const MaxEndlessRecords = 5
// AddEndless lägger in en omgång i listan (sorterad på poäng, högst först)
// och rapporterar om den är ny bästa.
func (s *State) AddEndless(r EndlessRecord) (best bool) {
best = len(s.Endless) == 0 || r.Score > s.Endless[0].Score
s.Endless = append(s.Endless, r)
sort.SliceStable(s.Endless, func(i, j int) bool { return s.Endless[i].Score > s.Endless[j].Score })
if len(s.Endless) > MaxEndlessRecords {
s.Endless = s.Endless[:MaxEndlessRecords]
}
return best
}
// BestEndless är bästa omgången (nil om ingen).
func (s *State) BestEndless() *EndlessRecord {
if len(s.Endless) == 0 {
return nil
}
return &s.Endless[0]
}
// New är ett nytt spel.