aoc2015/day22/day.go
2021-01-16 15:46:32 +01:00

149 lines
3.1 KiB
Go

package day22
import (
"fmt"
"math"
"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}
}
var activeEffects map[string]*Effect
type Spell struct {
cost int
damage int
heal int
applyEffect Effect
}
type Entity struct {
hitpoints int
mana int
damage int
armor int
}
func (e Entity) copy() *Entity {
return &Entity{e.hitpoints, e.mana, e.damage, e.armor}
}
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 activeEffects {
switch eName {
case "Shield":
if eData.timer == spells["Shield"].applyEffect.timer {
fmt.Println("Apply Shield")
player.armor += eData.armor
} else if eData.timer == 1 {
fmt.Println("Remove Shield")
player.armor -= eData.armor
}
case "Recharge":
fmt.Println("Regen Mana")
player.mana += eData.mana
case "Poison":
fmt.Println("Apply Poison")
boss.hitpoints -= eData.damage
}
activeEffects[eName].timer--
if eData.timer == 0 {
fmt.Println(eName, "wears off.")
delete(activeEffects, eName)
}
}
}
func fightRound(player, boss *Entity, spellName string) (outcome int) {
// outcome will be -1 on boss win, 0 on both living and 1 on player win
spell := spells[spellName]
applyEffects(player, boss)
if player.mana < spell.cost {
return -1
}
player.mana -= spell.cost
player.hitpoints += spell.heal
boss.hitpoints -= spell.damage
if _, ok := activeEffects[spellName]; !ok && spell.applyEffect.timer > 0 {
activeEffects[spellName] = spell.applyEffect.copy()
}
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 minManaToTheDeath(player, boss *Entity) int {
manaUsed := 0
minManaUsed := math.MaxInt64
return manaUsed
}
func Part1(puzzle tools.AoCPuzzle) interface{} {
activeEffects = make(map[string]*Effect)
player := Entity{50, 500, 0, 0}
boss := Entity{0, 0, 0, 0}
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()
fmt.Println("-----")
for _, s := range []string{"Recharge", "Shield", "Drain", "Poison", "Magic Missile"} {
fightRound(&player, &boss, s)
player.printStats()
boss.printStats()
fmt.Println("-----")
}
return 0
}
func Part2(puzzle tools.AoCPuzzle) interface{} {
return 0
}