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 }