Skip to content

Commit

Permalink
Merge branch 'master' into aiplayvalue
Browse files Browse the repository at this point in the history
Conflicts:
	basicAI.coffee
	cards.coffee
  • Loading branch information
Rob Speer committed May 27, 2012
2 parents 5228fd4 + 1d01a03 commit 9662d85
Show file tree
Hide file tree
Showing 14 changed files with 504 additions and 220 deletions.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -10,7 +10,7 @@ web-strategies:
coffee compileStrategies.coffee

css:
lessc web/dominiate.less web/dominiate.css
node_modules/.bin/lessc web/dominiate.less web/dominiate.css

doc:
docco *.coffee
Expand Down
6 changes: 6 additions & 0 deletions README.md
Expand Up @@ -61,6 +61,12 @@ downloaded from the Internet, you of course run this at your own risk.)
Running `windows/compile.bat` should do the Right Thing, but I haven't tested
it. See `windows/README` for more information.

Genetic algorithm version
-------------------------
Dr. Mitchell Morris is working on an exciting version of Dominiate that can evolve
new strategies using genetic algorithms. You can find this version at
https://github.com/Narmical/dominiate.

Roadmap
-------
Short-term planned features include:
Expand Down
35 changes: 27 additions & 8 deletions basicAI.coffee
Expand Up @@ -82,13 +82,15 @@ class BasicAI
choiceSet = {}
for choice in choices
choiceSet[choice] = choice

nullable = null in choices

# Get the priority list.
priority = priorityfunc.bind(this)(state, my)
priority = priorityfunc.call(this, state, my)
# Now look up all the preferences in that list. The moment we encounter
# a valid choice, we can return it.
for preference in priority
if preference is null and null in choices
if preference is null and nullable
return null
if choiceSet[preference]?
return choiceSet[preference]
Expand All @@ -103,7 +105,7 @@ class BasicAI
if (choice is null) or (choice is no)
value = 0
else
value = valuefunc.bind(this)(state, choice, my)
value = valuefunc.call(this, state, choice, my)
if value > bestValue
bestValue = value
bestChoice = choice
Expand Down Expand Up @@ -274,7 +276,9 @@ class BasicAI
"Conspirator" if my.inPlay.length >= 2 or multiplier > 1
"Familiar"
"Highway"
"Scheme"
"Wishing Well"
"Golem" # seems to be reasonable to expect +1 action from Golem
"Great Hall" if state.cardInfo.Crossroads not in my.hand
"Spice Merchant" if state.cardInfo.Copper in my.hand
"Stables" if this.choose('stablesDiscard', state, my.hand.concat([null]))
Expand Down Expand Up @@ -302,7 +306,7 @@ class BasicAI
# 7: Let's insert here an overly simplistic idea of how to play Crossroads.
# Or if we don't have a Crossroads, play a Great Hall that we might otherwise
# have played in priority level 5. (500-599)
"Crossroads" unless my.crossroadsPlayed
"Crossroads" unless my.countInPlay(state.cardInfo.Crossroads) > 0
"Great Hall"

# 8: card-cycling that might improve the hand. (400-499)
Expand Down Expand Up @@ -391,6 +395,7 @@ class BasicAI
"Trader" if wantsToTrash >= multiplier
"Trade Route" if wantsToTrash >= multiplier
"Mint" if my.ai.choose('mint', state, my.hand) # 140
"Secret Chamber"
"Pirate Ship"
"Noble Brigand"
"Thief"
Expand Down Expand Up @@ -436,7 +441,7 @@ class BasicAI
"Treasure Map"
"Ambassador"
"Throne Room"
]
]

# `multipliedActionPriority` is similar to `actionPriority`, but is used when
# we have played a Throne Room or King's Court.
Expand All @@ -453,9 +458,10 @@ class BasicAI
"Mountebank"
"Witch" if my.actions > 0 and state.countInSupply("Curse") >= 2
"Sea Hag" if my.actions > 0 and state.countInSupply("Curse") >= 2
"Crossroads" if (not my.crossroadsPlayed) or (my.actions > 0)
"Crossroads" if my.actions > 0 or my.countInPlay(state.cardInfo.Crossroads) == 0
"Torturer" if my.actions > 0 and state.countInSupply("Curse") >= 2
"Young Witch" if my.actions > 0 and state.countInSupply("Curse") >= 2
"Scheme" if my.countInDeck("King's Court") >= 2
"Scrying Pool"
"Wharf" if my.actions > 0
"Bridge" if my.actions > 0
Expand Down Expand Up @@ -632,7 +638,7 @@ class BasicAI
for card in my.hand
if (card.isTreasure) and (not (card in treasures))
treasures.push card
treasures.sort( (x, y) -> x.coins - y.coins)
treasures.sort( (x, y) -> y.coins - x.coins)

# Get the margin of how much money we're willing to discard.
margin = my.ai.coinLossMargin(state)
Expand Down Expand Up @@ -882,6 +888,19 @@ class BasicAI

return this.upgradeValue(state, [card, gained], my)

# Scheme uses the same priority function as multiplied actions. Good actions
# to multiply this turn are typically good actions to have around next turn.
schemePriority: (state, my) ->
# Project a little of what the state will look like at the beginning of the
# next turn. This keeps multipliedActionPriority from evaluating a card
# as though it will be used in the current (finished) turn.
myNext = {}
myNext[key] = value for key, value of my
myNext.actions = 1
myNext.buys = 1
myNext.coins = 0
this.multipliedActionPriority(state, myNext)

# `scryingPoolDiscardValue` is like `discardValue`, except it strongly
# prefers to discard non-actions.
scryingPoolDiscardValue: (state, card, my) ->
Expand Down Expand Up @@ -1101,7 +1120,7 @@ class BasicAI
# TODO: do we need an equivalent for potions?
coinLossMargin: (state) ->
newState = this.pessimisticBuyPhase(state)
coins = newState.coins
coins = newState.current.coins
cardToBuy = newState.getSingleBuyDecision()
return 0 if cardToBuy is null
[coinsCost, potionsCost] = cardToBuy.getCost(newState)
Expand Down
8 changes: 4 additions & 4 deletions card_list.txt
@@ -1,4 +1,4 @@
Cards that are done (157)
Cards that are done (158)
=========================
Adventurer
Alchemist
Expand Down Expand Up @@ -117,6 +117,7 @@ Salvager
Scout
Scrying Pool
Sea Hag
Secret Chamber
Shanty Town
Silk Road
Silver
Expand Down Expand Up @@ -158,7 +159,7 @@ Worker's Village
Workshop
Young Witch

Cards that still need to be coded (13)
Cards that still need to be coded (12)
======================================

Possibly easy cards
Expand All @@ -178,7 +179,7 @@ to write.
Black Market (requires a new setup step)
Develop (the hard part is making the list of choices)
Embargo (the trick is guessing what your opponent wants)
Forge
Forge (exponentially increasing number of choices!)
Inn
Native Village

Expand All @@ -187,6 +188,5 @@ Difficult cards
In estimated order of difficulty:

Scheme (adds a new sub-phase to cleanup)
Secret Chamber (avoid infinite loops)
Stash (requires a decision mid-shuffle)
Possession (will require entirely new kinds of AI decisions)

0 comments on commit 9662d85

Please sign in to comment.