package monsters import ( "dk/internal/database" "fmt" "zombiezen.com/go/sqlite" ) // Builder provides a fluent interface for creating monsters type Builder struct { monster *Monster db *database.DB } // NewBuilder creates a new monster builder func NewBuilder(db *database.DB) *Builder { return &Builder{ monster: &Monster{db: db}, db: db, } } // WithName sets the monster name func (b *Builder) WithName(name string) *Builder { b.monster.Name = name return b } // WithMaxHP sets the monster's maximum hit points func (b *Builder) WithMaxHP(maxHP int) *Builder { b.monster.MaxHP = maxHP return b } // WithMaxDmg sets the monster's maximum damage func (b *Builder) WithMaxDmg(maxDmg int) *Builder { b.monster.MaxDmg = maxDmg return b } // WithArmor sets the monster's armor value func (b *Builder) WithArmor(armor int) *Builder { b.monster.Armor = armor return b } // WithLevel sets the monster's level func (b *Builder) WithLevel(level int) *Builder { b.monster.Level = level return b } // WithMaxExp sets the monster's maximum experience reward func (b *Builder) WithMaxExp(maxExp int) *Builder { b.monster.MaxExp = maxExp return b } // WithMaxGold sets the monster's maximum gold reward func (b *Builder) WithMaxGold(maxGold int) *Builder { b.monster.MaxGold = maxGold return b } // WithImmunity sets the monster's immunity type func (b *Builder) WithImmunity(immunity int) *Builder { b.monster.Immune = immunity return b } // Create saves the monster to the database and returns it func (b *Builder) Create() (*Monster, error) { // Use a transaction to ensure we can get the ID var monster *Monster err := b.db.Transaction(func(tx *database.Tx) error { query := `INSERT INTO monsters (name, max_hp, max_dmg, armor, level, max_exp, max_gold, immune) VALUES (?, ?, ?, ?, ?, ?, ?, ?)` if err := tx.Exec(query, b.monster.Name, b.monster.MaxHP, b.monster.MaxDmg, b.monster.Armor, b.monster.Level, b.monster.MaxExp, b.monster.MaxGold, b.monster.Immune); err != nil { return fmt.Errorf("failed to insert monster: %w", err) } // Get the last inserted ID within the same transaction var lastID int err := tx.Query("SELECT last_insert_rowid()", func(stmt *sqlite.Stmt) error { lastID = stmt.ColumnInt(0) return nil }) if err != nil { return fmt.Errorf("failed to get last insert ID: %w", err) } // Create the monster with the ID monster = &Monster{ ID: lastID, Name: b.monster.Name, MaxHP: b.monster.MaxHP, MaxDmg: b.monster.MaxDmg, Armor: b.monster.Armor, Level: b.monster.Level, MaxExp: b.monster.MaxExp, MaxGold: b.monster.MaxGold, Immune: b.monster.Immune, db: b.db, } return nil }) if err != nil { return nil, fmt.Errorf("failed to create monster: %w", err) } return monster, nil }