package lang 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 } // KanaUnlockWords: när så här många kända ord innehåller kana "lossnar" // kana-läsningen och alla kana-ord går att läsa (som romaji) utan att förstås. const KanaUnlockWords = 3 // WordsPerLevel styr japanska-nivån: nivå = kända ord / WordsPerLevel, max MaxLevel. const ( WordsPerLevel = 4 MaxLevel = 5 ) // NewKnowledge börjar från noll. func NewKnowledge() *Knowledge { return &Knowledge{Words: map[string]bool{}} } // Knows rapporterar om ordet är känt. func (k *Knowledge) Knows(word string) bool { return k.Words[word] } // Learn lär in ett ord. Returnerar true om det var nytt. Låser upp kana när // tillräckligt många kana-ord är kända. func (k *Knowledge) Learn(word string) bool { if k.Words == nil { k.Words = map[string]bool{} } if k.Words[word] { return false } k.Words[word] = true if !k.Kana { n := 0 for w := range k.Words { if HasKana(w) { n++ } } if n >= KanaUnlockWords { k.Kana = true } } return true } // Count är antalet kända ord. func (k *Knowledge) Count() int { return len(k.Words) } // Level är japanska-nivån 0..MaxLevel. func (k *Knowledge) Level() int { return int(math.Min(MaxLevel, float64(k.Count()/WordsPerLevel))) } // Hintar som växer med nivån. // ShowsDestinationJP: från nivå 1 visar HUD:en resmålet även på japanska så // att man kan matcha tecknen mot skyltarna. func (k *Knowledge) ShowsDestinationJP() bool { return k.Level() >= 1 } // ShowsReadings: från nivå 2 visas läsningen (romaji) för kända ord på skyltar. func (k *Knowledge) ShowsReadings() bool { return k.Level() >= 2 } // HelpSeconds är hur länge det tar att få hjälp av en förbipasserande. // Bättre japanska = snabbare, men aldrig under HelpMinSeconds. const ( HelpBaseSeconds = 6.0 HelpPerLevel = 0.8 HelpMinSeconds = 2.0 ) // HelpSeconds beräknar väntetiden för en given nivå. func HelpSeconds(level int) float64 { return math.Max(HelpMinSeconds, HelpBaseSeconds-HelpPerLevel*float64(level)) } // EnglishShare är andelen skyltar som också visar engelska, per svårighet. func EnglishShare(difficulty int) float64 { switch { case difficulty <= 1: return 1.0 case difficulty == 2: return 0.6 case difficulty == 3: return 0.3 case difficulty == 4: return 0.1 default: return 0 } } // ShowEnglish avgör deterministiskt om skylten på (x, y) i en bana visar // engelska: banor är statiska så valet hashas från bana + position, inte // från spelomgångens seed. func ShowEnglish(levelID string, x, y, difficulty int) bool { share := EnglishShare(difficulty) if share >= 1 { return true } if share <= 0 { return false } h := uint32(2166136261) for _, b := range []byte(levelID) { h = (h ^ uint32(b)) * 16777619 } for _, v := range []int{x, y} { h = (h ^ uint32(v+7)) * 16777619 } return float64(h%1000)/1000 < share }