222 lines
4.6 KiB
Go
222 lines
4.6 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"strconv"
|
||
|
)
|
||
|
|
||
|
var enemyHp int
|
||
|
var enemyDmg int
|
||
|
var enemyDef int
|
||
|
|
||
|
var weaponsAvailable []weapon
|
||
|
var armorAvailable []armor
|
||
|
var ringsAvailable []ring
|
||
|
|
||
|
var currWeapon, cheapWeapon, highWeapon weapon
|
||
|
var currArmor, cheapArmor, highArmor armor
|
||
|
var currRing1, cheapRing1, highRing1 ring
|
||
|
var currRing2, cheapRing2, highRing2 ring
|
||
|
|
||
|
// My input: ./day21 100 8 2
|
||
|
func main() {
|
||
|
if len(os.Args) < 4 || os.Args[1] == "-help" {
|
||
|
fmt.Println("Usage: day21 <enemy hp> <enemy dmg> <enemy def")
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
enemyHp = mustAtoi(os.Args[1])
|
||
|
enemyDmg = mustAtoi(os.Args[2])
|
||
|
enemyDef = mustAtoi(os.Args[3])
|
||
|
|
||
|
cheapest := -1
|
||
|
highest := -1
|
||
|
initShop()
|
||
|
|
||
|
for wi := range weaponsAvailable {
|
||
|
currWeapon = weaponsAvailable[wi]
|
||
|
for ai := range armorAvailable {
|
||
|
currArmor = armorAvailable[ai]
|
||
|
for r1i := range ringsAvailable {
|
||
|
currRing1 = ringsAvailable[r1i]
|
||
|
for r2i := range ringsAvailable {
|
||
|
if r2i == r1i {
|
||
|
continue
|
||
|
}
|
||
|
currRing2 = ringsAvailable[r2i]
|
||
|
if toTheDeath(false) {
|
||
|
if calcCost() < cheapest || cheapest == -1 {
|
||
|
cheapest = calcCost()
|
||
|
saveCheapest()
|
||
|
}
|
||
|
} else {
|
||
|
if calcCost() > highest || highest == -1 {
|
||
|
highest = calcCost()
|
||
|
saveHighest()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if cheapest >= 0 {
|
||
|
fmt.Println("Cheapest Victory: " + itoa(cheapest))
|
||
|
fmt.Println("Weapon: " + cheapWeapon.name)
|
||
|
fmt.Println("Armor: " + cheapArmor.name)
|
||
|
fmt.Println("Ring1: " + cheapRing1.name)
|
||
|
fmt.Println("Ring2: " + cheapRing2.name)
|
||
|
loadCheapest()
|
||
|
toTheDeath(true)
|
||
|
} else {
|
||
|
fmt.Println("No victory to be had.")
|
||
|
}
|
||
|
fmt.Println()
|
||
|
if highest >= 0 {
|
||
|
fmt.Println("Most Expensive Loss: " + itoa(highest))
|
||
|
fmt.Println("Weapon: " + highWeapon.name)
|
||
|
fmt.Println("Armor: " + highArmor.name)
|
||
|
fmt.Println("Ring1: " + highRing1.name)
|
||
|
fmt.Println("Ring2: " + highRing2.name)
|
||
|
loadHighest()
|
||
|
toTheDeath(true)
|
||
|
} else {
|
||
|
fmt.Println("No victory to be had.")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func loadCheapest() {
|
||
|
currWeapon = cheapWeapon
|
||
|
currArmor = cheapArmor
|
||
|
currRing1 = cheapRing1
|
||
|
currRing2 = cheapRing2
|
||
|
}
|
||
|
|
||
|
func saveCheapest() {
|
||
|
cheapWeapon = currWeapon
|
||
|
cheapArmor = currArmor
|
||
|
cheapRing1 = currRing1
|
||
|
cheapRing2 = currRing2
|
||
|
}
|
||
|
|
||
|
func loadHighest() {
|
||
|
currWeapon = highWeapon
|
||
|
currArmor = highArmor
|
||
|
currRing1 = highRing1
|
||
|
currRing2 = highRing2
|
||
|
}
|
||
|
|
||
|
func saveHighest() {
|
||
|
highWeapon = currWeapon
|
||
|
highArmor = currArmor
|
||
|
highRing1 = currRing1
|
||
|
highRing2 = currRing2
|
||
|
}
|
||
|
|
||
|
func toTheDeath(output bool) bool {
|
||
|
var pHp, pDmg, pDef, eHp, eDmg, eDef int
|
||
|
pHp = 100
|
||
|
|
||
|
pDmg += currWeapon.damage
|
||
|
pDmg += currRing1.damage
|
||
|
pDmg += currRing2.damage
|
||
|
pDef += currArmor.defense
|
||
|
pDef += currRing1.defense
|
||
|
pDef += currRing2.defense
|
||
|
|
||
|
eHp = enemyHp
|
||
|
eDmg = enemyDmg
|
||
|
eDef = enemyDef
|
||
|
|
||
|
for pHp > 0 && eHp > 0 {
|
||
|
pAtk := pDmg - eDef
|
||
|
if pAtk <= 1 {
|
||
|
pAtk = 1
|
||
|
}
|
||
|
eHp -= pAtk
|
||
|
eAtk := 1
|
||
|
if eHp > 0 {
|
||
|
eAtk = eDmg - pDef
|
||
|
if eAtk <= 1 {
|
||
|
eAtk = 1
|
||
|
}
|
||
|
pHp -= eAtk
|
||
|
}
|
||
|
}
|
||
|
if output {
|
||
|
fmt.Print(itoa(calcCost()) + ": ")
|
||
|
fmt.Print(itoa(pHp) + " to " + itoa(eHp) + " ")
|
||
|
fmt.Println("DMG(" + itoa(pDmg) + ") DEF(" + itoa(pDef) + ") ")
|
||
|
}
|
||
|
return pHp > 0
|
||
|
}
|
||
|
|
||
|
func calcCost() int {
|
||
|
return currWeapon.cost + currArmor.cost + currRing1.cost + currRing2.cost
|
||
|
}
|
||
|
|
||
|
func initShop() {
|
||
|
addWeapon("Dagger", 8, 4)
|
||
|
addWeapon("Shortsword", 10, 5)
|
||
|
addWeapon("Warhammer", 25, 6)
|
||
|
addWeapon("Longsword", 40, 7)
|
||
|
addWeapon("Greataxe", 74, 8)
|
||
|
|
||
|
addArmor("Leather", 13, 1)
|
||
|
addArmor("Chainmail", 31, 2)
|
||
|
addArmor("Splintmail", 53, 3)
|
||
|
addArmor("Bandedmail", 75, 4)
|
||
|
addArmor("Platemail", 102, 5)
|
||
|
addArmor("No Armor", 0, 0)
|
||
|
|
||
|
addRing("Damage +1", 25, 1, 0)
|
||
|
addRing("Damage +2", 50, 2, 0)
|
||
|
addRing("Damage +3", 100, 3, 0)
|
||
|
addRing("Defense +1", 20, 0, 1)
|
||
|
addRing("Defense +2", 40, 0, 2)
|
||
|
addRing("Defense +3", 80, 0, 3)
|
||
|
addRing("No Ring 1", 0, 0, 0)
|
||
|
addRing("No Ring 2", 0, 0, 0)
|
||
|
}
|
||
|
func addWeapon(n string, c, dmg int) {
|
||
|
weaponsAvailable = append(weaponsAvailable,
|
||
|
weapon{name: n, cost: c, damage: dmg})
|
||
|
}
|
||
|
func addArmor(n string, c, def int) {
|
||
|
armorAvailable = append(armorAvailable,
|
||
|
armor{name: n, cost: c, defense: def})
|
||
|
}
|
||
|
func addRing(n string, c, dmg, def int) {
|
||
|
ringsAvailable = append(ringsAvailable,
|
||
|
ring{name: n, cost: c, damage: dmg, defense: def})
|
||
|
}
|
||
|
|
||
|
type weapon struct {
|
||
|
name string
|
||
|
cost, damage int
|
||
|
}
|
||
|
|
||
|
type armor struct {
|
||
|
name string
|
||
|
cost, defense int
|
||
|
}
|
||
|
|
||
|
type ring struct {
|
||
|
name string
|
||
|
cost, damage, defense int
|
||
|
}
|
||
|
|
||
|
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
|
||
|
}
|