diff options
| author | historia <[not public]> | 2026-06-25 15:40:48 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-25 15:40:48 -0400 |
| commit | abd612c15799f604e671e83dc7c410ed2b44185f (patch) | |
| tree | 0597ca92350de73aac2a7cf26b2f2d6595dac0cc /internal/behavior/store.go | |
| parent | 2725e2927a1595c7b100d942d1f14146252adeb7 (diff) | |
| download | thehouseoficarus-abd612c15799f604e671e83dc7c410ed2b44185f.tar.gz | |
slop refactor
Diffstat (limited to 'internal/behavior/store.go')
| -rw-r--r-- | internal/behavior/store.go | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/internal/behavior/store.go b/internal/behavior/store.go new file mode 100644 index 0000000..7695b8d --- /dev/null +++ b/internal/behavior/store.go @@ -0,0 +1,164 @@ +package behavior + +import ( + "fmt" + "math/rand" + "os" + "path/filepath" + "strings" + "sync" + + "gopkg.in/yaml.v3" +) + +func BuildPathIndex(dir string) map[string]string { + index := make(map[string]string) + filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { + if err != nil || d.IsDir() || !strings.HasSuffix(d.Name(), ".yaml") { + return nil + } + id := strings.TrimSuffix(d.Name(), ".yaml") + index[id] = path + return nil + }) + return index +} + +func BuildRoomIndex(dir string) map[int]string { + index := make(map[int]string) + filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { + if err != nil || d.IsDir() || !strings.HasSuffix(d.Name(), ".yaml") { + return nil + } + id := strings.TrimSuffix(d.Name(), ".yaml") + var n int + if _, scanErr := fmt.Sscanf(id, "%d", &n); scanErr == nil { + index[n] = path + } + return nil + }) + return index +} + +func WalkYAMLDir(dir string, fn func(path, id string, data []byte) error) error { + return filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { + if err != nil || d.IsDir() || !strings.HasSuffix(d.Name(), ".yaml") { + return nil + } + data, readErr := os.ReadFile(path) + if readErr != nil { + return nil + } + id := strings.TrimSuffix(d.Name(), ".yaml") + return fn(path, id, data) + }) +} + +type Duplicate struct { + ID string + Paths []string +} + +func CheckDuplicateIDs(dir string) []Duplicate { + seen := make(map[string][]string) + filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { + if err != nil || d.IsDir() || !strings.HasSuffix(d.Name(), ".yaml") { + return nil + } + id := strings.TrimSuffix(d.Name(), ".yaml") + seen[id] = append(seen[id], path) + return nil + }) + var dups []Duplicate + for id, paths := range seen { + if len(paths) > 1 { + dups = append(dups, Duplicate{ID: id, Paths: paths}) + } + } + return dups +} + +func SuccessChance(cfg SuccessFormula, level int, requiredLevel int) float64 { + chance := cfg.Base + float64(level-requiredLevel)*cfg.PerLevel + if chance > cfg.Cap { + chance = cfg.Cap + } + if chance < 0 { + chance = 0 + } + return chance +} + +var ( + dropIndex map[string]string + dropIndexMu sync.Mutex +) + +func loadDropIndex(dataDir string) map[string]string { + dropIndexMu.Lock() + defer dropIndexMu.Unlock() + if dropIndex == nil { + dropIndex = BuildPathIndex(filepath.Join(dataDir, "drops")) + } + return dropIndex +} + +func LoadDropTable(dataDir, id string) (*DropTableDef, error) { + index := loadDropIndex(dataDir) + path, ok := index[id] + if !ok { + path = filepath.Join(dataDir, "drops", id+".yaml") + } + data, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("read drop table %s: %w", id, err) + } + var dt DropTableDef + if err := yaml.Unmarshal(data, &dt); err != nil { + return nil, fmt.Errorf("parse drop table %s: %w", id, err) + } + return &dt, nil +} + +func ResolveDrop(dataDir string, drops []DropEntry) *DropEntry { + if len(drops) == 0 { + return nil + } + total := 0 + for _, d := range drops { + total += d.Weight + } + if total <= 0 { + return nil + } + roll := rand.Intn(total) + cumulative := 0 + for i := range drops { + cumulative += drops[i].Weight + if roll < cumulative { + if drops[i].Table != "" { + sub, err := LoadDropTable(dataDir, drops[i].Table) + if err == nil { + if resolved := ResolveDrop(dataDir, sub.Drops); resolved != nil { + qty := drops[i].Quantity + if qty <= 0 { + qty = resolved.Quantity + } + if qty <= 0 { + qty = 1 + } + return &DropEntry{ + ItemID: resolved.ItemID, + Quantity: qty, + Depletes: drops[i].Depletes, + Message: drops[i].Message, + } + } + } + return nil + } + return &drops[i] + } + } + return &drops[0] +} |
