package tables import ( "fmt" "mazeratsgen/internal/data" "mazeratsgen/internal/dice" "strings" ) type MonsterTable struct { Roller *dice.Roller } type MonsterStat struct { Value int Qualifier string } type MonsterStats struct { Health MonsterStat Attack MonsterStat Armor MonsterStat STR MonsterStat DEX MonsterStat WIL MonsterStat } type Monster struct { Base string Stats MonsterStats Feature string Trait string Ability string Tactics string Personality string Weakness string Seed int64 } func (t *MonsterTable) Generate() Monster { baseRoll, _ := t.Roller.Roll("1d6") return Monster{ Base: t.Base(baseRoll[0]), Stats: t.genStats(), Feature: t.Feature(t.Roller.TableRoll()), Trait: t.Trait(t.Roller.TableRoll()), Ability: t.Ability(t.Roller.TableRoll()), Tactics: t.Tactic(t.Roller.TableRoll()), Personality: t.Personality(t.Roller.TableRoll()), Weakness: t.Weakness(t.Roller.TableRoll()), Seed: t.Roller.Seed, } } func (t *MonsterTable) Template() string { return strings.TrimSpace(` Type: {{.Trait}} {{.Base}} Stats: Health: {{.Stats.Health.Value}} ({{.Stats.Health.Qualifier}}) Armor: {{.Stats.Armor.Value}} ({{.Stats.Armor.Qualifier}}) Attack: +{{.Stats.Attack.Value}} ({{.Stats.Attack.Qualifier}}) STR: +{{.Stats.STR.Value}} ({{.Stats.STR.Qualifier}}) DEX: +{{.Stats.DEX.Value}} ({{.Stats.DEX.Qualifier}}) WIL: +{{.Stats.WIL.Value}} ({{.Stats.WIL.Qualifier}}) Feature: {{.Feature}} Ability: {{.Ability}} Tactics: {{.Tactics}} Personality: {{.Personality}} Weakness: {{.Weakness}} Seed: {{.Seed}} `) } func (t MonsterTable) Weakness(roll [2]int) string { magicTable := MagicTable{Roller: t.Roller} treasureTable := TreasureTable{Roller: t.Roller} switch roll { case [2]int{3, 5}: return magicTable.Insanity(t.Roller.TableRoll()) case [2]int{4, 4}: return "Pick an existing NPC" case [2]int{4, 6}: return magicTable.PhysicalElement(t.Roller.TableRoll()) case [2]int{6, 2}: return treasureTable.ValuableMaterial(t.Roller.TableRoll()) case [2]int{6, 4}: return treasureTable.WeaponItem(t.Roller.TableRoll()) default: return data.Tables.Monster.Weakness[roll[0]-1][roll[1]-1] } } func (t MonsterTable) genStats() MonsterStats { return MonsterStats{ Health: t.genHealth(), Attack: t.genAttack(), Armor: t.genArmor(), STR: t.genSTR(), DEX: t.genDEX(), WIL: t.genWIL(), } } func (t MonsterTable) genHealth() MonsterStat { typeRoll, _ := t.Roller.Roll("1d5") mStat := MonsterStat{} switch typeRoll[0] { case 1: mStat.Qualifier = "Weak" case 2: mStat.Qualifier = "Typical" case 3: mStat.Qualifier = "Tough" case 4: mStat.Qualifier = "Hulking" case 5: mStat.Qualifier = "Colossal" } hpRoll, _ := t.Roller.Roll(fmt.Sprintf("%vd6", typeRoll[0])) hp := 0 for _, hpDie := range hpRoll { hp += hpDie } mStat.Value = hp return mStat } func (t MonsterTable) genArmor() MonsterStat { typeRoll, _ := t.Roller.Roll("1d5") mStat := MonsterStat{} switch typeRoll[0] { case 1: mStat.Qualifier = "Unarmored" mStat.Value = 6 case 2: mStat.Qualifier = "Light protection" mStat.Value = 7 case 3: mStat.Qualifier = "Moderate protection" mStat.Value = 8 case 4: mStat.Qualifier = "Heavy protection" mStat.Value = 9 case 5: mStat.Value = 10 mStat.Qualifier = "Nigh impervious" } return mStat } func (t MonsterTable) genAttack() MonsterStat { typeRoll, _ := t.Roller.Roll("1d5") mStat := MonsterStat{} switch typeRoll[0] { case 1: mStat.Qualifier = "Untrained" mStat.Value = 0 case 2: mStat.Qualifier = "Trained" mStat.Value = 1 case 3: mStat.Qualifier = "Dangerous" mStat.Value = 2 case 4: mStat.Qualifier = "Masterful" mStat.Value = 3 case 5: mStat.Value = 4 mStat.Qualifier = "Lethal" } return mStat } func (t MonsterTable) genSTR() MonsterStat { typeRoll, _ := t.Roller.Roll("1d5") mStat := MonsterStat{} switch typeRoll[0] { case 1: mStat.Qualifier = "Weak" mStat.Value = 0 case 2: mStat.Qualifier = "Average" mStat.Value = 1 case 3: mStat.Qualifier = "Strong" mStat.Value = 2 case 4: mStat.Qualifier = "Powerful" mStat.Value = 3 case 5: mStat.Value = 4 mStat.Qualifier = "Monstrous" } return mStat } func (t MonsterTable) genDEX() MonsterStat { typeRoll, _ := t.Roller.Roll("1d5") mStat := MonsterStat{} switch typeRoll[0] { case 1: mStat.Qualifier = "Slow" mStat.Value = 0 case 2: mStat.Qualifier = "Average" mStat.Value = 1 case 3: mStat.Qualifier = "Nimble" mStat.Value = 2 case 4: mStat.Qualifier = "Swift" mStat.Value = 3 case 5: mStat.Value = 4 mStat.Qualifier = "Blurred" } return mStat } func (t MonsterTable) genWIL() MonsterStat { typeRoll, _ := t.Roller.Roll("1d5") mStat := MonsterStat{} switch typeRoll[0] { case 1: mStat.Qualifier = "Dimwitted" mStat.Value = 0 case 2: mStat.Qualifier = "Average" mStat.Value = 1 case 3: mStat.Qualifier = "Clever" mStat.Value = 2 case 4: mStat.Qualifier = "Brilliant" mStat.Value = 3 case 5: mStat.Value = 4 mStat.Qualifier = "Genius" } return mStat } func (t MonsterTable) Base(roll int) string { var base string switch roll { case 1, 2: base = t.AerialAnimals(t.Roller.TableRoll()) case 3, 4: base = t.TerrestrialAnimals(t.Roller.TableRoll()) case 5, 6: base = t.AquaticAnimals(t.Roller.TableRoll()) } return base } func (t MonsterTable) AerialAnimals(roll [2]int) string { return data.Tables.Monster.Aerial[roll[0]-1][roll[1]-1] } func (t MonsterTable) TerrestrialAnimals(roll [2]int) string { return data.Tables.Monster.Terrestrial[roll[0]-1][roll[1]-1] } func (t MonsterTable) AquaticAnimals(roll [2]int) string { return data.Tables.Monster.Aquatic[roll[0]-1][roll[1]-1] } func (t MonsterTable) Tactic(roll [2]int) string { return data.Tables.Monster.Tactics[roll[0]-1][roll[1]-1] } func (t MonsterTable) Feature(roll [2]int) string { return data.Tables.Monster.Features[roll[0]-1][roll[1]-1] } func (t MonsterTable) Personality(roll [2]int) string { return data.Tables.Monster.Personality[roll[0]-1][roll[1]-1] } func (t MonsterTable) Ability(roll [2]int) string { magicTable := MagicTable{Roller: t.Roller} switch roll { case [2]int{2, 4}: return magicTable.EtherealElement(t.Roller.TableRoll()) case [2]int{4, 5}: return magicTable.PhysicalElement(t.Roller.TableRoll()) default: return data.Tables.Monster.Abilities[roll[0]-1][roll[1]-1] } } func (t MonsterTable) Trait(roll [2]int) string { magicTable := MagicTable{Roller: t.Roller} switch roll { case [2]int{2, 3}: return magicTable.EtherealElement(t.Roller.TableRoll()) case [2]int{5, 1}: return magicTable.PhysicalElement(t.Roller.TableRoll()) default: return data.Tables.Monster.Traits[roll[0]-1][roll[1]-1] } }