Permalink
Browse files

Fix the no-suicide rule when it goes two levels deep; it was permanen…

…tly changing its hypothetical game state and blaming every single card for losing the game.
  • Loading branch information...
2 parents 769e5bc + 9009649 commit 3a933957f810d8ae81233cfd37883b0e15ddf957 @rspeer committed Jan 26, 2012
Showing with 63 additions and 6 deletions.
  1. +3 −1 cards.coffee
  2. +59 −4 gameState.coffee
  3. +1 −1 play.coffee
View
4 cards.coffee
@@ -153,6 +153,8 @@ basicCard = {
shuffleEffect: (state) ->
# - What happens when this card is in hand and an opponent plays an attack?
reactToAttack: (state, player, attackEvent) ->
+ # - What happens when this card is in the duration pile and an opponent plays an attack?
+ durationReactToAttack: (state, player, attackEvent) ->
# - What happens when this card is in hand and its owner gains a card?
reactToGain: (state, player, card) ->
# - What happens when this card is in hand and someone else gains a card?
@@ -692,7 +694,7 @@ makeCard 'Lighthouse', duration, {
coins: +1
durationCoins: +1
- reactToAttack: (state, player, attackEvent) ->
+ durationReactToAttack: (state, player, attackEvent) ->
# Don't bother blocking the attack if it's already blocked (avoid log spam)
unless attackEvent.blocked
state.log("#{player.ai} is protected by the Lighthouse.")
View
63 gameState.coffee
@@ -293,7 +293,7 @@ class PlayerState
drawCards: (nCards) ->
drawn = this.getCardsFromDeck(nCards)
- @hand = @hand.concat(drawn)
+ Array::push.apply @hand, drawn
this.log("#{@ai} draws #{drawn.length} cards: #{drawn}.")
return drawn
@@ -667,6 +667,55 @@ class State
total += count
total += @trash.length
total
+
+ buyCausesToLose: (player, state, card) ->
+ if (state.gainsToEndGame() > 1)
+ return false
+ if (not card?)
+ return false
+
+ # One level of recursion is enough for first
+ if (this.depth==0)
+ [hypState, hypMy] = state.hypothetical(player.ai)
+ else
+ return false
+
+ # try to buy this card
+ # C&P from below
+ #
+ [coinCost, potionCost] = card.getCost(this)
+ hypMy.coins -= coinCost
+ hypMy.potions -= potionCost
+ hypMy.buys -= 1
+
+ hypState.gainCard(hypMy, card, 'discard', true)
+ card.onBuy(hypState)
+
+
+ for i in [hypMy.inPlay.length-1...-1]
+ cardInPlay = hypMy.inPlay[i]
+ if cardInPlay?
+ cardInPlay.buyInPlayEffect(hypState, card)
+
+ goonses = hypMy.countInPlay('Goons')
+ if goonses > 0
+ this.log("...gaining #{goonses} VP.")
+ hypMy.chips += goonses
+ #
+ # C&P until here
+
+ #finish buyPhase
+ hypState.doBuyPhase()
+
+ # find out if game ended and who if we have won it
+ hypState.phase = 'start'
+ if not hypState.gameIsOver()
+ return false
+ if ( hypMy.ai.toString() in hypState.getWinners() )
+ return false
+ state.log("Buying #{card} will cause #{player.ai} to lose the game")
+ return true
+
#### Playing a turn
#
@@ -822,7 +871,13 @@ class State
[coinCost, potionCost] = card.getCost(this)
if coinCost <= @current.coins and potionCost <= @current.potions
buyable.push(card)
+
+ # Don't allow cards that will lose us the game
+ #
+ # Note that this just cares for the buyPhase, gains by other means (Workshop) are not covered
+ buyable = (card for card in buyable when (not this.buyCausesToLose(@current, this, card)) )
+
# Ask the AI for its choice.
this.log("Coins: #{@current.coins}, Potions: #{@current.potions}, Buys: #{@current.buys}")
choice = @current.ai.chooseGain(this, buyable)
@@ -1188,12 +1243,12 @@ class State
# Reaction cards in the hand can react to the attack
reactionCards = (card for card in player.hand when card.isReaction)
- # Duration cards such as Lighthouse can also react
- reactionCards = reactionCards.concat(player.duration)
-
for card in reactionCards
card.reactToAttack(this, player, attackEvent)
+ for card in player.duration
+ card.durationReactToAttack(this, player, attackEvent)
+
# Apply the attack's effect unless it's been blocked by a card such as
# Moat or Lighthouse
effect(player) unless attackEvent.blocked
View
2 play.coffee
@@ -26,7 +26,7 @@ playGame = (filenames) ->
colonies: false
randomizeOrder: true
log: console.log
- require: []
+ require: ['Horse Traders']
})
until st.gameIsOver()
st.doPlay()

0 comments on commit 3a93395

Please sign in to comment.