Initial pass at Golden Pack.
This commit is contained in:
+83
-2
@@ -18,7 +18,26 @@ func (cx *ctx) applyTemplateShopEffects(deck []game.Card, c game.Card, trigger g
|
||||
}
|
||||
switch e.Action {
|
||||
case game.ActionGainApple:
|
||||
for range max(e.Count, 1) {
|
||||
n := max(e.Count, 1)
|
||||
switch e.Per {
|
||||
case game.PerShopFaintPets:
|
||||
n *= countShopFaintPets(cx.v.ShopRow)
|
||||
case game.PerBuysThisRound:
|
||||
// This buy will bump the counter, so count it (Blue-Ringed Octopus).
|
||||
n *= cx.me.BuysThisRound + 1
|
||||
}
|
||||
for range n {
|
||||
deck = append(deck, cx.simApple())
|
||||
}
|
||||
case game.ActionRevealForApples:
|
||||
// Cockatoo: the bot would reveal its highest-power other pet.
|
||||
best := 0
|
||||
for _, d := range deck {
|
||||
if d.IsPet() && d.ID != c.ID && d.Power > best {
|
||||
best = d.Power
|
||||
}
|
||||
}
|
||||
for range best {
|
||||
deck = append(deck, cx.simApple())
|
||||
}
|
||||
case game.ActionDoubleApples:
|
||||
@@ -31,11 +50,54 @@ func (cx *ctx) applyTemplateShopEffects(deck []game.Card, c game.Card, trigger g
|
||||
for range apples {
|
||||
deck = append(deck, cx.simApple())
|
||||
}
|
||||
case game.ActionApplesInPlay:
|
||||
// Golden pack (Hercules Beetle, sold): in-play apples aren't in the
|
||||
// deck, but they buff the front pet, so approximate them as deck
|
||||
// apples for scoring. MinRound is already gated above.
|
||||
for range max(e.Count, 1) {
|
||||
deck = append(deck, cx.simApple())
|
||||
}
|
||||
case game.ActionBuyTopFree:
|
||||
// Golden pack (Stoat): grabs an unknown top-of-deck card; approximate
|
||||
// with a sampled card of the current tier.
|
||||
pool := cx.unseenPool(cx.v.Round)
|
||||
if len(pool) == 0 {
|
||||
pool = game.TierContentsForPack(cx.v.Pack, cx.v.Round)
|
||||
}
|
||||
if len(pool) > 0 {
|
||||
rc := pool[rand.IntN(len(pool))]
|
||||
rc.ID = cx.nextSimID()
|
||||
deck = append(deck, rc)
|
||||
}
|
||||
case game.ActionSetAside:
|
||||
// Golden pack (Avocado): the just-bought token is set aside, not
|
||||
// kept in the deck being scored.
|
||||
if i := slices.IndexFunc(deck, func(d game.Card) bool { return d.ID == c.ID }); i >= 0 {
|
||||
deck = slices.Delete(deck, i, i+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
return deck
|
||||
}
|
||||
|
||||
// countShopFaintPets counts pets in the shop row with a Faint effect (mirrors
|
||||
// the engine's Opossum payout).
|
||||
func countShopFaintPets(row []game.Card) int {
|
||||
n := 0
|
||||
for _, c := range row {
|
||||
if c.ID == "" || !c.IsPet() {
|
||||
continue
|
||||
}
|
||||
for _, e := range c.Effects {
|
||||
if e.Trigger == game.TriggerFaint {
|
||||
n++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (cx *ctx) simApple() game.Card {
|
||||
return game.Card{
|
||||
ID: cx.nextSimID(),
|
||||
@@ -133,6 +195,25 @@ func (b *Bot) decideShop(v *game.View, mem *Memory) *Action {
|
||||
}
|
||||
}
|
||||
|
||||
// Golden pack: buying by discarding an Avocado yields the same deck as a
|
||||
// coin buy, so it's only preferred when coins are scarce — a small negative
|
||||
// bias keeps the token in reserve otherwise.
|
||||
if cx.me.Avocados > 0 {
|
||||
for i, c := range v.ShopRow {
|
||||
if c.ID == "" {
|
||||
continue
|
||||
}
|
||||
nd := append(slices.Clone(deck), c)
|
||||
nd = cx.applyTemplateShopEffects(nd, c, game.TriggerBuy)
|
||||
nd = cx.previewSellDown(nd)
|
||||
cands = append(cands, candidate{
|
||||
act: &Action{Type: "buyAvocado", Row: i},
|
||||
decks: [][]game.Card{nd},
|
||||
bias: -0.05,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Sell candidates: the worst 1, 2, or 3 keepers. Selling is free and
|
||||
// takes any number of cards, so bulk-dumping junk before a battle is one
|
||||
// action. Temporary cards are excluded — selling an apple for an apple
|
||||
@@ -201,7 +282,7 @@ func (b *Bot) decideShop(v *game.View, mem *Memory) *Action {
|
||||
}
|
||||
pool := cx.unseenPool(v.Round + 1)
|
||||
if len(pool) == 0 {
|
||||
pool = game.TierContents(v.Round + 1)
|
||||
pool = game.TierContentsForPack(v.Pack, v.Round+1)
|
||||
}
|
||||
var decks [][]game.Card
|
||||
for range 3 {
|
||||
|
||||
Reference in New Issue
Block a user