package game import ( "fmt" "log" "strconv" "strings" ) // Attack contains all damage values for each attackable range. // The damage value for range 1 is stored at index 0, the value for range 2 at index 1 and so on. type Attack struct { attacks []int } // INVALID_ATTACK reports if there are no attackable ranges. func INVALID_ATTACK(a Attack) bool { return len(a.attacks) == 0 } // MaxRange returns the biggest attackable range. func (a Attack) MaxRange() int { return len(a.attacks) } // DamageInRange returns the damage in a certain range. func (a Attack) DamageInRange(r int) int { if r > a.MaxRange() { return 0 } return a.attacks[r-1] } // Ranged reports if the attack has more range than 1. func (a Attack) Ranged() bool { return a.MaxRange() > 1 } // Extend increases the MaxRange by amount. func (a *Attack) Extend(amount int) { d := a.DamageInRange(a.MaxRange()) for range amount { a.attacks = append(a.attacks, d) } } // Shorten decreases the MaxRange by amount. func (a *Attack) Shorten(amount int) { a.attacks = a.attacks[:len(a.attacks)-amount] } func (a Attack) String() string { if INVALID_ATTACK(a) { return "invalid attack" } if len(a.attacks) == 1 { return fmt.Sprintf("%d", a.attacks[0]) } r := a.MaxRange() return fmt.Sprintf("%d range %d", a.DamageInRange(r), r) } func parseAttack(attack any) Attack { if damage, ok := attack.(int); ok { return Attack{[]int{damage}} } attackStr := attack.(string) tokens := strings.Split(attackStr, " ") a, err := strconv.Atoi(tokens[0]) // TODO: think about panicking here if err != nil { log.Panicf("Attack %s has no valid Damage value\n", attackStr) } r := 1 if len(tokens) == 3 { r, err = strconv.Atoi(tokens[2]) if err != nil { log.Panicf("Attack %s has no valid Range value\n", attackStr) } } attacks := make([]int, 0, r) for range r { attacks = append(attacks, a) } return Attack{attacks} }