Files
gogobee/internal/plugin/wordle_wordnik.go
prosolis 0a1359de46 Add masterwork rework, arena combat log, Death's Reprieve fix, and wordle improvements
Adventure — Masterwork Rework:
- Expand from 3 generic items to 15 tiered masterwork items across
  mining (weapon), fishing (armor), and foraging (boots) with per-tier
  drop rates (5%/4%/3%/2%/1.5%) and location gating
- Skill-specific cross-skill bonuses replace flat masterwork check
- Auto-equip if better, silent discard for duplicates, inventory for rest
- Add !adventure equip command for manual masterwork equipping
- Tiered room announcements: T1-2 DM only, T3 quiet, T4-5 full
- First-drop detection with special message
- Character sheet shows /⚔️ markers for masterwork/arena gear
- Sell protection for special gear in shop

Adventure — Arena Combat Log:
- Turn-based Dragon Quest style narrative for arena fights
- Outcome-first design: roll determines win/loss, log assembled backward
- No-repeat flavor text via actionPicker with per-pool tracking
- 60 participation XP on arena loss

Adventure — Death's Reprieve Fix:
- All equipment set to 1 condition instead of death-level degradation

Wordle:
- Refactored word sourcing and expanded fallback word list
- Simplified Wordnik integration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 16:24:59 -07:00

95 lines
2.1 KiB
Go

package plugin
import (
"fmt"
"log/slog"
"strings"
"gogobee/internal/dreamclient"
)
// dictValidateWord checks if a word exists in DreamDict.
// Returns (valid, apiErr). apiErr is true when the service is unreachable.
func dictValidateWord(dict *dreamclient.Client, word, lang string) (valid bool, apiErr bool) {
if dict == nil {
return true, false // no client configured = skip validation
}
v, err := dict.IsValidWord(strings.ToLower(word), lang)
if err != nil {
slog.Warn("wordle: dictionary validation error", "word", word, "lang", lang, "err", err)
return false, true
}
return v, false
}
// dictFetchDefinitionText fetches a clean definition string for display.
// Tries the given language first, falls back to English.
func dictFetchDefinitionText(dict *dreamclient.Client, word, lang string) string {
if dict == nil {
return ""
}
defs, err := dict.Define(strings.ToLower(word), lang)
if err != nil {
slog.Warn("wordle: definition fetch error", "word", word, "lang", lang, "err", err)
return ""
}
// If no definitions in the puzzle language, try English.
if len(defs) == 0 && lang != "en" {
defs, err = dict.Define(strings.ToLower(word), "en")
if err != nil || len(defs) == 0 {
return ""
}
}
if len(defs) == 0 {
return ""
}
d := defs[0]
text := strings.TrimSpace(d.Gloss)
if text == "" {
return ""
}
// Strip HTML tags if any.
text = stripHTMLTags(text)
pos := d.POS
if pos != "" {
return fmt.Sprintf("%s (%s): %s", strings.ToLower(word), pos, text)
}
return fmt.Sprintf("%s: %s", strings.ToLower(word), text)
}
// categoryLang returns the DreamDict language code for a Wordle category.
func categoryLang(category WordleCategory) string {
switch category {
case WordleCategoryPT:
return "pt-PT"
case WordleCategoryFR:
return "fr"
default:
return "en"
}
}
// stripHTMLTags removes HTML tags from a string.
func stripHTMLTags(s string) string {
var b strings.Builder
inTag := false
for _, r := range s {
if r == '<' {
inTag = true
continue
}
if r == '>' {
inTag = false
continue
}
if !inTag {
b.WriteRune(r)
}
}
return b.String()
}