125 lines
2.5 KiB
Go
125 lines
2.5 KiB
Go
package day22
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"tools"
|
|
)
|
|
|
|
type Effect struct {
|
|
damage int
|
|
armor int
|
|
mana int
|
|
timer int
|
|
}
|
|
|
|
func (e Effect) copy() Effect {
|
|
return Effect{e.damage, e.armor, e.mana, e.timer}
|
|
}
|
|
|
|
type Spell struct {
|
|
cost int
|
|
damage int
|
|
heal int
|
|
applyEffect Effect
|
|
}
|
|
|
|
type Entity struct {
|
|
hitpoints int
|
|
mana int
|
|
damage int
|
|
armor int
|
|
currentEffects map[string]Effect
|
|
}
|
|
|
|
func (e Entity) copy() Entity {
|
|
return Entity{e.hitpoints, e.mana, e.damage, e.armor, e.currentEffects}
|
|
}
|
|
|
|
func (e Entity) printStats() {
|
|
fmt.Println("HP:", e.hitpoints, "Mana:", e.mana, "Damage:", e.damage, "Armor:", e.armor)
|
|
}
|
|
|
|
var spells = map[string]Spell{
|
|
"Magic Missile": {53, 4, 0, Effect{}},
|
|
"Drain": {73, 2, 2, Effect{}},
|
|
"Shield": {113, 0, 0, Effect{0, 7, 0, 6}},
|
|
"Poison": {173, 0, 0, Effect{3, 0, 0, 6}},
|
|
"Recharge": {229, 0, 0, Effect{0, 0, 101, 5}},
|
|
}
|
|
|
|
func applyEffects(player, boss *Entity) {
|
|
for eName, eData := range player.currentEffects {
|
|
switch eName {
|
|
case "Shield":
|
|
if eData.timer == spells["Shield"].applyEffect.timer {
|
|
player.armor += eData.armor
|
|
} else if eData.timer == 1 {
|
|
player.armor -= eData.armor
|
|
}
|
|
case "Recharge":
|
|
player.mana += eData.mana
|
|
}
|
|
eData.timer--
|
|
}
|
|
for eName, eData := range boss.currentEffects {
|
|
switch eName {
|
|
case "Poison":
|
|
boss.hitpoints -= eData.damage
|
|
}
|
|
eData.timer--
|
|
}
|
|
}
|
|
|
|
func fightRound(player, boss *Entity, spell Spell) (outcome int) {
|
|
// outcome will be -1 on boss win, 0 on both living and 1 on player win
|
|
|
|
applyEffects(player, boss)
|
|
if player.mana < spell.cost {
|
|
return -1
|
|
}
|
|
// cast spell
|
|
|
|
if boss.hitpoints <= 0 {
|
|
return 1
|
|
}
|
|
|
|
applyEffects(player, boss)
|
|
if boss.hitpoints <= 0 {
|
|
return 1
|
|
}
|
|
player.hitpoints -= tools.Max(1, boss.damage-player.armor)
|
|
if player.hitpoints <= 0 {
|
|
return -1
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
func Part1(puzzle tools.AoCPuzzle) interface{} {
|
|
player := Entity{50, 500, 0, 0, make(map[string]Effect)}
|
|
boss := Entity{0, 0, 0, 0, make(map[string]Effect)}
|
|
bossdata := puzzle.GetInputArray()
|
|
for _, line := range bossdata {
|
|
parts := strings.Split(line, ": ")
|
|
switch parts[0] {
|
|
case "Hit Points":
|
|
boss.hitpoints, _ = strconv.Atoi(parts[1])
|
|
case "Damage":
|
|
boss.damage, _ = strconv.Atoi(parts[1])
|
|
}
|
|
}
|
|
player.printStats()
|
|
boss.printStats()
|
|
fightRound(&player, &boss, spells["Magic Missile"])
|
|
player.printStats()
|
|
boss.printStats()
|
|
|
|
return 0
|
|
}
|
|
|
|
func Part2(puzzle tools.AoCPuzzle) interface{} {
|
|
return 0
|
|
}
|