Combine AoC Repos
This commit is contained in:
227
2015/day22/main.go
Normal file
227
2015/day22/main.go
Normal file
@@ -0,0 +1,227 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
playerTurn = iota
|
||||
bossTurn
|
||||
)
|
||||
|
||||
type state struct {
|
||||
bossHp int
|
||||
bossDmg int
|
||||
playerHp int
|
||||
playerMp int
|
||||
playerDef int
|
||||
shield int
|
||||
poison int
|
||||
recharge int
|
||||
manaSpent int
|
||||
move int
|
||||
}
|
||||
|
||||
type spell struct {
|
||||
name string
|
||||
mpCost int
|
||||
damage int
|
||||
heal int
|
||||
duration int
|
||||
}
|
||||
|
||||
var minMp int
|
||||
var spellBook []spell
|
||||
var stateStack []state
|
||||
|
||||
func main() {
|
||||
minMp = -1
|
||||
initSpellBook()
|
||||
if len(os.Args) == 2 && os.Args[1] == "-help" {
|
||||
fmt.Println("Usage: day22 [<boss hp> <boss dmg> [<player hp> <player mp>]]")
|
||||
os.Exit(1)
|
||||
}
|
||||
//debugMode = true
|
||||
eHp := 71
|
||||
eDmg := 10
|
||||
if len(os.Args) >= 3 {
|
||||
eHp = mustAtoi(os.Args[1])
|
||||
eDmg = mustAtoi(os.Args[2])
|
||||
}
|
||||
pHp := 50
|
||||
pMp := 500
|
||||
if len(os.Args) == 5 {
|
||||
pHp = mustAtoi(os.Args[3])
|
||||
pMp = mustAtoi(os.Args[4])
|
||||
}
|
||||
s := state{
|
||||
bossHp: eHp,
|
||||
bossDmg: eDmg,
|
||||
playerHp: pHp,
|
||||
playerMp: pMp,
|
||||
playerDef: 0,
|
||||
shield: 0,
|
||||
poison: 0,
|
||||
recharge: 0,
|
||||
manaSpent: 0,
|
||||
move: playerTurn,
|
||||
}
|
||||
stateStack = append(stateStack, s)
|
||||
for len(stateStack) > 0 {
|
||||
var wrk state
|
||||
wrk, stateStack = stateStack[0], stateStack[1:]
|
||||
// Hard Mode
|
||||
if wrk.move == playerTurn {
|
||||
wrk.playerHp--
|
||||
}
|
||||
wrk.playerDef = 0
|
||||
if wrk.shield > 0 {
|
||||
wrk.playerDef = 7
|
||||
}
|
||||
if wrk.poison > 0 {
|
||||
wrk.bossHp -= 3
|
||||
}
|
||||
if wrk.recharge > 0 {
|
||||
wrk.playerMp += 101
|
||||
}
|
||||
wrk = decrementTimers(wrk)
|
||||
if wrk.playerHp <= 0 || (wrk.manaSpent > minMp && minMp != -1) {
|
||||
// Unsuccessful path
|
||||
continue
|
||||
}
|
||||
if wrk.bossHp <= 0 {
|
||||
// Successful path!
|
||||
if minMp == -1 || minMp > wrk.manaSpent {
|
||||
minMp = wrk.manaSpent
|
||||
}
|
||||
continue
|
||||
}
|
||||
if wrk.move == bossTurn {
|
||||
wrk.move = playerTurn
|
||||
atk := 1
|
||||
if wrk.bossDmg-wrk.playerDef > 1 {
|
||||
atk = wrk.bossDmg - wrk.playerDef
|
||||
}
|
||||
wrk.playerHp -= atk
|
||||
stateStack = append([]state{wrk}, stateStack...)
|
||||
} else {
|
||||
wrk.move = bossTurn
|
||||
for i := range spellBook {
|
||||
tstSpell := spellBook[i]
|
||||
if tstSpell.mpCost >= wrk.playerMp {
|
||||
continue
|
||||
}
|
||||
nextState, ok := castSpell(wrk, tstSpell)
|
||||
if ok {
|
||||
stateStack = append([]state{nextState}, stateStack...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Printf("%d\n", minMp)
|
||||
}
|
||||
|
||||
func castSpell(w state, s spell) (state, bool) {
|
||||
if s.name == "Magic Missile" || s.name == "Drain" {
|
||||
w.bossHp -= s.damage
|
||||
w.playerHp += s.heal
|
||||
} else if s.name == "Shield" {
|
||||
if w.shield > 0 {
|
||||
return w, false
|
||||
}
|
||||
w.shield = s.duration
|
||||
} else if s.name == "Poison" {
|
||||
if w.poison > 0 {
|
||||
return w, false
|
||||
}
|
||||
w.poison = s.duration
|
||||
} else if s.name == "Recharge" {
|
||||
if w.recharge > 0 {
|
||||
return w, false
|
||||
}
|
||||
w.recharge = s.duration
|
||||
}
|
||||
w.playerMp -= s.mpCost
|
||||
w.manaSpent += s.mpCost
|
||||
return w, true
|
||||
}
|
||||
|
||||
func copyState(w state) state {
|
||||
ret := state{
|
||||
bossHp: w.bossHp,
|
||||
bossDmg: w.bossDmg,
|
||||
playerHp: w.playerHp,
|
||||
playerMp: w.playerMp,
|
||||
playerDef: w.playerDef,
|
||||
shield: w.shield,
|
||||
poison: w.poison,
|
||||
recharge: w.recharge,
|
||||
manaSpent: w.manaSpent,
|
||||
move: w.move,
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func printState(w state) {
|
||||
if w.move == playerTurn {
|
||||
fmt.Println("*** Player Turn ***")
|
||||
} else {
|
||||
fmt.Println("*** Boss Turn ***")
|
||||
}
|
||||
fmt.Printf("Player - HP(%d) MP(%d)\n", w.playerHp, w.playerMp)
|
||||
fmt.Printf("Boss - HP(%d) DMG(%d)\n", w.bossHp, w.bossDmg)
|
||||
fmt.Printf("Shield(%d); Poison(%d); Recharge(%d)\n", w.shield, w.poison, w.recharge)
|
||||
fmt.Printf("Mana Used: %d\n", w.manaSpent)
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func decrementTimers(w state) state {
|
||||
w.shield--
|
||||
w.poison--
|
||||
w.recharge--
|
||||
return w
|
||||
}
|
||||
|
||||
func initSpellBook() {
|
||||
spellBook = append(spellBook, spell{
|
||||
name: "Magic Missile",
|
||||
mpCost: 53,
|
||||
damage: 4,
|
||||
})
|
||||
spellBook = append(spellBook, spell{
|
||||
name: "Drain",
|
||||
mpCost: 73,
|
||||
damage: 2,
|
||||
heal: 2,
|
||||
})
|
||||
spellBook = append(spellBook, spell{
|
||||
name: "Shield",
|
||||
mpCost: 113,
|
||||
duration: 6,
|
||||
})
|
||||
spellBook = append(spellBook, spell{
|
||||
name: "Poison",
|
||||
mpCost: 173,
|
||||
duration: 6,
|
||||
})
|
||||
spellBook = append(spellBook, spell{
|
||||
name: "Recharge",
|
||||
mpCost: 229,
|
||||
duration: 5,
|
||||
})
|
||||
}
|
||||
|
||||
func itoa(i int) string {
|
||||
return strconv.Itoa(i)
|
||||
}
|
||||
func mustAtoi(s string) int {
|
||||
var i int
|
||||
var err error
|
||||
if i, err = strconv.Atoi(s); err != nil {
|
||||
fmt.Println("Tried to atoi " + s)
|
||||
os.Exit(1)
|
||||
}
|
||||
return i
|
||||
}
|
||||
Reference in New Issue
Block a user