// Monster Battle -- finished version. // Two monsters trade blows until one faints. // Run with: go run projects/monster-battle/finished.go package main import ( "fmt" "math/rand" ) type monster struct { name string hp int maxHP int attack int } // newMonster checks the numbers first. rand.Intn crashes the program if it is // given a number below 1, so attack must be at least 1. func newMonster(name string, hp int, attack int) (*monster, error) { if hp < 1 { return nil, fmt.Errorf("%s: hp %d is below 1", name, hp) } if attack < 1 { return nil, fmt.Errorf("%s: attack %d is below 1", name, attack) } return &monster{name: name, hp: hp, maxHP: hp, attack: attack}, nil } func (m *monster) isAlive() bool { return m.hp > 0 } // hit deals random damage to other, prints the result and returns the damage. func (m *monster) hit(other *monster) int { damage := rand.Intn(m.attack) + 1 other.hp = other.hp - damage if other.hp < 0 { other.hp = 0 } fmt.Printf("%s hits %s for %d. %s has %d HP left.\n", m.name, other.name, damage, other.name, other.hp) return damage } // String makes *monster satisfy fmt.Stringer. func (m *monster) String() string { return fmt.Sprintf("%s: %d/%d HP", m.name, m.hp, m.maxHP) } func main() { hero, err := newMonster("Hero", 30, 8) if err != nil { fmt.Println("Error:", err) return } goblin, err := newMonster("Goblin", 25, 6) if err != nil { fmt.Println("Error:", err) return } dealt := map[string]int{} round := 1 for hero.isAlive() && goblin.isAlive() { fmt.Printf("-- Round %d --\n", round) dealt[hero.name] += hero.hit(goblin) if goblin.isAlive() { dealt[goblin.name] += goblin.hit(hero) } round++ } if hero.isAlive() { fmt.Println(hero.name + " wins!") } else { fmt.Println(goblin.name + " wins!") } fighters := []*monster{hero, goblin} for _, m := range fighters { fmt.Printf("%v, dealt %d damage\n", m, dealt[m.name]) } }