Inlärning (framsteg, stjärnor, ordlista) och M4: lämmeltåget
All checks were successful
release / build-release (push) Successful in 1m49s
All checks were successful
release / build-release (push) Successful in 1m49s
Inlärning enligt Björns regler: - lang.Knowledge: framsteg per ord (3 läsningar = känt), språkpoäng, köp av valfria ord (kostnad = tier), Award per stjärna - sim.Run: RunOptions med seed; stjärnor 1–3 mot par (parSec eller kortaste vägen × 0,5 s + 20 s); ≥2 stjärnor lär resmålets ord; att stanna på skylt/perrong ger seedad 35 % chans till framsteg per okänt ord - game: ordlista (L) med kända ord, framsteg och kostnad; stjärnor, poäng och inlärt resmål på resultatskärmen; framstegsnotis; flaggor -points/-seed M4 lämmeltåget: - sim.Party: medlemmar med mat/dryck/toa-mätare, behov under tröskel, seedade händelser var 45 s / antal (toa, törst, hunger, distraktion), fartstraff, toalett (W, 3 s/person) och kiosk (K, 150 ¥/person), följare på ledarens spår - level: rutor W och K, party och parSec i bandatan; banor med sällskap måste ha toalett och kiosk (testas); 001 har 2, 002 har 3 i sällskapet - game: följare med färgton, behovsmarkering över huvudet, mätarpanel, facilitetsrutor med förlopp; genart ritar toalett och kiosk - skriptläget: move stannar exakt på målrutan även när farten inte är bildruteexakt (sällskapets fartstraff), stall-skydd mot väggar - docs/README/wiki/spelbeskrivning uppdaterade Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -4,9 +4,11 @@ import "math"
|
||||
|
||||
// Knowledge är vad spelaren kan: ord ur ordboken och om hen kan läsa kana.
|
||||
type Knowledge struct {
|
||||
Words map[string]bool `json:"words"`
|
||||
Kana bool `json:"kana"`
|
||||
Helps int `json:"helps"` // antal gånger spelaren frågat om hjälp
|
||||
Words map[string]bool `json:"words"`
|
||||
Progress map[string]int `json:"progress"` // framsteg på ord som ännu inte är kända
|
||||
Points int `json:"points"` // språkpoäng att lägga på valfria ord
|
||||
Kana bool `json:"kana"`
|
||||
Helps int `json:"helps"` // antal gånger spelaren frågat om hjälp
|
||||
}
|
||||
|
||||
// KanaUnlockWords: när så här många kända ord innehåller kana "lossnar"
|
||||
@@ -20,7 +22,9 @@ const (
|
||||
)
|
||||
|
||||
// NewKnowledge börjar från noll.
|
||||
func NewKnowledge() *Knowledge { return &Knowledge{Words: map[string]bool{}} }
|
||||
func NewKnowledge() *Knowledge {
|
||||
return &Knowledge{Words: map[string]bool{}, Progress: map[string]int{}}
|
||||
}
|
||||
|
||||
// Knows rapporterar om ordet är känt.
|
||||
func (k *Knowledge) Knows(word string) bool { return k.Words[word] }
|
||||
@@ -115,3 +119,69 @@ func ShowEnglish(levelID string, x, y, difficulty int) bool {
|
||||
}
|
||||
return float64(h%1000)/1000 < share
|
||||
}
|
||||
|
||||
// Inlärning utöver hjälp (Björns regler 2026-10-23):
|
||||
// - bra resultat på en bana lär ut resmålets ord (StarsToLearnDestination),
|
||||
// - varje läst okänt ord har chansen ReadChance att ge +1 framsteg; vid
|
||||
// ProgressToLearn framsteg kan man ordet,
|
||||
// - språkpoäng (Points) tjänas på banor och läggs på valfria ord i ordlistan.
|
||||
const (
|
||||
ReadChance = 0.35
|
||||
ProgressToLearn = 3
|
||||
StarsToLearnDestination = 2
|
||||
PointsPerStar = 1
|
||||
)
|
||||
|
||||
// ProgressOf är hur många framsteg ordet har (0 om känt eller aldrig läst).
|
||||
func (k *Knowledge) ProgressOf(word string) int {
|
||||
if k.Progress == nil {
|
||||
return 0
|
||||
}
|
||||
return k.Progress[word]
|
||||
}
|
||||
|
||||
// AddProgress ger ett framsteg på ett okänt ord. Returnerar true om ordet
|
||||
// därmed blev känt.
|
||||
func (k *Knowledge) AddProgress(word string) bool {
|
||||
if k.Knows(word) {
|
||||
return false
|
||||
}
|
||||
if k.Progress == nil {
|
||||
k.Progress = map[string]int{}
|
||||
}
|
||||
k.Progress[word]++
|
||||
if k.Progress[word] >= ProgressToLearn {
|
||||
delete(k.Progress, word)
|
||||
k.Learn(word)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// WordCost är vad ett ord kostar i språkpoäng: dess tier (minst 1).
|
||||
func WordCost(e *Entry) int { return max(1, e.Tier) }
|
||||
|
||||
// CanBuy rapporterar om ordet går att köpa för poängen.
|
||||
func (k *Knowledge) CanBuy(e *Entry) bool {
|
||||
return e != nil && !k.Knows(e.Word) && k.Points >= WordCost(e)
|
||||
}
|
||||
|
||||
// Buy lär in ordet mot språkpoäng. Returnerar false om det inte går.
|
||||
func (k *Knowledge) Buy(e *Entry) bool {
|
||||
if !k.CanBuy(e) {
|
||||
return false
|
||||
}
|
||||
k.Points -= WordCost(e)
|
||||
if k.Progress != nil {
|
||||
delete(k.Progress, e.Word)
|
||||
}
|
||||
k.Learn(e.Word)
|
||||
return true
|
||||
}
|
||||
|
||||
// Award ger språkpoäng för stjärnor på en klarad bana.
|
||||
func (k *Knowledge) Award(stars int) int {
|
||||
p := max(0, stars) * PointsPerStar
|
||||
k.Points += p
|
||||
return p
|
||||
}
|
||||
|
||||
@@ -208,3 +208,43 @@ func TestCharClasses(t *testing.T) {
|
||||
t.Fatal("HasKana/IsJapanese")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProgressLearnsAfterEnoughReads(t *testing.T) {
|
||||
k := NewKnowledge()
|
||||
for i := 1; i < ProgressToLearn; i++ {
|
||||
if k.AddProgress("改札") || k.ProgressOf("改札") != i || k.Knows("改札") {
|
||||
t.Fatalf("efter %d framsteg: progress=%d known=%v", i, k.ProgressOf("改札"), k.Knows("改札"))
|
||||
}
|
||||
}
|
||||
if !k.AddProgress("改札") || !k.Knows("改札") || k.ProgressOf("改札") != 0 {
|
||||
t.Fatal("tredje framsteget ska lära ordet och nollställa framstegen")
|
||||
}
|
||||
if k.AddProgress("改札") {
|
||||
t.Fatal("kända ord får inga framsteg")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuyWordsWithPoints(t *testing.T) {
|
||||
d := testDict()
|
||||
k := NewKnowledge()
|
||||
e1, e3 := d.Lookup("改札"), d.Lookup("新宿駅") // tier 1 resp. 3
|
||||
if WordCost(e1) != 1 || WordCost(e3) != 3 {
|
||||
t.Fatal("kostnad = tier")
|
||||
}
|
||||
if k.CanBuy(e1) || k.Buy(e1) {
|
||||
t.Fatal("utan poäng ska inget gå att köpa")
|
||||
}
|
||||
if got := k.Award(3); got != 3*PointsPerStar || k.Points != got {
|
||||
t.Fatalf("Award = %d, points=%d", got, k.Points)
|
||||
}
|
||||
k.Progress["新宿駅"] = 2
|
||||
if !k.Buy(e3) || !k.Knows("新宿駅") || k.Points != 0 || k.ProgressOf("新宿駅") != 0 {
|
||||
t.Fatalf("köp misslyckades: points=%d known=%v", k.Points, k.Knows("新宿駅"))
|
||||
}
|
||||
if k.CanBuy(e3) {
|
||||
t.Fatal("redan känt ord ska inte gå att köpa")
|
||||
}
|
||||
if k.Award(-2) != 0 || k.Points != 0 {
|
||||
t.Fatal("negativa stjärnor ger inget")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user