Dominion Strategy Forum

Dominion => Simulation => Topic started by: rspeer on September 11, 2011, 03:55:09 am

Title: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 11, 2011, 03:55:09 am
Hey all. I've got a new Dominion simulator, and it's made of JavaScript so you can run it right now on the Web (unless your browser sucks)! Here it is: http://rspeer.github.com/dominiate/play.html

Now, this is nowhere near a substitute for Geronimoo's simulator at this point. For one thing, I've only implemented 37-ish Kingdom cards so far (although now that OMG IT WORKS, I can probably get to defining a lot more of them quickly.) It'd also be nice if it had more pre-defined strategies than the few that appear in the dropdown box.

But running on the Web will hopefully make simulation accessible to many more people. Some other interesting differences are:
Notable deficiencies:

This project is open source, and I really would appreciate help finishing it, because Dominion is a game with a lot of parts to it. Heck, I made all the JavaScript and CSS and stuff work, so implementing more cards and strategies is the fun part. Places to start with that include:
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 11, 2011, 07:48:01 am
Nice work and good documentation.

I was looking through the card definitions and saw you've forgotten about Princess for the "real" cost calculation:

Code: [Select]
getCost: (state) ->
    coins = this.costInCoins(state)
    coins -= state.bridges

// Some of my pseudocode here
if state.princesses > 0 then coins -= 2
// Don't know if it counts TR'd or KC'd cards as multiple played "copies"
// End pseudocode

    if this.isAction
      coins -= state.quarries * 2
    if coins < 0
      coins = 0
    return [coins, this.costInPotions(state)]
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Geronimoo on September 11, 2011, 09:15:43 am
OOOhh jealous of your documentation. No way you're a professional IT, they don't make docs  ;)

So do the bots learn to play better while they're playing?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 11, 2011, 12:31:42 pm
Nice work and good documentation.

I was looking through the card definitions and saw you've forgotten about Princess for the "real" cost calculation:

Code: [Select]
getCost: (state) ->
    coins = this.costInCoins(state)
    coins -= state.bridges

// Some of my pseudocode here
if state.princesses > 0 then coins -= 2
// Don't know if it counts TR'd or KC'd cards as multiple played "copies"
// End pseudocode

    if this.isAction
      coins -= state.quarries * 2
    if coins < 0
      coins = 0
    return [coins, this.costInPotions(state)]

A bit confusing, I admit. This isn't counting copies of the card (that would be state.current.countInPlay('Bridge'), and it would fail on Throne Rooms and King's Courts).

Instead, there is a value in the state that applies a discount to every card cost, and I call it "bridges". The effect of playing a bridge is to increase the "bridges" value by 1, and the effect of playing a Princess (not that you can get a Princess at the moment...) is to increase it by 2.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 11, 2011, 12:35:05 pm
OOOhh jealous of your documentation. No way you're a professional IT, they don't make docs  ;)

So do the bots learn to play better while they're playing?

Not at the moment.

I have two things I want to try with that. One is to define strategies with parameters, and then the bots can learn which parameters win the most.

The other approach is Golem (http://github.com/rspeer/golem),  a separate project I've got which uses machine learning over all the games in dominionstats to learn which cards are good to buy when. It's definitely a goal I have to hook this up to Golem. But it'll require calls to a separate server, the interface code will be pretty messy, and it'll slow the simulation way down.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 11, 2011, 01:04:04 pm
IT professional here and yeah, making documentation is the equivalent of cleaning the coal containers on an ocean liner, one of the "less" fun tasks.

However, often there are moments you'd wish you've written some documentation, I have seen some forgotten software projects come back to life, because of a sudden interest from a client.


I like the clean CoffeeCode, haven't used it myself and how you deal with the governing 'state'. When I dabbled in Dominion simulation, I've often wondered where I should put stuff like Bridge's special action.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 11, 2011, 03:51:52 pm
HOLY HELL, IT RUNS ON MY PHONE.

Is it the future now? Because my phone just played a thousand or so games of Dominion against itself. (In the process it got rather warm and used about 8% of the battery. And the strategy editors were of course quite unusable.)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Tydude on September 11, 2011, 04:16:18 pm
Is it just my code, or does it not work if you don't include Colony and Platinum? For example, I just set up a simple code for Big Money+Smithy.
Code: [Select]
{
  name: 'BigMoneyU'
  gainPriority: (state) -> [
    "Colony" if state.current.countInDeck("Platinum") > 0
    "Province" if state.countInSupply("Colony") <= 6 \
               or state.countInSupply("Province") <= 6
   
    "Duchy" if 0 < state.gainsToEndGame() <= 5
    "Estate" if 0 < state.gainsToEndGame() <= 2
    "Platinum"
    "Gold"
    "Smithy" if state.current.countInDeck("Smithy")<1
    "Silver"
    "Copper" if state.gainsToEndGame() <= 3
  ]
}

Right? If I run it with Colonies, it works as expected (buys a single Smithy and then BM from there on out). With no Colonies, it seems to completely skip buying the Smithy.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 11, 2011, 05:19:59 pm
Is it just my code, or does it not work if you don't include Colony and Platinum? For example, I just set up a simple code for Big Money+Smithy.
Code: [Select]
{
  name: 'BigMoneyU'
  gainPriority: (state) -> [
    "Colony" if state.current.countInDeck("Platinum") > 0
    "Province" if state.countInSupply("Colony") <= 6 \
               or state.countInSupply("Province") <= 6
   
    "Duchy" if 0 < state.gainsToEndGame() <= 5
    "Estate" if 0 < state.gainsToEndGame() <= 2
    "Platinum"
    "Gold"
    "Smithy" if state.current.countInDeck("Smithy")<1
    "Silver"
    "Copper" if state.gainsToEndGame() <= 3
  ]
}

Right? If I run it with Colonies, it works as expected (buys a single Smithy and then BM from there on out). With no Colonies, it seems to completely skip buying the Smithy.

Oh man. The supply was pretty messed up if that box was unchecked. Thanks for finding the bug, and I've fixed it now.

Incidentally, I added the rule to buy a second Smithy once there are 16 cards in the deck, and put it up as a selectable strategy called "BigSmithy".
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Matt_Arnold on September 11, 2011, 05:43:05 pm
Awesome. Fantastic. I have forked and will submit my proposed file change soon.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Matt_Arnold on September 11, 2011, 05:52:27 pm
So let me make sure I understand this. I decided to experiment with how I could code Monument in cards.coffee. There's a difference between being VP and accumulating VP tokens, but I'm not sure I see these represented differently in your code. Perhaps your intent is that at the end of the game, each Victory card will be "played" once, thereby activating their "vp" property and accumulating tokens? Therefore, Monument would just use the property "vp: 1". Is this a correct assumption?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Matt_Arnold on September 11, 2011, 05:55:54 pm
Never mind; I found state.current.chips += 1
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Geronimoo on September 12, 2011, 04:48:33 am
Nice how you have 5 lines of code where I need 5 pages in some cases :)

I haven't read the docs in detail, but are you using the buy rules in deciding how to play certain cards (like Chapel, Remodel,...) ? I found that this improved the decisions a lot in my sim.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 12, 2011, 05:14:43 am
Is there an easy checklist for the cards you have done/need to be done?
Looking through the source it can be a bit difficult to spot which ones you still need.

I've been thinking about Trade Route, adding "tradeRouteValue" to state seems enough to me, no need to do something with a mat.
This value should be increased whenever a VP card is bought.
Calculating the TR value by counting if the full amount of VP cards is left in a certain pile is incorrect due to Ambassador.

I don't think it's necessary to explicitly not use this value if Trade Route is not in the supply, we can still update the value as an O(1) operation, but just do nothing with it, but if it can be easily programmed, of course it should be done.

I wanted to create a trunk and try some things myself, but somehow my adjustment (Adding Trade Route Value to the state) ended up in the main branch. Please retract if you find this erroneous.

I will refrain from proceeding with the tricky part.

The tricky part is where to maintain if the token was already moved to the "TR Mat".

We could:
- Create some extra TR pool with the names of the VP cards that have been gained at least once from the Supply. If a card on the "gain" (or "buy") action wants to add himself to this pool (and increase the TR value), it only succeeds if it's not yet in there.
- Create explicit booleans for each card to maintain which has added to the TR value (not what we want).
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Buggz on September 12, 2011, 05:56:11 am
This value should be increased whenever a VP card is bought.
..that hasn't been bought before. You'll need to specifically keep track of which VP cards have been used to increase TRs value.

EDIT: A Trade Route object containing current value and an array of the cards used should suffice, but I haven't had the chance to look at the code yet and how things are implemented.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 12, 2011, 05:57:46 am
This value should be increased whenever a VP card is bought.
..that hasn't been bought before. You'll need to specifically keep track of which VP cards have been used to increase TRs value.
Yes, I discovered this too, see my edit in my previous post.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Thisisnotasmile on September 12, 2011, 06:11:19 am
I'm not a programmer so if this is not possible, ignore me. Idea:

When Trade Route is in play, use a (mathematical) set that starts as the empty set S = {}. Whenever a Victory card is gained, a copy of it gets moved into this set (e.g. S = {Province, Estate}). Since one of the properties of sets is that all members are unique, adding duplicate cards to the set will not change the value of the set (e.g. S = {Province, Estate, Province} = {Province, Estate}). Then, whenever someone uses a Trade Route, all you need to do is measure the cardinality of set S to find the value of Trade Route.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 12, 2011, 06:13:35 am
Hmm,I doubt whether a "loose" language like JavaScript has such a mathematical set.

It can be easily simulated though.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Geronimoo on September 12, 2011, 06:16:03 am
Thank you thisisnotasmile, I updated my Trade Route code (which used a List instead of a Set)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Thisisnotasmile on September 12, 2011, 06:16:54 am
Finally my three years at university studying maths has paid off!
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Buggz on September 12, 2011, 06:40:28 am
Pseudocode ahoy:
Code: [Select]
var coinValue = TradeRouteArrayOfBoughtCards.length;

if(!$.inArray(VPCardJustBought, ArrayOfBoughtVPCards)) {
    ArrayOfBoughtVPCards.push(VPCardJustBought);
}
Only would only need to store the name, not the whole card object. Discard if already in the array. If one wants to be more gentle with the processor one could initialize it with every VP card and then remove them instead, thus you won't need the extra check. Then one could just return false or coin value or whatever needed directly if the array is empty (I doubt it would have a noticeable effect though).

But I shouldn't get into too much detail without having a clue on how the code looks and works.

EDIT: Just got another idea, one could just bind another function on a buy event (or whatever applicable) of a VP card, and then remove that bind after the first purchase.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Sopenas on September 12, 2011, 07:33:58 am
Hello,

  Amazing work! Keep it going :)

  I found one problem with trashing. I was experimenting with fishing villages, and noticed bot wants to leave at least 3 coppers before trashing them. And when counting coppers it does not include fishing willage's +1 coin. So it leads to situations, where it thashes less than it should to. I copy/pasted one example. Here bot has already bought fishing village, so it needs two coppers to keep buying power, but it keeps three of them. I guess trashing algorithm is hard coded, but maybe i am wrong? Here is log:

== BankWharf's turn 1 ==
BankWharf plays Copper.
BankWharf plays Copper.
BankWharf plays Copper.
Coins: 3, Potions: 0, Buys: 1
BankWharf buys Chapel.
BankWharf draws 5 cards (Copper,Estate,Copper,Copper,Copper).

== BankWharf's turn 2 ==
BankWharf plays Copper.
BankWharf plays Copper.
BankWharf plays Copper.
BankWharf plays Copper.
Coins: 4, Potions: 0, Buys: 1
BankWharf buys Fishing Village.
(BankWharf shuffles.)
BankWharf draws 5 cards (Estate,Copper,Copper,Chapel,Fishing Village).

== BankWharf's turn 3 ==
BankWharf plays Fishing Village.
BankWharf plays Chapel.
BankWharf trashes Estate.
BankWharf trashes Copper.
BankWharf trashes Copper.
Coins: 1, Potions: 0, Buys: 1
BankWharf draws 5 cards (Copper,Copper,Copper,Estate,Copper).

== BankWharf's turn 4 ==
BankWharf resolves the duration effect of Fishing Village.
BankWharf plays Copper.
BankWharf plays Copper.
BankWharf plays Copper.
BankWharf plays Copper.
Coins: 5, Potions: 0, Buys: 1
BankWharf buys Wharf.
(BankWharf shuffles.)
BankWharf draws 5 cards (Estate,Copper,Chapel,Copper,Copper).


== BankWharf's turn 5 ==
BankWharf plays Chapel.
BankWharf trashes Estate.
BankWharf trashes Copper.
BankWharf trashes Copper.
BankWharf plays Copper. - should trash it too, because bot still is capable of buying silver with 2 coppers ant fishing village
Coins: 1, Potions: 0, Buys: 1
BankWharf draws 5 cards (Estate,Copper,Wharf,Fishing Village,Copper).

Good luck :)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 12, 2011, 07:49:39 am
I have made some modifications to the sources for Trade Route.

I kept it simple:
- Added a Trade Route "Mat" (array) and Value (int) to the State.
- Whenever a card is gained, it fires and checks to see if TR is in play, the card is a VP card and already on the list and adds the card and sets a new Trade Route Value if the card is not yet on the list

I even sent a Pull Request I believe.

I am new to GitHub, so bear with me.


I wanted to add the event to the VP cards instead of the main gainCard() method, but I could only find an overridable Buy method and not Gain.
I think a Gain method may be needed not only for this, but other cards as well, but my understanding of the source is still very little, so maybe you can do the rest of the work.

Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rrenaud on September 12, 2011, 09:31:12 am
Nice.

How hard would it be to make a councilroom feature where you can start from a given turn from an already played game and simulate from strategies from there?  We could make the simplifying assumption that both decks start shuffled.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 12, 2011, 11:45:54 am
Nice how you have 5 lines of code where I need 5 pages in some cases :)

I haven't read the docs in detail, but are you using the buy rules in deciding how to play certain cards (like Chapel, Remodel,...) ? I found that this improved the decisions a lot in my sim.

Chapel follows the trashPriority / trashValue rules. trashPriority is an ordered list of what to trash with possible conditions, like the buy rules. Everything that can be defined as a priority list can also be defined as a function returning a value for each choice, but I haven't used this much because priority lists are easier.

I haven't done Remodel and Expand yet, but it seems to me like they may require a separate decision (to know about things like remodeling gold into province). I suppose this could be deduced if the strategy defines both a gainValue and a trashValue, because you could take the difference, but that will almost never be the case.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 12, 2011, 12:16:36 pm
I have made some modifications to the sources for Trade Route.

I kept it simple:
- Added a Trade Route "Mat" (array) and Value (int) to the State.
- Whenever a card is gained, it fires and checks to see if TR is in play, the card is a VP card and already on the list and adds the card and sets a new Trade Route Value if the card is not yet on the list

I even sent a Pull Request I believe.

I am new to GitHub, so bear with me.


I wanted to add the event to the VP cards instead of the main gainCard() method, but I could only find an overridable Buy method and not Gain.
I think a Gain method may be needed not only for this, but other cards as well, but my understanding of the source is still very little, so maybe you can do the rest of the work.

I've debugged and merged it -- thanks! I also added it to the default action priority, near the end, but there should actually be some sort of condition there, because there are many situations where you'd prefer not to play Trade Route. SillyAI is playing it with hands full of expensive cards sometimes.

As an event triggered when an entire type of card is gained, the main gainCard() method is a good place for it. I don't think gainEffect() is necessary.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 12, 2011, 12:19:59 pm
Hello,

  Amazing work! Keep it going :)

  I found one problem with trashing. I was experimenting with fishing villages, and noticed bot wants to leave at least 3 coppers before trashing them. And when counting coppers it does not include fishing willage's +1 coin. So it leads to situations, where it thashes less than it should to. I copy/pasted one example. Here bot has already bought fishing village, so it needs two coppers to keep buying power, but it keeps three of them. I guess trashing algorithm is hard coded, but maybe i am wrong? Here is log:

I'm trying to hard-code as little as possible -- the hardcoded things are things like always revealing a Moat. The trashPriority can be overridden by AIs. You can see the default one in http://rspeer.github.com/dominiate/docs/basicAI.html.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 12, 2011, 12:26:02 pm
Okay, here's the list of cards that are done and not done:

https://github.com/rspeer/dominiate/blob/master/card_list.txt

We're up to 64 cards (including the 10 base cards and 5 prizes)! There are still some easy ones left to code, too.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 12, 2011, 12:31:37 pm
Nice.

How hard would it be to make a councilroom feature where you can start from a given turn from an already played game and simulate from strategies from there?  We could make the simplifying assumption that both decks start shuffled.

One sort of hard part would be getting the game state from that turn in that game. I see why you suggest starting by shuffling both decks -- because CouncilRoom already has some JS that counts the number of cards in each deck and the supply.

Then we'd also need some UI for starting Dominiate in a mid-game state.

It sounds cool but kind of fiddly to code, so I probably won't get to that kind of thing for a while.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 12, 2011, 01:04:26 pm
Ambassador can be somewhat of an AI challenge, since it can be challenging for humans.

In this hand (let's say after you've been Minioned): Copper-Copper-Estate-Ambassador
What do you reveal/return? 2 Coppers or the 1 Estate. If you're Minioning yourself, then I think the 2 Coppers are better since you need to thin your deck as much as possible. Otherwise, the useless Estate could be better.

And then there's TR and KC. We might want to tell the AI not to return until the 2nd or 3rd time or something, but this also depends very much on the cards in hand.

KC-Ambassador-Curse-Curse-Curse is easy for humans, since you'll just return 1 at a time or 1 times 1 and 1 times 2, but you have to have at least 1 for the third time.


So all in all, I can see some challenges here, but maybe Geronimoo is willing to put some of his ideas here, since he has a lot of experience with his own.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: WanderingWinder on September 12, 2011, 02:03:32 pm
As a general strategy point, you most often want to prefer returning two coppers to one estate. This comes up a lot in early-game amb-cop-cop-cop-est hands.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ackack on September 12, 2011, 02:11:31 pm
As a general strategy point, you most often want to prefer returning two coppers to one estate. This comes up a lot in early-game amb-cop-cop-cop-est hands.

I don't think this is as obvious as a lot of people seem to think it is, and I think it's pretty dependent on what else is out there. Decks that Ambassador 1 Estate exclusively in this spot (which certainly isn't optimal, but as an experiment) end up substantially fatter but also substantially wealthier than decks that Ambassador 2 Coppers exclusively. I suspect a strategy like send an Estate the first time and then 2 Coppers thereafter probably works pretty well. If you have some way of playing 2 Ambassadors at a go, then it might be more worthwhile to winnow down as fast as possible.

added: questions in a similar vein are Remaking Coppers vs. Estates early, or whether a Steward and 4 Coppers should trash or buy Gold. In general I lean towards buying power unless there's some engine I'm building that needs to be trimmed down as fast as possible, or if there's some other specific reason I want to get Copper out of the deck (I'm playing Venture, I'm defending against Pirate Ship, etc.)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 12, 2011, 02:29:59 pm
Okay, this is making it clear that the next time I can justify coding on this, I should implement Ambassador. And then we can make different bots with the two different Ambassador rules, and actually find out whether it's better to return one estate or two coppers in general.

TWO STRATEGIES ENTER. ONE STRATEGY LEAVES.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: WanderingWinder on September 12, 2011, 04:15:08 pm
Also note I said 'in general' - I expect this is probably 80% of the time, and it's based on my experience, which I think is pretty good, but not, of course, infallible.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Kirian on September 12, 2011, 04:41:23 pm
Quick feature requests:

A "Stop" button for when pressing "until one strategy dominates" can run for thousands of games.  A "Run until stopped" button would be useful too but less interesting.

A "Reset" button.  When I make a small tweak to one strategy or the other, as far as I can tell, the only way to reset the wins to zero is to F5... which also resets anything else.

Otherwise, a great little app!
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: WanderingWinder on September 12, 2011, 04:54:34 pm
When I click to simulate 100 games, it will go to where there are 100 more games in the current bank of games than there were in the previous, even if I've switched the strategies. i.e. if I simmed 500 games with strategy A vs. strategy B, and then want to sim C vs. D, it starts back at 0 and sims 600 games.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 12, 2011, 05:50:48 pm
I'm an aspiring programmer (still finishing my undergraduate), with a little experience, and this looks like a fun project to get some experience with and learn some new stuff. Hopefully I'll be able to code some cards while there are still some left  :P
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 12, 2011, 06:02:51 pm
Ok, how's this look for Tactician?

Code: [Select]
makeCard 'Tactician', duration, {
 cost: 5

 playEffect: (state) ->
  discardCards = no

  if current.hand.length > 0
      discardCards = yes

  state.requireDiscard (current, current.hand.length)

  if discarded
     durationCards: +5
     durationBuys: +1
     durationActions: +1
}

Still learning github, don't have time at the moment to try more cards or figure out how to submit the changes or whatever, but at least I managed to put something together before work.

Edit: cleaned up tabs in code block
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rrenaud on September 12, 2011, 06:10:28 pm
Github should be paying rspeer for all the new accounts getting created on his behalf ;P
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 12, 2011, 06:26:06 pm
Code: [Select]
makeCard 'Tactician', duration, {
 cost: 5

 playEffect: (state) ->
  discardCards = no

  if current.hand.length > 0
      discardCards = yes

  state.requireDiscard (current, current.hand.length)

  if discarded
     durationCards: +5
     durationBuys: +1
     durationActions: +1
}

That's about the right idea, but the "if discarded" block at the end won't work. It's probably not correct syntax, but more relevantly there's no way to fit in the +5 cards, +1 action, and +1 buy in that part of the code.

When the duration effect is being resolved, it's not running the playEffect code at all, it's running durationEffect. If the effect is constant, it can use the default durationEffect code, which is to look up the card object's durationActions, durationBuys, etc. and apply them. (You can't change these values from the playEffect. Modifying actual values on a card is a bad idea, because there is one Tactician object, it can just show up in a lot of places in the game.)

But Tactician's effect is infuriatingly non-constant because it needs to remember if you discarded any cards with it, so we can't take the easy route. How can we remember that between the playEffect of one turn and the durationEffect of the next? I'm afraid the answer is: yet another property on the PlayerState!

Here's how I'd outline it:

This is also the first card I'd feel the need to specifically write test cases for. So far I've been lazy about testing, and with most cards I just watch how SillyAI plays it over a number of games and make sure it looks right. But the edge cases of Tactician that require all this code are things that I have probably never seen happen in an actual game of Dominion.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 13, 2011, 01:08:06 am
Unfortunately I thought of how it wouldn't quite work in the if discarded block after I was at work and unable to go back and rethink it. I read the documentation last night but apparently not enough of it stuck ::)

Your response was very helpful, I feel I have a better understanding of how to approach cards in general. (if I specifically respond to every useful thing you said my post will be too long :P)

Maybe I'll give Tactician another crack. In any case, thanks for the patience with a relative newbie.

I'm going to keep trying this, and hopefully get some cards right. Don't think I'll try Possession though ;)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 13, 2011, 03:45:52 am
May I ask how you handle a required trash?

I simply put "trash: 1" in the card definition, but I don't know if this even works.
And how do you "trash for benefit" like Remake, Apprentice.

I am looking into Apprentice currently.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 13, 2011, 05:03:23 am
May I ask how you handle a required trash?

I simply put "trash: 1" in the card definition, but I don't know if this even works.
And how do you "trash for benefit" like Remake, Apprentice.

I am looking into Apprentice currently.

"trash: 1" should work as of recently, for a simple required trash with no further effect. See Trade Route.

Trash for benefit is a doozy. I think we could knock off Remodel, Expand, Upgrade, and Remake all at once, but it'll take a fair amount of new code to get there.

In the playEffect, you could make the actual trashing happen with "state.requireTrash(state.current, 1)". But this will cause AIs to make the wrong decisions -- in trash-for-benefit cards, you often want to trash good cards because the benefit is even better, while these methods will just consult the trashPriority list and probably trash an Estate, a Copper, or a Curse. So there should be a new method ("requireImproveCard"?), which asks the AI for a new kind of decision.

After that, you need to determine what was trashed, to give the benefit -- you could count the cards left in hand, and compare them to the original list, but that's awful. Really this is a sign that requireTrash and allowTrash should return a list of the trashed cards. I'll correct this oversight on my part shortly.

Speaking of cards that require a lot of code, Ambassador is up! That took longer than I thought, so I won't get to nice things like a stop button tonight. I'm particularly interested in tweaks to DoubleAmbassador that make it win more.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 13, 2011, 05:11:52 am
My cursory look at Ambassador strategies has been interesting. Play two versions of DoubleAmbassador against each other. Change the second one to prefer returning "Copper,2" (with its conditions) over "Estate,1", and call it "DoubleAmbassadorPrime".

DoubleAmbassadorPrime wins about 60% of Colony games against DoubleAmbassador, but only about 40% of non-Colony games.

That's pretty wacky. What causes this difference? I took into account some interactions between returning Copper and buying Silver. Should I also have done this for buying Gold or Platinum?

Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rinkworks on September 13, 2011, 10:32:00 am
Trash for benefit is a doozy. I think we could knock off Remodel, Expand, Upgrade, and Remake all at once, but it'll take a fair amount of new code to get there.

I've been working on a Dominion playing game myself, and indeed, I found this to be the case.  All four cards follow the same logic, just different parameters:  (1) How many cards to upgrade, (2) how much higher the cost of the new card may be, and (3) whether the cost of the new card must be exact or "up to."

Quote
in trash-for-benefit cards, you often want to trash good cards because the benefit is even better, while these methods will just consult the trashPriority list and probably trash an Estate, a Copper, or a Curse. So there should be a new method ("requireImproveCard"?), which asks the AI for a new kind of decision.

Possession is the only official card I have yet to touch, but aside from that, the trash-for-benefit cards were indeed the hardest to write A.I. for, and I still have a lot of tweaking to do.  Actually, Remodel/Expand/Upgrade/Remake aren't that bad, because you can hook into your "buy a card" routine for choosing what new card to obtain.

But Salvager, Bishop, and Apprentice (probably in that order) are monsters.  In case it helps, here's how I got something that probably isn't ideal but at least isn't embarrasing.

Common To All Three Cards

When playing any of these three cards, I look at each card in my hand and evaluate it as a trash target.  Doing this evaluation involves looking at three separate things:

(1) The benefit.  How much extra buying power will I get if I trash this card.  More importantly, what does that extra buying power allow me to get in return?  More on this when I talk about the individual cards.

(2) The loss of the card in terms of the power of my deck.  I have an "evaluate this deck" function that looks at your whole deck and tries to evaluate its power.  This is a complicated analysis and (at present) very flawed, but basically it looks at what your average hand size is likely to be, which in turn helps it figure out what your average buying power, attacking power, etc., you're liable to have is, how many VPs you have, and so on.  All those factors are weighted and averaged based on how far progressed the game is (for example, # of VPs is the overriding consideration in the end-game but barely at all in the early game).

(3) The "play value" of the card.  This is an estimation of how useful the card is to actually play.  I use the card's cost as a starting point, adjusting as necessary.  For example, the play value of a Sea Hag is 4 normally but drops to -1 when the Curses run out.  Cards with VPs (e.g., Island, Nobles, etc) are penalized, and "pure VP" cards have a -1 play value.

Salvager

Salvager is the easiest of the three because unless you trash a card whose supply pile is depleted, you can't make too bad a mistake.  Worst case, you re-buy the card you trash.  But you obviously want to improve upon no effect.

In calculating the benefit, I first look at how much money I anticipate having if I *don't* play the Salvager, then comapre that to how much I'll have if I *do* play the Salvager.  Then I compare those two values to see if I will cross any particular critical threshold.

For example, if I anticipate having $7 without playing the Salvager and $9 if I do, that allows me to buy a Province, and so I consider that a good Salvager play.  However, if I anticipate having $8 without playing the Salvager and $10 if I do, I consider that a poor Salvager play.  Especially since Salvager allows multiple buys, I also look at thresholds such as $13 (Province + Duchy) and $16 (Province + Province) and other combinations.  (Of course it's important not to look at actual fixed values, like $8 and $16, but at "the current cost of Province" and "the current cost of two Provinces," since Bridge and Princess can muck with those amounts.)

Anyway, the upshot is that I come out of this calculation not with a $ amount but a +VP amount.  Ultimately I don't care if I'm getting +$2, I care what +VP change that causes.  To make this more accurate, I then need to adjust this number by subtracting the # of VP that the trashed card would have given me.

I now balance this +/- VP consideration with the change to my "deck evaluation" and the "play value" of the card to trash.  For the "play value," I'm particularly interested in seeing the difference between the play value and the card's base cost.  That way dead Sea Hags (for example) really stand-out as strong Salvager candidates.

Then I assign at weight to all these heuristics (again valuing +/- VP high in the late game, low in the early game), and ultimately wind up with a number that is quite useless except when compared with the results of these same calculations for the other cards in my hand.

Whichever card results in the highest calculation gets trashed.  If the numbers for all the cards in my hand are negative, I don't play the Salvager at all.

Obviously this is a HIGHLY fuzzy and error-prone calculation.  But as my goal is to build something that approximates good play, rather than a provably optimal strategy, it suits my purposes fine.

Apprentice

Essentially the same calculation as Salvager, IF you are able to write a function that, given some number of +cards, will tell you how much extra spending power your deck is liable to produce with them.  My such function tries to take into account what actions I'm liable to draw with those cards too, but it still ultimately tries to boil that consideration down into an estimate of increased buying power.

One complication is that you have to consider how many buys you have.  With Salvager, if your expected buying power goes from $15 to $16, you don't have to worry about having the extra buy to afford the second Province, because it gives you that extra buy.  With Apprentice, the crossing the $15 -> $16 threshold is only useful if you have an extra buy from somewhere else, or anticipate drawing a card that will give you +buy.

Bishop

Actually this is probably the easiest of the three to code unless you want to take into account the benefit to the other players.  I didn't, so I just look at the same three values:  (1) +/- VP, (2) change in deck power, (3) play value of the card to trash.

(2) and (3) are calculated in the exact same way as for Salvager and Apprentice.  Calculating (1) is a whole lot easier, because you don't have to look at cost thresholds or anything.  You just look at the the number of VP chips you get and subtract any VPs attached to the card you're trashing.

In Summary

I hope the above helps.  Even if you don't go to the lengths I did, maybe this rambling will help you think about an approach you do or do not wish to take to solving the problem.  If you do decide to do something like what I did, recognize that it's a lot of work, and the results are fuzzy and imperfect.  Probably what you want in a sim is something simpler anyhow.  But for me, I'm kind of interested in seeing how far I can take this.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 13, 2011, 11:52:10 am
If people are looking for easy cards to start with, here are ones that can be done with existing code and require no new decisions:

Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 13, 2011, 12:30:09 pm
I coded Familiar, Ironworks and Moneylender last night but must have not done everything correctly on GitHub, but when I look at the master dominiate page it is showing I have one pull request, so I'm not quite sure where I went wrong.

I also just realized that Ironworks probably won't be optimal at the moment; I just copied the Workshop code and added to the end for the bonuses, so I don't think it will properly handle situations like multiple Ironworks in hand when the highest priority to gain is Gardens but it would be better to gain action cards first and Gardens with the last Ironworks played.

I also noticed that the Workshop cost was set at 4, rather than 3, and that's another change I included in my pull request.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 13, 2011, 01:47:09 pm
You did it right, and I pulled in your changes. And thanks for catching my Workshop thinko.

While you're at it, could you add Familiar, Ironworks, and Moneylender to the default actionPriority in basicAI.coffee, in reasonable places?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 13, 2011, 01:57:05 pm
Will do, and I'll be sure to do the same for other cards as I add them.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: danshep on September 13, 2011, 08:38:50 pm
To write rules for the Salvager/Apprentice/Bishop trashings, just changing the existing trash rules so that it has knowledge of WHY it is trashing should work, so you can do:

Code: [Select]
trashPriority: (state, trasher) -> [
  "Apprentice" if trasher == "Apprentice"
  ... rest of priorities ...
]

Not sure where that trasher variable belongs - whether it should be a parameter or on the method or something on the state, or is there a state already for the current card being played?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 13, 2011, 09:41:50 pm
I've been thinking of having a "state.current.activeCards" variable, which contains the stack of cards that are currently being resolved. Kind of like state.current.inPlay, but excluding the cards that have been completely resolved.

So it might be ["Apprentice"] or ["Golem", "Tactician"] or ["King's Court", "King's Court", "Masquerade"], to name a few relevant situations.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: danshep on September 13, 2011, 11:30:07 pm
I think you might need to be able to pass in the current trasher to the trash rules, if only so that you can let the trash rules be checked from the play rules, so just knowing the active cards is play isn't going to cut it.

The default play rule for bishop/apprentice/salvager is going to need to check if there is a trash target for card first, so it's going to need to be able to call the trash rules, asking whether there is a card that could be trashed.

You could get around this with a 'theoriticalTrashPriority' method which messes with the activeCards array before calling the trashPriority method, but I think that might make for some confusing code.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 14, 2011, 12:24:29 am
If I understand what you're suggesting, there's already the equivalent for Shanty Town. To check whether a Shanty Town will succeed, you have to not count the Shanty Town itself, so there's a flag that determines this. I think it's worth the extra code to determine whether an action is useful.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 15, 2011, 03:41:30 am
I made some updates to the simulator:
Note that "state.current" can only be replaced by "my" on AI decision functions, not when defining cards. Cards don't have a "my".

Here's a new list of relatively easy cards for people to try implementing:
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 15, 2011, 03:55:56 am
I'll do Watchtower today, that's a bit of a challenge (AI part), yet easy enough to plow through with some infallible Vulcan logic.

Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 15, 2011, 11:55:45 am
I forgot the card effect of Watchtower isn't that easy because of the two decisions you make (reveal Watchtower? Put the card on the deck or trash it?) upon gaining a card.

These decisions could be modeled after chooseBaronDiscard.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 15, 2011, 12:03:55 pm
Speaking of adding AI code, there's now literate documentation for basicAI.coffee (http://rspeer.github.com/dominiate/docs/basicAI.html). It both explains the default strategies, and it describes how the decision functions work. So if anyone (in addition to Davio) wants to take on a card that requires a new kind of decision, go ahead!

Some suggestions of cards that just need a new decision type: Apothecary, Bureaucrat, Chancellor, Hamlet, Herbalist, Island, Jester, Library, Loan, Mine, Mining Village, Minion, Mint, Pearl Diver, Pirate Ship, Royal Seal, Rabble, Scout, Spy, Torturer, Wishing Well

Also, Counting House, Navigator, and Trading Post are still out there and don't need new decision types.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 15, 2011, 08:25:33 pm
Tactician is finally in, and so is Wishing Well. We're up to 80 out of 141 cards!
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 16, 2011, 02:55:20 am
And an important update: Dominiate now has error handling.

Okay, so it just pops up a JavaScript alert, which I recognize is design straight out of 1995, but as with other aspects of the design it'll get better. At least it doesn't just silently brood when it hits an error anymore.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 16, 2011, 03:28:55 am
I ran into some complications with Watchtower.

- First of all, it's not "really" a Reaction card in the sense that it doesn't do anything when an opponent plays an attack card. It's currently the only of the 4 (Moat, SC, HT are the others) that does this.
- How to decide whether to trash or put on deck or do nothing?

I guess it should follow these basic rules:
- If the card's in the trashpriority list, trash it
- If it's a pure victory card, don't reveal (let it go to discard)
- Else put it on deck

This doesn't catch the edge cases of Ambassadoring players, Gardening players (and perhaps Golem/Counting House) wanting Coppers & Curses and Tournament players wanting Provinces on top, but these can built in if need be.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 16, 2011, 04:18:25 am
Those rules sound right to me.

I don't know what I was thinking when I said Watchtower would be straightforward. But anyway, you can define what it does as a "gainReaction" function (where the other reaction cards have "attackReaction") -- which I hadn't actually hooked into the game state until now. You should 'git pull' to get that new code.

To see if an AI wants to trash a card, you can give it a trash decision between that card and null: if this.chooseTrash(state, [card, null]) is card... This is what wantsToTrash() does to count the number of cards the AI would like to trash.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 16, 2011, 06:00:18 am
Those rules sound right to me.

I don't know what I was thinking when I said Watchtower would be straightforward. But anyway, you can define what it does as a "gainReaction" function (where the other reaction cards have "attackReaction") -- which I hadn't actually hooked into the game state until now. You should 'git pull' to get that new code.

To see if an AI wants to trash a card, you can give it a trash decision between that card and null: if this.chooseTrash(state, [card, null]) is card... This is what wantsToTrash() does to count the number of cards the AI would like to trash.
Isn't there a bug?

# - What happens when this card is in hand and its owner gains a card?
  gainReaction: (state) ->

  reactToGain: (player, card) ->
    this.gainReaction(player, card)


You use (state) and (player,card), I think the first one needs to be edited.
Also in gameState.coffee you only pass player, not card...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 16, 2011, 08:37:44 am
Gah, yes.

It should probably take (state, player, card).
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 16, 2011, 08:49:23 am
How about this for passing the actual card?
I was wondering if passing 'card' instead of the top card of the discard pile would create a duplicate...

Code: [Select]
gainCard: (player, card, suppressMessage=false) ->
    if card in @prizes or @supply[card] > 0
      if not suppressMessage
        this.log("#{player.ai} gains #{card}.")
      player.discard.push(card)
      if card in @prizes
        @prizes.remove(card)
      else
        @supply[card] -= 1
      if @supply["Trade Route"]? and card.isVictory and card not in @tradeRouteMat
        @tradeRouteMat.push(card)
        @tradeRouteValue += 1
      for i in [player.hand.length-1...-1]
        reactCard = player.hand[i]
        if reactCard.isReaction
          reactCard.reactToGain(state, player, player.discard[player.discard.length-1])
    else
      this.log("There is no #{card} to gain.")


How's this for a rudimentary Watchtower:
Code: [Select]
makeCard 'Watchtower', action {
cost: 3
isReaction: true
playEffect: (state) ->
handLength = state.current.hand.length
if handLength < 6
state.drawCards(state.current, 6 - handLength)
gainReaction: (state, player, card) ->
if player.ai.chooseTrash(state, [card, null])
player.discard.remove(card)
if (not card.isVictory) or (card.isVictory and (card.isAction or card.isTreasure))
player.discard.remove(card)
player.draw.push(card)
}
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 16, 2011, 10:39:22 am
Quote
Code: [Select]
if (not card.isVictory) or (card.isVictory and (card.isAction or card.isTreasure))

Why do you want (!Vic) or (Vic and (Ac or Tr)) ?
a) doesn't that put Curses on the Draw, given you don't want to trash them (for what ever reason, say Gardens)
b) isn't what you really want
Code: [Select]
if (card.isAction or card.isTreasure)
Or what am I missing?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 16, 2011, 11:51:55 am
Code: [Select]
I was wondering if passing 'card' instead of the top card of the discard pile would create a duplicate...

A key decision I made early on in the code is that cards are singleton objects. So, for example, you can refer to c.Estate in multiple places without worrying if it's this c.Estate or that c.Estate, just like multiple arrays can contain the number 3 without caring whether it's this 3 or that 3.

The main thing you need to make sure of is that when you add a card to one list, you remove it from another (or from the supply). And you're doing that correctly when you do
Code: [Select]
player.discard.remove(card)
player.draw.push(card)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 16, 2011, 05:30:46 pm
Quote
Code: [Select]
if (not card.isVictory) or (card.isVictory and (card.isAction or card.isTreasure))

Why do you want (!Vic) or (Vic and (Ac or Tr)) ?
a) doesn't that put Curses on the Draw, given you don't want to trash them (for what ever reason, say Gardens)
b) isn't what you really want
Code: [Select]
if (card.isAction or card.isTreasure)
Or what am I missing?
There should have been an else there.

The second part can indeed be simplified by (card.isAction or card.isTreasure), guess it was just the regular Friday screen-stare blindness.
I constructed some weird condition worrying about mixed Victory cards.

So this is better:
Code: [Select]
makeCard 'Watchtower', action {
cost: 3
isReaction: true
playEffect: (state) ->
handLength = state.current.hand.length
if handLength < 6
state.drawCards(state.current, 6 - handLength)
gainReaction: (state, player, card) ->
if player.ai.chooseTrash(state, [card, null])
player.discard.remove(card)
else if card.isAction or card.isTreasure
player.discard.remove(card)
player.draw.push(card)
}
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 16, 2011, 05:56:48 pm
rspeer, I have a question about something I actually already asked you about on github, but I think it would be beneficial to post the question here as well.

How exactly should the output (via state.log) be formatted? Obviously Isotropic is a great standard to look at, but I'm specifically curious about the use of ellipses--Isotropic constantly uses them, and some of the cards in cards.coffee use them, but not all of them.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 16, 2011, 06:15:07 pm
If you want to be more consistent than me about output, that's great.

I generally use the ellipses when I'm adding more output to an effect that I know has already output something. Isotropic uses them to represent the depth of the action stack, which is a fancier and better idea. I haven't made an action stack yet.

That second Watchtower reaction will work, but it never consults the AI. Here's one possible solution that could be re-used for Royal Seal:
Code: [Select]
if player.ai.chooseToGainOnDeck(state, card)
And the default chooseToGainOnDeck on the BasicAI would then be:
Code: [Select]
(state, card) -> card.isAction or card.isTreasure
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 17, 2011, 04:33:47 am
Updates: Watchtower is finally in, Followers is fixed to have its full effect, and AIs can now make their own hypothetical copies of the state to play with: "What happens if I draw three cards? I'll guess at what they are. Do they help?"
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 19, 2011, 04:01:15 am
Updates from this weekend:

I optimized one of the most frequently-called functions, gainsToEndGame(), yielding a 2-4x speedup in simulation speed.

Royal Seal, Mint, and Masquerade are in.

The AI decision framework is reworked somewhat. Now an AI can have both an xPriority and an xValue for any decision 'x'; it will use the xValue if it runs off the priority list. This makes it possible, for example, to define discard preferences better: its first choice is to discard a pure Victory card. After that the value function kicks in, and it tries to discard a terminal action it won't get to play, or otherwise the card with the lowest base cost.

With this new framework, it's possible to define cards that make new kinds of decisions without adding so much plumbing to BasicAI.coffee. Asking for ai.choose('foo', state, choices) will go straight to the fooValue and fooPriority functions, without having to define two more functions as middlemen.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 24, 2011, 05:22:35 pm
We're up to 100 cards! A great occasion to commemorate with my 100th post to the forum. Recent cards include Remodel, Expand, Remake, Upgrade, Mine, Herbalist, Lookout, Bureaucrat, Apothecary, Scout, and Library.

I notice that contributions from others have trailed off... If anyone wants help getting set up with GitHub or CoffeeScript, PM me.

As something that might help a number of people to contribute, I've just added a batch file for compiling the code on Windows without node.js! You won't be able to run the command-line version, but you should be able to edit the code and run the edited version in your browser. I haven't tested this process yet, though.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 25, 2011, 12:03:10 am
This past week was really busy for me in school and as much as I wanted to spend time coding more Dominion cards, homework had to be the priority :o

Working on some cards right now though  :)

edit: Treasury and Cutpurse are done  ;)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 25, 2011, 05:42:20 am
Finally got myself into all of this and did Counting House
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 25, 2011, 10:51:47 am
One Coffeescript question:

The actionPriority is implemented by a function that returns an array, if I interpret
Code: [Select]
actionPriority: (state,my) -> [
...
]
correctly? On the other hand, when I follow what happens with the returnvalue of this function, it seems to be a single element...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 25, 2011, 12:22:26 pm
And I think I got the Outpost. It does work when:

played in normal turn -> extra turn with 3 cards
played in extra turn -> draw 3 cards, no extra turn

any more weird edge cases I have forgotten?

Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 25, 2011, 01:04:27 pm
Maybe some funkiness with Possession?
But with Possession you play your opponent's turn, not your own, so it doesn't count towards your # of turns.

Do all Duration cards work with the extra turn?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 25, 2011, 01:30:21 pm
Maybe some funkiness with Possession?
But with Possession you play your opponent's turn, not your own, so it doesn't count towards your # of turns.

Do all Duration cards work with the extra turn?

Possession is not implemented, so I think we shouldn't care for it for the moment. But that's the card I also had in mind. KC/TR perhaps also must taken care of...
 
Have just tested on Fishing Village until now, but the "extra turn" from the point of view of the programm is just a "normal turn", where we skip the rotation of the player and that get's another intro (don't count turns, different headline). Maybe I should take a look on Tactician, while I don't see what should be different there I'm a lit suspicious.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 25, 2011, 01:39:39 pm
Oh, found a small bug, it drew 3 cards in cleanup all the time. Would swear that it didn't do it a few hours ago. Anyway, is fixed,.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 25, 2011, 02:20:40 pm
Oh, found a small bug, it drew 3 cards in cleanup all the time. Would swear that it didn't do it a few hours ago. Anyway, is fixed,.

Isn't that what Outpost is supposed to do, even if it doesn't get you another extra turn?

Quote from: Outpost
You only draw 3 cards (instead of 5) in this turn's Clean-up phase. Take an extra turn after this one. This can't cause you to take more than two consecutive turns.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 25, 2011, 02:28:04 pm
Oh, found a small bug, it drew 3 cards in cleanup all the time. Would swear that it didn't do it a few hours ago. Anyway, is fixed,.

Isn't that what Outpost is supposed to do, even if it doesn't get you another extra turn?

Quote from: Outpost
You only draw 3 cards (instead of 5) in this turn's Clean-up phase. Take an extra turn after this one. This can't cause you to take more than two consecutive turns.

Yeah, that's what Outpost is supposed to do. But my implementation drew 3 cards no matter what, even if you didn't played (or even bought) an Outpost.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 25, 2011, 03:07:58 pm
Oh, ok that makes sense. Should have figured I misunderstood it  ::)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 25, 2011, 03:10:38 pm
One Coffeescript question:

The actionPriority is implemented by a function that returns an array, if I interpret
Code: [Select]
actionPriority: (state,my) -> [
...
]
correctly? On the other hand, when I follow what happens with the returnvalue of this function, it seems to be a single element...

That's indeed a function that returns an array. Generally I assign the result to something called "priority" and iterate over it with a for...in loop. For example, in chooseByPriorityAndValue:

Code: [Select]
      # Get the priority list.
      priority = priorityfunc(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
        # see if we can make this choice, etc.

Anyway, time to go look at the incoming code on GitHub! Thanks guys!
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 25, 2011, 03:23:33 pm

That's indeed a function that returns an array. Generally I assign the result to something called "priority" and iterate over it with a for...in loop. For example, in chooseByPriorityAndValue:

Thanks, that's good news. Then I'll try to improve the heuristics for putting cards back to deck. Heuristics will be
Code: [Select]
# 1) Put the best action you can't use back on deck
 
  # 2) Put the best treasure you don't need back on deck
 
  # 3) Put the worst card back on deck
Any complains?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 25, 2011, 04:18:16 pm
Sounds great.

I suppose "treasure you don't need" will be calculated by seeing if you would buy something different without that treasure? I believe that's how Geronimoo does it and it would make sense to me. Although that'll require a change to SillyAI, which will buy something different because whee random.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 25, 2011, 06:20:17 pm
ARRRGGH

Anybody any idea why I might get a
Code: [Select]
TypeError: Cannot read property 'Shanty Town' of undefined
on
Code: [Select]
putOnDeckPriority: (state,my) ->
    # 1) Put the best action you can't use back on deck
    putBackActions = []
    putBackActions = card for card in my.ai.actionPriority(state,my) when ( (card?) and (state.c[card].getActions() == 0) and (card in my.hand))
I strongly suspect (by experiment) that it is the "state.c[card].getActions() == 0", where card="Shanty Town". But that would mean that state.c would be undefined. state is not undefined, as state.log works two lines later...

putOnDeckPriority gets called by the generic  chooseByPriorityAndValue, so I can't believe that there is a wrong parameter for state or something.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 25, 2011, 06:26:39 pm
Try "state.cardInfo", which should be the same object as "c" is in cards.coffee. "state.c" actually is undefined.

I wrote it as "state.c" once in the documentation, but I thought I had fixed it by now.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 25, 2011, 07:07:16 pm
ah thanks.  Got rid of this error now, but still a long way I'm afraid.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 26, 2011, 05:17:36 am
ah thanks.  Got rid of this error now, but still a long way I'm afraid.

So got 1a) running afte splitting it up another time
Code: [Select]
    #1a) If no actions left, put back best Action

    #1b) If not enough actions left, put back best Terminal you can't play
b) shoud be easy now, but have to work. But I'm not sure if that's really what one want, as on top of the top of the actionPriorityList usually are Cantrips>Terminals, so one would put back an unplayable Village over an unplayable Mountebank.
On the other hands one of course can't just rate Terminals>Cantrips, cause that would put back an unplayable Woodcutter over Grand Market...

perhaps we really need another list for this...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 26, 2011, 11:18:24 am
Hmm. I don't think I'd want to set up a separate mailing list or anything -- this would make it harder for others to start working on the simulator. This forum is a good place for development discussion, I'd say, because it contains the majority of the people who would use this code.

But the other option for specific discussion about the code would be using GitHub's messaging interface. I'm also setting up the wiki, at https://github.com/rspeer/dominiate/wiki, as a place for more documentation and for development plans.

I just added code that will predict (pessimistically) how much money the player will have at the end of the turn, and what it intends to buy with that money, which can help in deciding when to put back treasure.

It's not so bad to prioritize putting back a Village when there are no actions left. If the simulator is running into a situation with too many terminals this turn, it may run into the same situation next turn, in which case the village will help. Of course there are many situations where this will be a suboptimal decision, but it seems a quite reasonable way to make the decision in the short time the simulator is supposed to spend per turn.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 26, 2011, 11:22:54 am
Hmm. I don't think I'd want to set up a separate mailing list or anything -- this would make it harder for others to start working on the simulator. This forum is a good place for development discussion, I'd say, because it contains the majority of the people who would use this code.
I was talking about another priorityList for which Action to put back on the deck. Actually like the forums here for discussion.

Quote
It's not so bad to prioritize putting back a Village when there are no actions left. If the simulator is running into a situation with too many terminals this turn, it may run into the same situation next turn, in which case the village will help. Of course there are many situations where this will be a suboptimal decision, but it seems a quite reasonable way to make the decision in the short time the simulator is supposed to spend per turn.
OK, I think I will keep it the way, one can always optimize later...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 26, 2011, 01:14:50 pm
I'd rather see a shortlist with the most critical actions and just derive the rest from the standard list.

This shortlist would contain Cursers while Curses last.

Maybe it can be a 3-pronged assault.
1. Pick a Curser from the shortlist if there are Curses left
2. Pick any other Attack (obviously suboptimal, because there are a lot of not so bad attacks)
3. Pick the highest card from the normal list
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DG on September 26, 2011, 03:08:08 pm
In my humble opinion, the Geronimo simulator is at a stage where its next main improvement would be the customization of card play rules within a simulation. he simulator already models card purchases very well and Geronimo is left to improve the heuristics, which will be an increasingly difficult and endless task. Moreover, any added complexity in the heuristics will make it more difficult for users to eventually change behaviours through simple parameter changes.

Is there any conceptual planning for this simulator as to how users could eventually alter the card play? Is this being considered in the current design?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 26, 2011, 03:13:48 pm
You can alter the card play.

Any of the methods on basicAI, such as actionPriority, discardPriority, or putOnDeckValue, can be overridden by a specific AI. It just happens that the one people are usually interested in overriding is gainPriority.

For one example, look at TournamentPlayer, which changes the discardPriority to avoid discarding Provinces when it has a Tournament.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 26, 2011, 06:28:18 pm
So, I think I've got it.

Found another bug in the PutOnDeck() I wrote, obviously it did not put it on the deck but under it or wherever. Found the transferCardToTop(), but don't like that it doesn't say something. However, here's my putOnDeckPriority

Code: [Select]
putOnDeckPriority: (state, my) ->
    # 1) If no actions left, put back best Action
    #    Take card from hand which are actions, sort them by ActionPriority
    #
     
    # 2) If not enough actions left, put back best Terminal you can't play
    #    Take cards from hand which are Actions and Terminals, sort them by ActionPriority
    #    Then, ignore as many terminals as you can play this turn, return the others
    #
     
    # 3) Put back as much money as you can
    #    First get a pessimistic estimate of the avaiable money this turn
    #    then find take the cost in coins of the highest priority card you can afford
    #    then put the treasures which are not needed in 'putBack' for discardPriority, most valuable first, Potion = 2.5 Coins
    #
      # Don't put last Potion back if Alchemists are in play
      #

    # 4) Put back the worst card (take priority for discard)
    #

There is a lot sorting and estimating hardcoded in the function now, maybe one wants to subroutine them for reuse.
AND the whole mess will only work when you want to put back exactly 1 card, and also if you only have one buy. Have to think again how to handle GhostShip...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 27, 2011, 08:37:48 pm
So, fixed some of the bugs I placed yesterday, as well as coded Haven. And found a bug with Potions, they where counted twice.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 27, 2011, 11:16:41 pm
I have Pirate Ship all done, except for pirateShipPriority. I have a really basic version of it done, but I think Geronimoo's method (http://dominionsimulator.wordpress.com/play-rules/seaside/pirate-ship/) is pretty good--I'm just not quite sure how to see if playing for coins will enable the player to buy a card higher on the gainPriority list, rather than just seeing what state.current.coins will be with the Ship's value.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 28, 2011, 12:25:47 am
So, fixed some of the bugs I placed yesterday, as well as coded Haven. And found a bug with Potions, they where counted twice.

It's up. And after I pointed out your copying bug, I found three more of my own, at which point I finally wrote a much simpler cloneDominionObject function that works on States and PlayerStates.

It's so much easier to say what not to copy than to list every single object that needs a new copy made of it.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 28, 2011, 12:36:45 am
I have Pirate Ship all done, except for pirateShipPriority. I have a really basic version of it done, but I think Geronimoo's method (http://dominionsimulator.wordpress.com/play-rules/seaside/pirate-ship/) is pretty good--I'm just not quite sure how to see if playing for coins will enable the player to buy a card higher on the gainPriority list, rather than just seeing what state.current.coins will be with the Ship's value.

This is what the hypothetical-situation code can be used for.

You'll want to do something almost like pessimisticCardsGained, an AI method that thinks ahead to the buy phase, assuming it won't draw any more money, and lists the cards it will gain then.

Code: [Select]
  pessimisticCardsGained: (state) ->
    newState = this.pessimisticBuyPhase(state)
    newState.doPlay()
    return newState.current.gainedThisTurn

But you'll want to get the pessimisticBuyPhase twice, and see what happens when you give it more money the second time. So, if I may write totally untested code to accomplish this on the forum, I think it would be something like this:

Code: [Select]
  effectOfMoneyChange: (state, moneyChange) ->
    state1 = this.pessimisticBuyPhase(state)
    state2 = state1.copy()
    state1.doPlay()
    gains1 = state1.current.gainedThisTurn
    state2.current.coins += moneyChange
    state2.doPlay()
    gains2 = state2.current.gainedThisTurn
    return (gains1.toString() != gains2.toString())

This could even take a negative money change for evaluating Remodel, Salvager, etc.

Maybe it should just compare the card costs instead of the actual cards, so that it doesn't break with SillyAI.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 28, 2011, 12:40:59 am
Thief and Pirate Ship both are done now. Both will trash the opponent's most expensive treasure, using trashOppTreasureValue for the decision (right now it just uses the cost), and Thief will gain the treasure if the bot wants to gain it.

pirateShipPriority is pretty lame right now, but I don't how to best write the heuristic for when to use it. Right now it will use the coins if there are 5 or more, and using them will result in state.current.coins >= 8, otherwise it attacks. I'm not sure how to see if it will be able to afford a card in gainPriority with a higher spot than Pirate Ship (like Geronimoo's).

So the basic functionality of Pirate Ship is done, but the AI part needs work. I'm beginning to think the best way to write a particular bot with these complex decision cards is probably going to involve manually overwriting the relevant card Priority functions and the actionPriority function.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 28, 2011, 03:13:33 am
How does Pirate Ship work with Reactions?

On Isotropic Reaction cards are revealed after the attack card is played and before a choice is made.
This is key for Pirate Ship, because if you can't steal, you want the $$$ obviously.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 28, 2011, 03:17:25 am
This is what the hypothetical-situation code can be used for.

So when I get this right, this could also be used in my PutOnDeckPriority to find out how much money the bot would like to spend, saving me a ton of "for  in  where ( and and and and)" and handeling multiple buys.

The only question is if that is really what one wants, because with 2 buys and $11 he would buy Province/Silver instead of Province, putting Gold back, which would be the better move in endgame. But probably thats also a situation that the gainPriority must account for when playing with multiple buys anyway, so maybe we can just shift the problem to that point. Negative point for this is that gainPriority is probably the function most often change by users, so we maybe don't want such unexpected side-effects.

PS: @array: So just if it where C. Think I can rememer that.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 28, 2011, 05:12:33 am
Thief, Haven, and Pirate Ship are in. But this putOnDeckPriority code is really confusing and hard to read. Can I ask nicely for some line breaks and intermediate variables?

Object identities are confusing! There was some new bug with copied AIs that I still can't figure out, and it would show up every time someone played a Bureaucrat; the hypothetical opponent being asked to discard wasn't in the game somehow.

It bothers me, but I'm going to have to have AIs hypothesize about how their opponents play hypothetical situations using the actual opponent AIs for now. (That's kind of cheating, and it doesn't work if in some future time the opponent is a human...)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 28, 2011, 05:51:36 am
Thief, Haven, and Pirate Ship are in. But this putOnDeckPriority code is really confusing and hard to read. Can I ask nicely for some line breaks and intermediate variables?
Think I will rewrite it (maybe this evening) with the hypothetical ai mentioned.

Can also split it up a bit, in the beginning I thought I could not afford intermediate variables because they would mess with the list I return, but maybe I also don't really understand the language yet. The way it is done now definitely allows for more variables.

The other thing that I think is not nice to read is the sorting of the treasures. So either I introduce a subfunction there, or maybe just sort them my price. Is perhaps not the worst idea.

Linebreaks I can do anywhere I want by just ending the line with a  \   ?

Edit: I realize that anyway I need to think more about the Priority of putting back Quarry, Talisman, Royal Seal, maybe Stash and some fancy treasures I might have forgotten.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on September 28, 2011, 06:32:50 am
Harem is a fancy treasure, especially for Thief.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 28, 2011, 09:27:06 am
So I think I will reevaluate the putting back of treasures
Code: [Select]
# A) Look what you would gain if you just put back as if you discard (that is the fallback if everything we try now fails)

# B) For each unique treasure, test if the gain changes if we just put this treasure back

# C) Extraconditions like Potions for Alchemist, Royal Seal which have effects other than gaining

# D) Put the "best" treasure back that does not change the gain or was excluded in C).
This should also be able to handle Quarry, Talisman, HoP.

Now we just have to evaluate what "best" means, first idea would just be by price. What I don't like there
Code: [Select]
Harem > HoP, Royal Seal
Harem, Royal Seal, Stash > Quarry, Talisman, Potion
Diadem < all
Harem should be more or less rated like silver, perhaps an epsilon higher to defend against attacks. But that's only a small chance in the turn just before the reshuffle, which can more or less be ignored. But when you bought HoP, a reasonable AI should want to gain something with it in the end, so it should be more valuable than silver and thus as Harem.
Same should be true for Royal Seal, Stash vs. Quarry, Talisman, Potion while here maybe in the endgame it is shifted again in Royal Seals favour.
Second idea would be a new function treasurePriority2(state) (which exists, but for other means), which has just a defaultList (without much thought and probably forgotten something)
Code: [Select]
Bank>Platinum>Gold>HoP>Quarry>Talisman>Potion>Diadem>Royal Seal>Stash>Harem>Silver>Copper
and which of course could be costumized then if someone wants something more fancy.  Most of the inequalities are not so important anyway, you seldomly want to play say Talisman and Potion in the same strat.
Royal Seal then also needs some extra considerration if we want to put it back at all , but that is a different point similar to "do not put back Potions when Alchemists are in play".

Edit: Contraband I forgot. And Hoard. Hoard should work with this, Contraband is difficult anyway.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on September 28, 2011, 01:11:20 pm
How does Pirate Ship work with Reactions?

On Isotropic Reaction cards are revealed after the attack card is played and before a choice is made.
This is key for Pirate Ship, because if you can't steal, you want the $$$ obviously.

Hadn't thought of that. Right now it probably just makes the same choice either way.

For 2p it would be a simple enough task, but I'm wondering about how best to do it for multiplayer--if all but one are protected, do I still want to attack? Should I consider the opponent's deck's treasure density and calculate the chance of a successful attack?

I think this code would cause the player to choose coins if any opponent reveals Moat (or has a Lighthouse), so it would should be fine for 2p but probably not best for multiplayer.

Code: [Select]
pirateShipPriority: (state, my) -> [
  'coins' if opp.moatProtected for opp in players[1...]
  .
  .
  .
]

Of course, a check for Secret Chamber should probably be made as well, but it seems like that would have to be a bit more complicated...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 28, 2011, 02:10:23 pm
Found a bug with the output, and don't really now how to resolve it:

When going into hypothetical scenarios, the log-functions of GameState test for the depth of the hypotheticalliness and only outputs if we are in "the real world". But there also is a log-function of Playerstate, which is called by the basic drawCards, discardFromDeck etc. functions of playerstate, and which does not test on "real world". And I think it can't, because the player state does not know if the depth.

Tried to introduce @depth also in class PlayerState, but didn't succeed.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 28, 2011, 02:12:47 pm
The hack I was doing to resolve this was to have state.hypothetical simply replace the log functions of its PlayerStates with no-ops when it created them.

It's possible that introducing cloneDominionObject broke this somehow.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 28, 2011, 05:19:52 pm
Is it possible that there are more things messed up with the copying? While testing my new code for putBackPriority, it seems like the hypothetical versions of the AIs lose some cards when discarding. I have the following:

Bot:
Code: [Select]
gainPriority: (state, my) -> [
    "Potion" if my.countInDeck("Potion") < 2
    "Alchemist" if my.countInDeck("Alchemist") < 4
    "Village" if my.countInDeck("Village") < 3
    "Courtyard" if my.countInDeck("Courtyard") < 3
    "Silver"
We play a Courtyard and think about what to put back, the hand contains 6 Coppers, 2 Potions and some Estates:
Code: [Select]
for card in treasures
        [hypState, hypMy] = state.hypothetical(my.ai)
        hypMy.doDiscard(card)
        nowGained = hypMy.ai.pessimisticCardsGained(hypState)
When putting back Copper, it says it would gain a Village. Which sounds reasonable.
When putting back Potion, it says it would gain a Potion(!), Which sounds not reasonable at all, since we've already got 2 Potions. So it seems like the doDiscard somehow loses the Potion, at least in the hypothetical world.

Or I'm using the hypothetical( ) wrong.

Edit: Furthermore I get something like: I have a hypothetical hand of Estates and 3 Coppers (shown by state.log("#{hypMy.hand}"), and it says it would buy a Quarry with it.

Edit2: Complete code is on Github in case you need it.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 28, 2011, 09:08:43 pm
I think the theme of today is "cloneDominionObject screwed up everything".

I backed it out; the big, huge functions that explicitly copy States and PlayerStates are back instead. I wish I had test cases.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on September 29, 2011, 04:51:36 pm
I think the theme of today is "cloneDominionObject screwed up everything".

I backed it out; the big, huge functions that explicitly copy States and PlayerStates are back instead. I wish I had test cases.

Actually found out that the problems with hypothetical discarding didn't come from the copying, but was in the code of pessimisticBuyPhase. You just deleted the draw and the discard there to be pessimistic, so that the deck was not correct anymore when the ai enters the hypothetical buy phase.
Made a backup of them and restore them just before entering the buyphase.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on October 01, 2011, 12:04:56 am
This isn't really anything important, but I was thinking of a couple more ways cards.coffee could be divided--right now it's organized into basic cards, vanilla cards, duration cards, trash for improvement, and all the rest. I was thinking it would also be nice to have separate categories for the Victory and Treasure cards, and maybe Attacks as well. It'd be an easy enough thing for me to do on my own, but if there's some reason this would be a bad idea I wouldn't do it.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Davio on October 03, 2011, 10:55:26 am
It's not that it's a bad idea, it's just that there are 100+ cards and no one cares enough to remodel the file.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on October 06, 2011, 11:23:00 pm
...no one cares enough to remodel the file.

Evidently I do :P I have trashed it and replaced it with a file costing $2 more. Or something. At least, I changed it so Treasures and Attacks were separated and given their own categories and prototypes.

Fairgrounds is back in (or there for the first time?), I fixed few other minor things (Trade Route wasn't trashing a card, Bureaucrat not gaining a Silver), and implemented Loan, Talisman, and Fortune Teller.

I also added a dig function (http://forum.dominionstrategy.com/index.php?topic=121.msg1163#msg1163). Looks like Golem and Scrying Pool are the only cards left to code that would use it, but there are a few more cards that are done which could be rewritten to incorporate it: Adventurer, Farming Village, and Hunting Party.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on October 10, 2011, 12:30:53 am
Cool. By the way, sorry that I'm not very active on this project around now: I have a huge project that I have to release this week.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on October 10, 2011, 05:57:23 pm
Totally understandable. I've been having fun contributing but I should probably be focusing more on schoolwork :P (college senior, math major)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ivadla on October 12, 2011, 06:02:53 pm
Is it just me or is dominiate very slow compared to Geronimoo's simulator? On my computer dominiate takes 195 seconds to simulate 1000 games between BigMoney and BigSmithy. Geronimoo's simulator only needs 1.6 seconds and jdominion 20 seconds.
I ran this on an old 1.5 Ghz Pentium-M with Firefox 7 and Java 1.6.0.26

Is it possible to optimize Dominiate? Or does it run faster with node.js or another js-engine?
With the current speed it seems very difficult to really optimize strategies.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rrenaud on October 12, 2011, 06:16:43 pm
Chrome seems to be about 3x faster than firefox when I count in my head.

Firefox takes about 30 seconds for 100 games, chrome about 10.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: danshep on October 12, 2011, 06:35:33 pm
I keep meaning to dive into the code and try this myself, but have you tried making a null logging device so that when playing games in bulk it doesn't add all that extra DOM manipulation that the game logs require?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on October 14, 2011, 03:04:24 pm
That makes a lot of sense, and there are probably also still things that can be optimized.

Running the Chrome profiler identifies three major hotspots, when running on simple strategies (Chapel/Mountebank vs. Bank/Wharf)

I'm curious about the implications of (program) being so high -- that's the browser's JS environment itself. Maybe the only way to improve that is to keep updating Chrome, or maybe it's an indirect effect of something actually caused by this code (perhaps all the DOM updates we're doing? A no-logging mode is a good idea.)

But then chooseByPriorityAndValue is also a clear thing to improve. This calls some code that makes actual difficult decisions, but it's interesting that it spends so much time in that function itself when it's mostly just looking up values and comparing numbers. Are we calling it too many times? Are we calling it with too many options that we should be pruning?

I intend to get back to this code soon, maybe later tonight, and I'll take a shot at optimization.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on October 15, 2011, 04:04:54 am
All right, Fast Mode is in. In Fast Mode, there are many fewer DOM updates, you don't get any gameplay logs, and it returns control to the browser much less often.

It runs about twice as fast as before in Chrome (apparently DOM updates are pretty damn fast in Chrome, which is why it hadn't bothered me much), and in Firefox it runs considerably faster, about as fast as Chrome does in slow mode now.

It's possible that we should default to a mode that has some of the features of fast mode, except you get at least one gameplay log.

I was going to implement some new cards, but now I've changed my plans; I'm going to go on Isotropic and buy as many Crossroads as I possibly can.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on October 17, 2011, 05:15:43 am
I've started implementing some Hinterlands cards, and also fixing bugs. Mandarin, Nomad Camp, Crossroads, and Border Village are in.

It's no test suite, but I made a command-line tester to play SillyAI against itself for 1000 games. It's now run several times without crashing. I think the Watchtower bug (currently the only actual bug on the GitHub queue) might have even been fixed by some other change.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: michaeljb on October 19, 2011, 01:54:40 pm
I've coded Golem, Farmland, Silk Road, and Tunnel. I still need to implement Tunnel's reaction, and then I'll request a pull. I'll probably do Pearl Diver too, to finish off the "easy" card list.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on November 03, 2011, 08:40:48 am
When I want to use the webinterface (say http://rspeer.github.com/dominiate/play.html#DoubleJack/DoubleMilitia), I get an error message:
Code: [Select]
can't convert undefined to object
on Firefox 7.0.1
and
Code: [Select]
Array.prototype.indexOf called on null or undefined
on Chrome/Chromium 15.0.874.106

The game log stops at
Code: [Select]
(DoubleMilitia shuffles.)
DoubleMilitia draws 5 cards: [Copper, Copper, Copper, Copper, Copper].
(DoubleJack shuffles.)
DoubleJack draws 5 cards: [Estate, Copper, Estate, Copper, Copper].
Tableau: [Jack of All Trades, Militia, Vault, Ambassador, Noble Brigand, Bureaucrat, Sea Hag, Philosopher's Stone, Wharf, Trading Post, Potion]

== DoubleMilitia's turn 1 ==
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on November 03, 2011, 12:05:43 pm
Fixed.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Toskk on November 04, 2011, 04:24:27 pm
Is it possible for the AI strategies in Dominiate to access the turnsTaken variable? I'm working on optimizing a few buy decisions, and knowing how many turns have passed already could be very helpful.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on November 04, 2011, 04:33:33 pm
Yep. It's a variable on the PlayerState, so you access it with "my.turnsTaken".
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Toskk on November 04, 2011, 04:36:59 pm
Excellent, thanks. :)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Toskk on November 04, 2011, 07:13:19 pm
Ok, one more question.. the function my.numCardsInDeck().. is that returning the number of cards in the deck *and* hand and discard pile (the sum of all cards the player owns), or just the number of cards actually in the player's deck (not including those in hand or in the discard pile) at that moment? If it's the latter, is there some function to determine the total number of cards in deck, hand, and discard pile?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on November 05, 2011, 05:11:48 am
In the code of Dominiate, I try to use "deck" to refer to all the cards that will be counted at the end of the game, and I call the pile you draw from the "draw pile". I realize I haven't entirely been consistent, but it's better than the rules, which don't distinguish them at all.

The deck in Dominiate is currently defined as the contents of your draw pile, discard pile, hand, cards in play, cards set aside, cards under Havens, native village mat, and island mat. Come to think of it, maybe the island mat shouldn't actually count, and my.getVP() should instead count your deck plus your island mat.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Qvist on November 23, 2011, 07:36:42 am
So, now I tested Dominiate and I must admit, it's great. Kudos, great work.

Here's a bot, I did not get to work for Geronimoo's Simulator and it works quite well as it beats Double Jack for instance:
Code: [Select]
{
  name: 'Mint + Fool\'s Gold'
  author: 'Qvist'
  requires: ["Mint", "Fool's Gold", "Steward"]
  gainPriority: (state, my) -> [
    "Province"
    "Duchy" if state.gainsToEndGame() <= 5
    "Estate" if state.gainsToEndGame() <= 2
    "Mint" if my.countInDeck("Mint") == 0 && my.countInPlay("Copper") >= 4
    "Steward" if my.countInDeck("Steward") == 0
    "Fool's Gold"
  ]
}

But I see still some poor decisions.
As I understand it right you can basically program your AI here as complex as you want by overriding the respectice methods which is very nice for a programmer like me. But I have no experience with CoffeeScript. I looked into your code and understand it most of the times, but I couldn't understand benefitValue for example. As I understand it right choice cards like Steward use it. I don't know how this function works, but it seems to make wrong decisions. Maybe you can either help me to find the reason for these following issues or you can explain me the benefitValue method or you can explain me how to override it.

Here are the problems:
Hand: Mint, Steward, Fool's Gold, Fool's Gold, Fool's Gold
I have enough money for a Province, so normally I would mint a Fool's Gold. But the AI takes the +2$ from Steward.

Hand: Mint, Steward, Province, Fool's Gold, Fool's Gold
I have not enough money for a Province, so normally play the Steward and hope to draw another Fool's Gold. But the AI takes the +$2 from Steward although I have no card for $6 or $7 in my gainPriority.

Can you help me?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on November 23, 2011, 08:00:00 am
So, now I tested Dominiate and I must admit, it's great. Kudos, great work.

Here's a bot, I did not get to work for Geronimoo's Simulator and it works quite well as it beats Double Jack for instance:
Code: [Select]
{
  name: 'Mint + Fool\'s Gold'
  author: 'Qvist'
  requires: ["Mint", "Fool's Gold", "Steward"]
  gainPriority: (state, my) -> [
    "Province"
    "Duchy" if state.gainsToEndGame() <= 5
    "Estate" if state.gainsToEndGame() <= 2
    "Mint" if my.countInDeck("Mint") == 0 && my.countInPlay("Copper") >= 4
    "Steward" if my.countInDeck("Steward") == 0
    "Fool's Gold"
  ]
}

But I see still some poor decisions.
As I understand it right you can basically program your AI here as complex as you want by overriding the respectice methods which is very nice for a programmer like me. But I have no experience with CoffeeScript. I looked into your code and understand it most of the times, but I couldn't understand benefitValue for example. As I understand it right choice cards like Steward use it. I don't know how this function works, but it seems to make wrong decisions. Maybe you can either help me to find the reason for these following issues or you can explain me the benefitValue method or you can explain me how to override it.

Here are the problems:
Hand: Mint, Steward, Fool's Gold, Fool's Gold, Fool's Gold
I have enough money for a Province, so normally I would mint a Fool's Gold. But the AI takes the +2$ from Steward.

Hand: Mint, Steward, Province, Fool's Gold, Fool's Gold
I have not enough money for a Province, so normally play the Steward and hope to draw another Fool's Gold. But the AI takes the +$2 from Steward although I have no card for $6 or $7 in my gainPriority.

Can you help me?

Hi. I'm not as into all of this as rspeer, so maybe he corrects me, but afaiu:
You should be able to overwrite every function by just defining it in the same file as the gainPriority. The file you are writing defines a new class "XYZ-AI" derived from the basicAI-class, you can just redefine every function, as you already do with the gainPriority (which is also defined in basicAI.coffee). I think there is much potential (possibly also for speed) by just defining your own actionPriority, as the standard one returns a very long list, because it has to cover all possible cards, and not the 3-10 you usually care for.

In you're example (very easy case, probably you have to be a litte more sophisticated):
1) C&P the actionPriority from https://github.com/rspeer/dominiate/blob/de69485f38af8f0be78e4f2fb984bcfbeb6fb238/basicAI.coffee
2) [optional, but strongly recommended, for performance and readability] Delete every card you don't care for
3) Think about which card you want to play in which situation and list them in the same way as you do with buyPriority.  In your case probably something like
Code: [Select]
actionPriority: (state, my, skipMultipliers = false) -> [
  "Mint" if $functionThatTellsMeHowMuchMoneyIsInMyHand>=8
  "Steward"
  "Mint"
]
getting the right choice for Steward might be a little bit more difficult. The relevant function is benefitValue(state, choice, my) [in the same file]. You might want to try to lower the value for coins, or increase it for draw under certain conditions.

Edit: You might also want to change the MintValue-function, as at the moment it decides what to mint from the price, so minting silver over Fool's Gold. Something like
Code: [Select]
mintValue (state, card, my) ->
  mv = card.cost
  if c[card]=="Fool's Gold" mv=4
  return mv
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Qvist on November 23, 2011, 09:30:54 am
Thanks for the advice.
It already helped me a lot.

So I edited some functions for this bot and it already beats most of the other implemented ones.

Code: [Select]
{
  name: 'Mint + Fool\'s Gold'
  author: 'Qvist'
  requires: ["Mint", "Fool's Gold", "Steward"]
  gainPriority: (state, my) -> [
    "Province"
    "Duchy" if state.gainsToEndGame() <= 5
    "Estate" if state.gainsToEndGame() <= 2
    "Mint" if my.countInDeck("Mint") == 0 && my.countInPlay("Copper") >= 4
    "Steward" if my.countInDeck("Steward") == 0
    "Fool's Gold"
  ]
  actionPriority: (state, my, skipMultipliers = false) -> [
    "Mint" if this.pessimisticMoneyInHand(state)>=8
    "Steward"
    "Mint"
  ]
  trashPriority: (state, my) -> [
    "Curse"
    "Potion"
    "Estate" if state.gainsToEndGame() > 4
    "Copper" if my.getTotalMoney() > 4
    "Estate" if state.gainsToEndGame() > 2
    "Silver"
  ]
  benefitValue: (state, choice, my) ->
    cardValue = 2
    coinValue = 1
    trashValue = 4      # if there are cards we want to trash

    if my.ai.wantsToTrash(state) < (choice.trash ? 0) || my.getDeck().length <= 5
      trashValue = -4
    if this.pessimisticMoneyInHand(state) >= 8
      cardValue = -2
      coinValue = -1
    else if this.pessimisticMoneyInHand(state) >= 6
      cardValue = -2
     
    value = cardValue * (choice.cards ? 0)
    value += coinValue * (choice.coins ? 0)
    value += trashValue * (choice.trash ? 0)
    value

}

But there's still one thing I'm missing that's making problems. The benefitValue seems to only trigger after already playing it. I'd like to check benefitValue before choosing to play it.

Something like that:
Code: [Select]
actionPriority: (state, my, skipMultipliers = false) -> [
    "Mint" if this.pessimisticMoneyInHand(state)>=8
    "Steward" if benefitValue>0
    "Mint"
  ]

Is this possible?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on November 23, 2011, 09:58:50 am
So I edited some functions for this bot and it already beats most of the other implemented ones.
Some remarks:
You probably want to use my.getAvailableMoney() instead of pessimisticMoneyInHand() in gainPriority. The latter is written for use during the actionphase, where you have to guess how much money you will end with after the turn, while when you buy something, you are already in the buyphase and know how much money you have. So the function is much easier there.

Quote
But there's still one thing I'm missing that's making problems. The benefitValue seems to only trigger after already playing it. I'd like to check benefitValue before choosing to play it.

Something like that:
Code: [Select]
actionPriority: (state, my, skipMultipliers = false) -> [
    "Mint" if this.pessimisticMoneyInHand(state)>=8
    "Steward" if benefitValue>0
    "Mint"
  ]

Is this possible?
benefitValue wants a choice as parameter. So if I see it correctly, you should use
Code: [Select]
  "Steward" if benefitValue(state, [{cards: 2}, {coins: 2}, {trash: 2}], my) > 0
Don't know if it that can be done more elegantly.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Qvist on November 23, 2011, 10:08:33 am
So I edited some functions for this bot and it already beats most of the other implemented ones.
Some remarks:
You probably want to use my.getAvailableMoney() instead of pessimisticMoneyInHand() in gainPriority. The latter is written for use during the actionphase, where you have to guess how much money you will end with after the turn, while when you buy something, you are already in the buyphase and know how much money you have. So the function is much easier there.

Thanks for the tip, but that doesn't work for Fool's Gold as I've already tried that. That function only counts the coins which are defined in the card, which is 1 for Fool's Gold. So I have to simulate all cards already have been played, for that I have use pessimisticMoneyInHand() or write a new function. But pessimisticMoneyInHand() does its job.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on November 23, 2011, 10:18:52 am
So I edited some functions for this bot and it already beats most of the other implemented ones.
Some remarks:
You probably want to use my.getAvailableMoney() instead of pessimisticMoneyInHand() in gainPriority. The latter is written for use during the actionphase, where you have to guess how much money you will end with after the turn, while when you buy something, you are already in the buyphase and know how much money you have. So the function is much easier there.

Thanks for the tip, but that doesn't work for Fool's Gold as I've already tried that. That function only counts the coins which are defined in the card, which is 1 for Fool's Gold. So I have to simulate all cards already have been played, for that I have use pessimisticMoneyInHand() or write a new function. But pessimisticMoneyInHand() does its job.

Oh, you are right. But there should be a method at this point, the treasures are played. I will have a look.

Edit: Probably it's just my.coins ?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on November 23, 2011, 06:06:32 pm
my.coins is right for counting treasures (and +$ actions) that are already played, and Qvist is correct that pessimisticMoneyInHand() is the only way to count treasures you haven't played yet when choosing an action.

Would it be useful for other things as well, if we updated getAvailableMoney() to count things like Bank and Fool's Gold appropriately? It'd still have to treat Venture as if it were a copper or silver, but the other treasures can be improved.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on November 24, 2011, 02:57:07 am
my.coins is right for counting treasures (and +$ actions) that are already played, and Qvist is correct that pessimisticMoneyInHand() is the only way to count treasures you haven't played yet when choosing an action.
That's right, but I in gainPriority, they should have all been played. In the decision for the Steward, you need pessimiticMoneyInHand()

Quote
Would it be useful for other things as well, if we updated getAvailableMoney() to count things like Bank and Fool's Gold appropriately? It'd still have to treat Venture as if it were a copper or silver, but the other treasures can be improved.
I don't want to look up the code now, but from what I remember, would that not exactly end up with pessimisticMoneyInHand()? AFAIR, pessimisticMoneyInHand() gives you the amount of $ you would end up with if you would just play everything you have, and draw nothing in this process. That is about what you would have to do if you want to improve getAvailableMoney().
Or you could even improve this (by finding at least as many Coppers as you have with the Ventures for example), but then you could also improve pessimisticMoneyInHand.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on November 24, 2011, 07:36:49 am
Well, for one thing, getAvailableMoney is way faster than pessimisticMoneyInHand.

The main difference would be that it wouldn't take into account if you have actions remaining and +$ action cards in your hand.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Jorbles on November 24, 2011, 02:46:36 pm
I've coded Golem, Farmland, Silk Road, and Tunnel. I still need to implement Tunnel's reaction, and then I'll request a pull. I'll probably do Pearl Diver too, to finish off the "easy" card list.

Was going to say I found a bug in Tunnel, but it seems that it's just not coded yet. (or maybe it is and it just hasn't been moved into the newest build). Anyhow I guess I will have to wait to try my Venture, Tunnel, Moneylender bot (see below). Love the simulator now that I've started playing with it.

Code: [Select]
#VentureTunnelMoneylender
{
 name: 'VTM'
 author: 'Jorbles'
 requires: ['Venture', 'Tunnel', 'Moneylender']
 gainPriority: (state, my) -> [
   "Colony" if my.countInDeck('Platinum') > 0
   "Province" if state.countInSupply('Colony') <= 6 \
              or state.countInSupply('Province') <= 6

   "Duchy" if 0 < state.gainsToEndGame() <= 5
   "Estate" if 0 < state.gainsToEndGame() <= 2
   "Platinum"
   "Venture" if my.countInDeck('Tunnel') >= 1
   "Gold"
   "Venture"
   "Moneylender" if my.countInDeck('Moneylender') == 0
   "Silver" if my.countInDeck('Silver') < 1
   "Tunnel"
 ]
}
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on November 24, 2011, 03:39:02 pm
On github it seems fully implemented. what is the bug?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Jorbles on November 24, 2011, 05:15:27 pm
Really? Because when I try it, there seems to be no reaction on discards (ie. discarding Tunnels doesn't cause Gold gains, which it should default to).
For example:
Code: [Select]
== VTM's turn 12 ==
VTM plays Silver.
VTM plays Copper.
VTM plays Copper.
VTM plays Venture.
...VTM reveals [Tunnel, Tunnel, Copper].
...VTM discards [Tunnel, Tunnel].
...playing Copper.
Coins: 6, Potions: 0, Buys: 1
VTM buys Venture.
VTM draws 5 cards: [Estate, Venture, Moneylender, Tunnel, Tunnel].
Maybe the trigger for the reaction isn't set up for this kind of discard?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on November 25, 2011, 01:48:33 am
Maybe the trigger for the reaction isn't set up for this kind of discard?
Yepp. Seems like the function "dig", which is called by Venture does not call the function "handleDiscard", which cares for the reaction.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on November 25, 2011, 05:02:56 am
Fixed.

When I changed the discarding code to check for discard reactions, I forgot to change dig because I was mostly looking in cards.coffee.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on November 25, 2011, 10:55:10 am
@performance:

I just tested my hypothesis that producing manual actionPriorities would fasten the simulator, and for JoaT:BankWharfs in Chromium fast mode I get 1000 games from 24secs down to 14 secs. So my question:
Do you see any possibility to let the simulator compile a custom actionPriority before starting based on the one in basicAI.coffee, stripped to the cards that are specified in buyPriority? Or at least in requires?
In loadStrategy (play.coffee) you overwrite with "ai[key] = value" by what is specified in the browser. Now if we could treat the function actionPriority (from basicAI.coffee) as a string, is might be possible to overwrite ai[actionPriority] by something which we calculate at runtime? If that's true, than we might condense the actionPriority to the cards that really are listed in buyPriority.

Possible issues: Swindler?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on November 28, 2011, 12:05:06 pm
So I tried what I proposed, and in principle it works. There is a little problem I don't know how to solve:
The function I may modifie at runtime is already compiled to Javascript, so the code does not looking so nicely anymore. It basically is
Code: [Select]
return [my.menagerieDraws() === 3 ? "Menagerie" : void 0, my.shantyTownDraws(true) === 2 ? "Shanty Town" : void 0, my.countInHand("Province") > 0 ? "Tournament" : void 0, wantsToPlayMultiplier ? "Throne Room" : void 0, wantsToPlayMultiplier ? "King's Court" : void 0, state.gainsToEndGame() >= 5 || (_ref = state.cardInfo.Curse, __indexOf.call(my.draw, _ref) >= 0) ? "Lookout" : void 0, "Cartographer", "Bag of Gold", "Apothecary", "Scout:",
so basically a list. I tried to split the string at "," to get the single entries, which also works quite well, the only problem is expressions like
Code: [Select]
(_ref = state.cardInfo.Curse, __indexOf.call(my.draw, _ref) >= 0) ? "Lookout" : void 0
which gets ripped apart in the __indexOf.call-function.  Is there any easy way to get around this, so say split the string at ",", conditioned on no open brackets?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: danshep on November 28, 2011, 07:05:07 pm
I think what you want to be doing there is creating a method that returns action priorities only for cards in the supply.

{{{
  defaultActionPriority: (state) -> [
    ((state, my) -> "Menagerie" if my.menagerieDraws() == 3 ) if state.countInSupply("Managerie") > 0
    ((state, my) -> "Shanty Town" if my.shantyTownDraws(true) == 2 ) if state.countInSupply("Shanty Town") > 0
    ... etc ...
  ]
}}}

And then, you compile that once into an array of functions that only includes the actions available (I'm guessing countInSupply is wrong there). Then you'll have a much shorter array to call.

Actually, all the choice functions would work better if they were functions, so that you could short-circuit the function as soon as it hits a valid choice, rather than compiling it all into a 100 element array that may never get the last 99 elements read.

Just changing the chooseByPriorityAndValue method would allow all the choices in choice arrays to be wrapped in functions to be lazily evaluated:

{{{
      for preference in priority
        if preference of function
          preference = preference.bind(this)(state, my)
        if preference is null and null in choices
          return null
        if choiceSet[preference]?
          return choiceSet[preference]
}}}





Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on November 29, 2011, 03:11:46 am
Okay, I don't follow what danshep just did, but I agree that lazy evaluation would be a great thing if we could get it without harming the readability of the strategies.

I think I do understand what DStu wants to do, but trying to reverse-engineer things from the JavaScript of the function is probably going to be a horrifying way to do it.

A thought I had after trying to sort out DStu's post is that we could have strategies define a shorter version of actionPriority that uses only their preferred cards, and fall back on the long one if they get a card swindled (or masqueraded) into their deck that's neither a basic card nor in their "requires" list.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on November 29, 2011, 04:14:27 am
With the Javascript it's actually not that bad. There is a bunch of code at the beginning for KC/TR that I have ignored until now,  but that's just one block that you take or leave depending on KC/TR in the deck.
There are the preprocessed functions at the beginning which one could just also always take, or we don't do preprocessing anymore, as in the stripped function it will have no benefit, once it works.

Ignoring these two (solvable) points, you have to  process the last important line of JS, where the array is constructed. Splitting it at "," almost really works, there are I think only 6 lines (of two different types) where it fails because there's a comma in a function. If you don't care about them (I tried JoaT vs Wharf, where you don't have the problems), my (say) 10 lines of code already work.
The long time problem is of course to keep this parsing up to date if the actionPriority changes, and to notice errors once they occur.

PS: Have not read danshep in detail, but that also sounds interesting.

Edit: In short what I want to do, as I now really now what it is:
When generating a new strategy in play.coffee, to define the actionPriortiy of this bot, I want to take the actionPriority-function from basicAI.coffee, and delete all lines from the list that are not used by the bot (not listed in "requieres"). This can work as you can handle the function as a string, but it's already Javascript and not Coffeescript anymore, especially they are now all in one single line, seperated by ",". Problem is that this seperations are not the only ","s in the string.

Edit2: Perhaps I should parse the string lowlevel char for char. Then I can just count braces, or handle them recursively, which is not really difficult as I don't have to understand anything and just identify the parts between two "real" ","s. And performance should not be important at this part, because this is only done twice per run.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on November 29, 2011, 06:40:14 am
What we gain in speed that way, we lose in inscrutability. When the code is clear and accessible, it invites people to join the project.

Here's another suggestion. Let's just replace the default action priority list with a priority value function, which delegates to a method on each relevant card. Then only the cards in hand will be evaluated. Plus, we get to define this on the card itself (much like Geronimoo does), and this gives us a nice hook for letting people define variant cards and test them.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on November 29, 2011, 06:53:35 am
I don't think that the code would be a mess, and for most part of the project, you could ignore it.
But of course hacky modification of written code is somehow dangerous, especially in the long run if you are not totally clean. And "clean" probably then means really consider everything that JS can present you, which certainly I can't.

So your idea would be to give each card a value (probably function) that calculates its playPriority.
You would have to modify the card to modify the priority?

That might work. I also think that it's much easier to do little changes with this function, as to do small modifications, say exchange the priority of two cards would be much easier, as you don't have to rewrite the whole code for actionPriority (which would be especially funny if you want to keep the KC/TR-code), but only need to edit these two cards and exchange their playPriority.

Edit: Probably you could also have both a function and a value, as the value is easier to modify, and the function could be defaulted to
Code: [Select]
  priorityFunc (my, state) ->
    return priorityValue

Edit2: I haven't read your code for KC/TR. Does this work with this concept?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: danshep on November 29, 2011, 06:02:59 pm
I'll try and find time to turn my mangled explanation into working code. It's not as complicated as I make it sound.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on December 01, 2011, 12:54:24 pm
Ok, than I will not mess around with this yet. And rspeers proposal is probably a big change, best done by himself.

Another topic: http://forum.dominionstrategy.com/index.php?topic=144.msg17103#msg17103
I bragged that I can do it in 4 lines of code in this sim (Actually it would be 2 if the 10 starting cards would be defined in 1 line and not 2 for readability...).

Is this interesting somehow. I think one really only must take
Code: (gameState.coffee line 19) [Select]
@discard = [c.Copper, c.Copper, c.Copper, c.Copper, c.Copper,
                c.Copper, c.Copper, c.Estate, c.Estate, c.Estate]
and replace the array by a function from the ai, like
Code: [Select]
@discard = ai.startingDeck()
And define the standardDeck in
Code: (basicAI.coffee line XYZ) [Select]
startingDeck () ->  [c.Copper, c.Copper, c.Copper, c.Copper, c.Copper,
                             c.Copper, c.Copper, c.Estate, c.Estate, c.Estate]
Then anybody could overwrite the startingDeckFunction as he wishes.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Jorbles on December 15, 2011, 08:25:25 pm
You know what would be a great feature that I don't think would be very hard to add? A piece of data that shows the average/median turn a game ends on after a simulation has been run. What do other people think?

I tend to think of strategies as being good/bad based on how fast they are and I know it would depend on your opponent's strategy, but if you play a strategy against itself it would let you know how fast the strategy is compared to others.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on December 22, 2011, 03:03:48 am
I have a branch where I'm assigning values to everything in the actionPriority list. It's slow going because it's quite tedious and requires jumping all around cards.coffee while trying to remember what three-digit number I was on.

Showing the median turn a game ends on would be a great idea. Especially if it can be shown on the same graph as the average VP -- put a vertical line at the median game length, maybe even shade in from the 25th to 75th percentiles.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ecq on December 27, 2011, 09:21:11 pm
I'm having trouble getting the command-line client working, using the latest coffeescript, node, and dominiate code.

Basic info:

Code: [Select]
ecq ~/proj/dominiate [master] $ uname -mrs
Darwin 11.2.0 x86_64
ecq ~/proj/dominiate [master] $ node -v
v0.6.6
ecq ~/proj/dominiate [master] $ coffee -v
CoffeeScript version 1.2.0
ecq ~/proj/dominiate [master] $ git log --oneline -n 1
b26f896 mark Secret Chamber as done -- fixes #36

First problem:

Code: [Select]
ecq ~/proj/dominiate [master] $ ./play.coffee  strategies/BigMoney.coffee strategies/BigSmithy.coffee
SyntaxError: In /Users/patrick/proj/dominiate/basicAI.coffee, unmatched OUTDENT on line 438
    at SyntaxError (unknown source)
    at Lexer.error (/usr/local/lib/node_modules/coffee-script/lib/coffee-script/lexer.js:584:13)
    at Lexer.pair (/usr/local/lib/node_modules/coffee-script/lib/coffee-script/lexer.js:539:40)
    at Lexer.outdentToken (/usr/local/lib/node_modules/coffee-script/lib/coffee-script/lexer.js:298:16)
    at Lexer.lineToken (/usr/local/lib/node_modules/coffee-script/lib/coffee-script/lexer.js:276:14)
    at Lexer.tokenize (/usr/local/lib/node_modules/coffee-script/lib/coffee-script/lexer.js:28:94)
    at /usr/local/lib/node_modules/coffee-script/lib/coffee-script/coffee-script.js:40:34
    at Object..coffee (/usr/local/lib/node_modules/coffee-script/lib/coffee-script/coffee-script.js:18:17)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)

The indentation for the default action priority list appears to be incorrect.  This is easy enough to fix, but I'm hoping the fact that I see it sheds some light on things.  Fixing that issue and moving on...

Code: [Select]
ecq ~/proj/dominiate [master*] $ git diff
diff --git a/basicAI.coffee b/basicAI.coffee
index 2127661..2d1b7c4 100644
--- a/basicAI.coffee
+++ b/basicAI.coffee
@@ -435,7 +435,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.
ecq ~/proj/dominiate [master*] $ ./play.coffee  strategies/BigMoney.coffee strategies/BigSmithy.coffee
TypeError: object is not a function
    at Array.CALL_NON_FUNCTION_AS_CONSTRUCTOR (native)
    at /Users/patrick/proj/dominiate/play.coffee:14:10
    at /Users/patrick/proj/dominiate/play.coffee:33:23
    at /Users/patrick/proj/dominiate/play.coffee:36:6
    at Object.<anonymous> (/Users/patrick/proj/dominiate/play.coffee:64:3)
    at Object.<anonymous> (/Users/patrick/proj/dominiate/play.coffee:70:4)
    at Module._compile (module.js:432:26)
    at Object.run (/usr/local/lib/node_modules/coffee-script/lib/coffee-script/coffee-script.js:68:25)
    at /usr/local/lib/node_modules/coffee-script/lib/coffee-script/command.js:135:29
    at /usr/local/lib/node_modules/coffee-script/lib/coffee-script/command.js:110:18

This is where things get tricky for me, because I've barely used node.js.  Google suggests the problem is a circular reference.  Despite what the stack trace says, the offending line seems to be line 12: "ai = new BasicAI()" in play.coffee.  For some reason BasicAI is an array containing the BasicAI constructor, when it should be the constructor itself.  I poked around a little and found that on line 1201 of basicAI.coffee, immediately after defining the BasicAI class, BasicAI is an array.  Weird.

In case it was a circular reference, I tried swapping lines 6 and 7 of play.coffee (the lines that require gameState and basicAI) to see if that made a difference.  It does.  Swapping those two lines allows the program to run without exceptions, but neither AI buys anything and the simulation just runs on forever.

Thoughts?  Am I missing something simple?  What versions are known to work?  I'm not sure if this is the best place to post this info, or if the github bug tracker is more appropriate.  Let me know if I should move it.

Thanks for the help and the awesome project.  I can't wait to use it.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on December 29, 2011, 03:04:59 pm
Hm, I suppose that's the problem with a fast-moving programming language. I'm running on Node 0.4.10 (and that was a cutting-edge version when I started).

Later I'll try upgrading Node and see what goes wrong.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on December 30, 2011, 07:09:10 am
Okay, it seems that the change was entirely in CoffeeScript. I upgraded to Node v0.6.6 and Dominiate continues to run correctly. So the problems can only be in syntax that has changed in CoffeeScript 1.2.

This means that a possible quick fix is to install CoffeeScript 1.1 for now. Certainly not a state I want to leave things in, of course.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ecq on December 30, 2011, 12:16:42 pm
Thanks for the help.  CoffeeScript v1.1.0 works fine for me.  I filed a bug to fix v1.2.0: https://github.com/rspeer/dominiate/issues/56 (https://github.com/rspeer/dominiate/issues/56).  I also sent a pull request with code that fixes a couple of the issues.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on January 08, 2012, 07:44:41 am
So, I added a first guess for support of costum starting state in my  repo  (https://github.com/DStu-dominion/dominate).

You can redefine the starting state there by overwriting the functions
startingDraw: () -> []
and
startingDiscard: () -> []

to whatever cards you like to have in your deck. It's a zero-variable function because I don't understand how coffeescript handles variables, so functions are easier.
Not much tested and no support for enable/disable shuffling or anything fancy like played Durations from last turn, so no pullrequest yet, just for information...

edit: OK, realized (while wanting to test something else) that perhaps I should also care for the supplies when I change the starting state. Anyway, I also have a 0.something  version of the "don't kill yourself rule". It should work like that:

Before proposing tha ai some cards to choose from to buy, erase all that that will cause it to lose if it will buy it and afterwards finish the buyphase as usual.
If that works, it is even better as what Geronimoo does, because, if I have figured it out correctly only tests if the current buy will kill you, without considering if further buys might rescue you again (because maybe Province/Estate will win you, when Province alone will make you lose).
Also online on my page now.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on January 26, 2012, 03:36:45 am
Thanks for all the contributions, and sorry that I've been away. I've merged them all and pushed the changes to the Web version, and nothing seems to be on fire yet!

Quick summary: ecq (blits) refactored code so that "fast mode" is the only mode, fixed the incompatibilities with CoffeeScript 1.2.0, got rid of some card-specific hacks, fixed Courtyard strategies, and implemented Scheme. DStu added the "no suicide rule". (Any chance we can beat Geronimoo to the Penultimate Province Rule?)

Would there happen to be anyone who feels like writing test cases that make sure the game actually follows the rules of Dominion? A bit of a thankless job, I know, but it will pay off massively in that we can try all kinds of new optimizations and reworkings without worrying about breaking the gameplay. With these merges, for example, I had to track down a very easy-to-miss bug where AIs could use Lighthouses as Moats and reuse Horse Traders -- but I'm not complaining about that too much, because there were so many useful changes in here.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on January 26, 2012, 03:58:58 am
Quote
Quick summary: ecq (blits) refactored code so that "fast mode" is the only mode, fixed the incompatibilities with CoffeeScript 1.2.0, got rid of some card-specific hacks, fixed Courtyard strategies, and implemented Scheme. DStu added the "no suicide rule". (Any chance we can beat Geronimoo to the Penultimate Province Rule?)

Beside that "no suicide" only works in the buy-phase until now, we already beat Geronimoo in the following scenario: You have $10 and 2 buys, 1 Province left and are 6VPs behind. Geronimoo buys 2 Duchies (because Province is forbidden, next prio is Duchy), we buy Province and Estate and win, because buys are only forbidden if you lose after the buy-phase is completed.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ecq on January 27, 2012, 08:52:44 pm
Thanks for all the contributions, and sorry that I've been away. I've merged them all and pushed the changes to the Web version, and nothing seems to be on fire yet!

Quick summary: ecq (blits) refactored code so that "fast mode" is the only mode, fixed the incompatibilities with CoffeeScript 1.2.0, got rid of some card-specific hacks, fixed Courtyard strategies, and implemented Scheme. DStu added the "no suicide rule". (Any chance we can beat Geronimoo to the Penultimate Province Rule?)

Would there happen to be anyone who feels like writing test cases that make sure the game actually follows the rules of Dominion? A bit of a thankless job, I know, but it will pay off massively in that we can try all kinds of new optimizations and reworkings without worrying about breaking the gameplay. With these merges, for example, I had to track down a very easy-to-miss bug where AIs could use Lighthouses as Moats and reuse Horse Traders -- but I'm not complaining about that too much, because there were so many useful changes in here.

I sent you a PM on GitHub asking about next steps.  Testing stuff was one possibility.  I don't mind writing test cases or ideally setting things up so it's easy for all of us to write test cases.  It's not my favorite thing to do, but it seems like a prerequisite for bigger and better things.  I could use some input on testing framework.  Cucumber-js is one option that I played with https://github.com/bilts/dominiate/commit/cbe8cc730c58f03a23cdcdda06d68f12ad31116c (https://github.com/bilts/dominiate/commit/cbe8cc730c58f03a23cdcdda06d68f12ad31116c).  I've also had positive experiences with Jasmine on other projects.

Related: What's the best way to send you those sorts of messages?  Should I just post here or PM on this forum?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: theory on January 31, 2012, 06:14:56 am
How should I redefine the Tactician play rule?  Right now it seems to discard it at any opportunity.  How would I set it to discard only after playing everything else (so long as one card is left) and there is < $X in the hand?

Also, when I had buggy code (for example, I had requires: ["Tactician, Tunnel"] instead of requires: ["Tactician", "Tunnel"]), it didn't tell me, but instead just weirded out and ended up reverting me back to BankWharf.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on January 31, 2012, 06:33:57 am
How should I redefine the Tactician play rule?  Right now it seems to discard it at any opportunity.  How would I set it to discard only after playing everything else (so long as one card is left) and there is < $X in the hand?

You should not mess with Tactician, it does exectly what it does. What you need to redefine is actionPriority, because you don't want to play the Tactician at every opportunity.
For playing it after anything else, you want it to be behind all the +Actions in the actionPriority-list, for your second you want something like
Code: [Select]
...
"Tactician" if pessimisticMoneyInHand(state) <= $x
...
ceterum censeo: You should redefine the actionPriority anyway for most bots just with the cards you care for, that speeds up the bot quite a bit.

edit: OK, I see, when you have played a Village before you also want to play all other terminals before. In that case you want
Code: [Select]
"Tactician" if countPlayableTerminals(state) == 1
at the position it is now, and some an additional single "Tactician" some pretty low.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on February 14, 2012, 03:06:53 am
Trader onGain doesn't work?

I have the two following issues: Bot a) Trader/Market:
Code: [Select]
# Play Big Money including Banks, except buy Wharf with every $5 buy.
{
  name: 'Trader/Market'
  author: 'DStu'
  requires: ['Trader', 'Cache']
  gainPriority: (state, my) -> [
    "Province" if my.getTotalMoney() >= 16
    "Duchy" if state.gainsToEndGame() <= 4
    "Estate" if state.gainsToEndGame() <= 2
    "Market"
    "Trader" if my.countInDeck("Trader") < 2
    "Silver"
    "Copper" if my.countInHand("Trader") > 0
  ]
 
  actionPriority: (state, my) -> [
  ]
 
  trashPriority: (state, my) -> [
     "Trader" if my.getAvailableMoney() < 5
     "Estate" if state.gainsToEndGame() > 4
     "Curse"
     "Copper"
  ]
}

Code: [Select]
== Trader/Market's turn 3 ==
[...]
Trader/Market draws 5 cards: [Estate, Copper, Trader, Copper, Estate].

== BigSmithy's turn 4 ==
[...]

== Trader/Market's turn 4 ==
Trader/Market plays Copper.
Trader/Market plays Copper.
Coins: 2, Potions: 0, Buys: 1
Trader/Market buys Copper.
(Trader/Market shuffles.)
Trader/Market draws 5 cards: [Silver, Copper, Copper, Estate, Copper].
Why doesn't it show the Trader? Similarly with Cache:

Code: [Select]
# Play Big Money including Banks, except buy Wharf with every $5 buy.
{
  name: 'Trader/Cache'
  author: 'DStu'
  requires: ['Trader', 'Cache']
  gainPriority: (state, my) -> [
    "Province" if my.getTotalMoney() >= 16
    "Duchy" if state.gainsToEndGame() <= 4
    "Estate" if state.gainsToEndGame() <= 2
    "Cache" if my.countInHand("Trader") > 0
    "Gold"
    "Cache"
    "Trader" if my.countInDeck("Trader") < 2
    "Silver"
  ]
 
  actionPriority: (state, my) -> [
    "Trader" if (my.getAvailableMoney() < 5 and this.wantsToTrash(state) )
    "Trader" if (my.countInHand("Trader") > 1 and this.wantsToTrash(state) )
  ]
 
  trashPriority: (state, my) -> [
     "Trader" if my.getAvailableMoney() < 5
     "Estate" if state.gainsToEndGame() > 4
     "Curse"
     "Copper"
  ]
}

Code: [Select]
== Trader/Cache's turn 7 ==
[...]
Trader/Cache draws 5 cards: [Copper, Trader, Silver, Copper, Gold].

== BigSmithy's turn 8 ==
[...]
== Trader/Cache's turn 8 ==
Trader/Cache plays Gold.
Trader/Cache plays Silver.
Trader/Cache plays Copper.
Trader/Cache plays Copper.
Coins: 7, Potions: 0, Buys: 1
Trader/Cache buys Cache.
Trader/Cache gains Copper.
Trader/Cache gains Copper.
Trader/Cache draws 5 cards: [Copper, Silver, Copper, Silver, Copper].
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ecq on February 14, 2012, 08:38:11 am
Trader onGain doesn't work?

I discovered this issue yesterday as well.  We were probably both looking at the same thread in the General section.  I fixed it and have a pull request open: https://github.com/rspeer/dominiate/pull/72 (https://github.com/rspeer/dominiate/pull/72)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on February 14, 2012, 09:09:42 am
Trader onGain doesn't work?

I discovered this issue yesterday as well.  We were probably both looking at the same thread in the General section.  I fixed it and have a pull request open: https://github.com/rspeer/dominiate/pull/72 (https://github.com/rspeer/dominiate/pull/72)

Code: [Select]
+  isReaction: true
lol, and me was looking through the chooseByPriorityAndValue: (state, choices, priorityfunc, valuefunc)...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ecq on February 14, 2012, 11:24:25 am
heh, it was a simple fix, but I went on a wild goose chase tracking it down
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: blueblimp on March 01, 2012, 05:42:27 pm
Should the game logs be cleared when I hit the reset button? It doesn't seem to do so when I try. I'm using Chrome. (I can look more deeply if you want, but I'm curious what the intended functionality here is.)

Also, I'm trying to force my bot to only use Ironworks to gain Great Halls and not buy them directly, using the rule '"Great Hall" if my.phase isnt "buy"'. It seems to ignore the if though and just go ahead and buy Great Halls anytime. Is this supposed to work? Is there a better way? (Edit: Seems that the solution is to use state.phase rather than my.phase.)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: blueblimp on March 01, 2012, 06:30:51 pm
I'm not sure whether this is a bug, but it is awkward to prevent bots from trashing coppers aggressively with Chapel. Even if copper is not in the trashPriority list, it will still get trashed. I think this is a bug because there are included bots that try to avoid trashing coppers in some situations, such as the ChapelWitch bot, but it won't work.

I believe this is because copper receives a trash value of 0 because it is worth zero vp and costs zero. In the function chooseByPriorityAndValue, since bestValue is initialized to -Infinity and the value of the null choice is zero and the null choice is at the end of the choice list, this means copper will be chosen to be trashed.

I've attached a simple example bot that tries to entirely avoid trashing coppers so that you can see this behaviour in action.

Code: [Select]
# Try to use Chapel to trash ONLY estates, never coppers.
{
  name: 'ChapelEstatesOnly'
  requires: ['Chapel']

  gainPriority: (state, my) -> [
    "Province"
    "Gold"
    "Chapel" if my.countInDeck("Chapel") == 0
    "Silver"
  ]

  trashPriority: (state, my) -> [
    "Estate"
  ]
}

Setting all trash values to -1 blocks copper trashing:

Code: [Select]

# Try to use Chapel to trash ONLY estates, never coppers.
{
  name: 'ChapelEstatesOnlyFixed'
  requires: ['Chapel']

  gainPriority: (state, my) -> [
    "Province"
    "Gold"
    "Chapel" if my.countInDeck("Chapel") == 0
    "Silver"
  ]

  trashPriority: (state, my) -> [
    "Estate"
  ]

  # Need this for it to work!
  # This blocks all trashing we don't authorize by priority.
  trashValue: (state, card, my) ->
    -1
}
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ecq on March 05, 2012, 12:03:08 pm
I've been considering how to test the simulators and had kind of a neat idea this weekend.  We could grab a couple of days worth of Isotropic logs, reject games with unimplemented cards and/or Masquerade, and exercise the code using the remaining game logs.  We'd parse the logs, feed hands and decisions from the game through the simulator, and ensure that everything made sense.

Obviously this is imperfect because Isotropic doesn't tell you precisely what was drawn or discarded, but it could serve as baseline sanity checks for the game and card implementations, making sure we're counting money, buys, actions, and VP correctly.

I think it'd be hard to implement, but maybe not as hard as writing the equivalent set of tests manually, and probably less error-prone.  Obviously we'd still need tests for AI decisions, strange edge cases, and things that aren't available from scanning logs.

I'm betting Geronimoo's simulator could benefit from this idea as well, but I know Dominiate is actively looking for tests.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on April 10, 2012, 12:19:43 pm
Anybody any idea why this
Code: [Select]
{
  name: 'IGG'
  author: 'DStu'
  requires: ["Ill-Gotten Gains"]
  gainPriority: (state, my) -> [
    "Province"
    "Ill-Gotten Gains"
    "Duchy"
    "Estate" if state.gainsToEndGame() <= 2
    "Gold"
    "Silver"
  ]
 
  gainCopperPriority: (state, my) ->
    if my.coinGainMargin(state) <= my.countInHand("Ill-Gotten Gains")
      [yes]
    else
      [no]
}
is rejected from the simulator? It always resets to DoubleJack when I hit the simulate-button. Obviously it doesn't like my.coinGainMargin, but I don't understand why...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on April 10, 2012, 03:29:23 pm
Ok, got it, coinGainMargin does not belong to the gamestate, but to the AI. so it's
Code: [Select]
gainCopperPriority: (state, my) ->
    if my.ai.coinGainMargin(state) <= my.countInHand("Ill-Gotten Gains")
      [yes]
    else
      [no]

Committed this version as improvement, the old one does not even support the rush against BigMoney, see http://dominionstrategy.com/2012/02/06/hinterlands-ill-gotten-gains/#comment-14370
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Quadell on April 11, 2012, 10:36:28 am
I'm trying to simulate a Gardens-Workshop-Moat strategy (if Moat is the only low-cost third kingdom card available), and I can't stop it from playing Moat instead of Workshop, which is disastrous for the strategy. How can I tell the simulator to prefer to play Workshop over Moat?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on April 11, 2012, 10:41:35 am
There is always a better kindom card than Moat, namely Estate.

Anyway, what you want is

Code: [Select]
{
  name: 'Workshop, Gardens and Moat'
  author: 'Quadell'
  requires: ["Workshop", "Gardens", "Moat"]
  gainPriority: (state, my) -> [
    "Gardens"
    "Workshop"
    "Silver"
    "Moat"
    "Estate"
    "Copper"
  ]
 
  actionPriority: (state, my) -> [
    "Workshop"
    "Moat"
  ]
}
Not debugged, tested or even optimzied...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Quadell on April 11, 2012, 11:12:51 am
Thanks! That works, and it will be useful to know how to do this in future tests. In this case it appears to be moot, as you point out, since this alone is pretty strong:
Code: [Select]
{
  name: 'Simplest Workshop-Gardener'
  author: 'Quadell'
  requires: ["Workshop", "Gardens"]
  gainPriority: (state, my) -> [
    "Workshop"
    "Gardens"
    "Estate"
    "Copper"
  ]
}

It beats Big Smithy, Double Jack, any simple cursing strategy, etc. You can improve this with Great Hall, Village, or Fishing Village, and probably others, but it looks to me like most $2-$3 cards (including Moat) just make it worse. Anyway, thanks again!
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Quadell on April 12, 2012, 10:12:42 am
Post-script: The limits of simulation (http://forum.dominionstrategy.com/index.php?topic=2196.msg34251).
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on June 09, 2012, 06:53:04 pm
While Isotropic was down I finally finished my "aiPlayValue" branch (remember when I said I was working on this sometime in, oh, 2011) and merged it in. The AI's default preference for playing each card is now defined on the card, with a function called "ai_playValue", returning a number from -100 (avoid playing at all costs) to 1000 (OMG PLAY IT NOW).

This is a mechanism that generalizes: cards can define an "ai_xValue" function, for some x, and that function will be consulted by default when making decision x about that card. The decision named 'play' replaces the 'action' and 'treasure' decisions.

I used this mechanism for Throne Room and King's Court too, with a decision named "multiplied" that returns a value over 1000 if it's preferable to play the card with a multiplier. We could in fact define all the default decisions for a card on the card object, which is great for experimenting with variant cards!

Part of the point here was also to make it play faster, because it no longer has to evaluate the enormous actionPriority function all the time. In fact, the result is about a 10% speedup.

The bigger bottleneck is actually the "gainsToEndGame" function, which is called all the time by lots of different decisions. The value is saved in a cache, but apparently the cache is cleared way too often, so that would be the thing to look at next for efficiency. But other nice things to accomplish would be:

Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on June 12, 2012, 03:56:49 pm
But other nice things to accomplish would be:

  • Implement and update the Optimized Big Money + action strategies
  • Create a meta-strategy that chooses the best OBM strategy
  • Make a nice way to add a variant card to the game

I ignored all these and implemented a version of Develop. Runs at the moment, but needs some more testing before pull request.

edit: and there's no default play rules for Develop in the AI, and I'm not sure if these make any sense ;)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on June 17, 2012, 10:53:47 am
So, I think I got a first version for Develop, including a little example bot on how to use it with Develop/Festival/Watchtower that loses to BM.

ai_playvalue still missing, not sure what's a good number...

edit: Sent a pull request, but I think it get messed with the old IGG-one which is still not solved...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: blueblimp on August 06, 2012, 05:23:27 pm
Grand Market has two values for ai_playValue:
Code: [Select]
makeCard "Grand Market", c.Market, {
  cost: 6
  coins: 2
  actions: 1
  cards: 1
  buys: 1
  # Grand Market is the only card with a non-constant mayBeBought value.
  mayBeBought: (state) ->
    not(c.Copper in state.current.inPlay)
  ai_playValue: (state, my) -> 795
  ai_playValue: (state, my) -> 880
}
In some versions of CoffeeScript, this causes a syntax error. In particular, version 1.3.3, which is the latest. (Although the current code in CoffeeScript's GitHub seems to let it pass, so I'm not sure what's going on there.) Anyway, I assume this is a typo, but I don't know whether it's supposed to be 795 or 880.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on August 08, 2012, 03:11:38 am
880 was supposed to be the multipliedPlayValue.

Anyway, I've implemented Sage, Poor House, and Graverobber! Here's a silly example:

Code: [Select]
# Sajak buys two Jacks of All Trades and a Sage.
{
  name: 'Sajak'
  author: 'rspeer'
  requires: ["Jack of All Trades", "Sage"]
  gainPriority: (state, my) -> [
    "Province" if my.getTotalMoney() > 15
    "Duchy" if state.gainsToEndGame() <= 5
    "Estate" if state.gainsToEndGame() <= 2
    "Gold"
    "Jack of All Trades" if my.countInDeck("Jack of All Trades") < 2
    "Sage" if my.countInDeck("Sage") < 1
    "Silver"
  ]
}
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on August 08, 2012, 03:13:18 am
... On the other hand, it turns out that one Jack and a Sage is better than DoubleJack, 53% to 47%.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: h1402686 on December 01, 2012, 10:42:09 am
I've just been reading annotated game 2 (http://dominionstrategy.com/2011/02/14/annotated-game-2/) (yes I am way behind), in which [spoiler alert] one of the players manages to buy 4 colonies in 15 turns using no kingdom cards other than apprentices. Doubtless there was some luck involved, but in solitaire play I can't get anywhere close. I must be choosing the wrong cards to trash with the apprentice. There's also some discussion in the comments about how this could have been done even more efficiently by mixing in other kingdom cards. This simulator looks like the best platform for exploring this. However, I know that it will be a while before I can learn how to use this simulator and do the exploration so I thought I'd post here in the hopes that someone will get interested and explore the question first.

EDIT: I believe Dominiate rather than Geronimoo's simulator is the correct platform here because it seems to allow you to override which cards get trashed.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on December 01, 2012, 10:59:26 am
Discussed this briefly (without Colonies)  here (http://forum.dominionstrategy.com/index.php?topic=5497.0) last week.  I haven't done much optimization, but you should get a feeling on how to use the simulator in this case...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ^_^_^_^ on February 17, 2013, 11:15:20 pm
Interestingly enough, this makes it appear that double Ambass is about equal in power to Witch/Chapel. W/C has only a slightly higher winning percentage.

Double Ambassador: 1640.5 wins (47.4%) ChapelWitch: 1817.5 wins (52.6%)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: fprefect on September 09, 2013, 04:57:42 am
Hello alltogether,

Has anyone got the coffeescripts run on Windows with node.js? For mee it sais always 'package coffee-script not available'. And yes: I installed coffee-script and added the paths to the PATH variable...

PS: Compiling the js files for the web gui works, but all the bots are not in the pull down menu...

fprefect
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on September 21, 2013, 01:49:45 am
You might be able to tell I've kind of burned out on this project. Mostly because I get too few opportunities to play a good game of Dominion these days. I can feel everything I used to know about Dominion being pushed out of my mind to make room for other things. Sorry about that.

I believe my instructions for CoffeeScript on Windows are out of date. NodeJS for Windows exists now. I don't know exactly how to get from zero to CoffeeScript using that fact, but there's probably a much better way than using the non-Node thing I linked to.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on September 21, 2013, 03:17:21 am
You might be able to tell I've kind of burned out on this project. Mostly because I get too few opportunities to play a good game of Dominion these days. I can feel everything I used to know about Dominion being pushed out of my mind to make room for other things. Sorry about that.

I believe my instructions for CoffeeScript on Windows are out of date. NodeJS for Windows exists now. I don't know exactly how to get from zero to CoffeeScript using that fact, but there's probably a much better way than using the non-Node thing I linked to.

1. Install a virtual machine
2. Put linux on it
3. Follow rspeer's instructions

rspeer, I've been fiddling with this some and I just wanted to say thanks. It's a really elegant framework. Works right out of the box and easy to learn by example.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on September 21, 2013, 09:23:36 am
I've added Rebuild to dominiate. Also Journeyman and Rogue, but hey! Rebuild! :D

I've also implemented a few basic Rebuild strategies, but there's certainly plenty of room for improvement:

http://gokologs.drunkensailor.org/static/dominiate/play.html
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: achmed_sender on September 21, 2013, 11:37:56 am
I've added Rebuild to dominiate. Also Journeyman and Rogue, but hey! Rebuild! :D

I've also implemented a few basic Rebuild strategies, but there's certainly plenty of room for improvement:

http://gokologs.drunkensailor.org/static/dominiate/play.html

Cool
At least I'm now relieved that things like Wharf/Bank wins over Rebuild (even with Jack) in a Province game

EDIT: I'm surprised that Witch BM can beat Rebuild-Single
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Watno on September 21, 2013, 11:57:04 am
BM+Monument is dead even with the simple Rebuild Strategy, and so is DoubleJack.
DoubleMountebank beats it 60-40. i fear I havwe to start thinking about what to do again when I see Rebuild on the board.

Are you planning on adding all cards to the simulator, AI?

EDIT: How does the opening post of this thread only have 2 respect?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: WanderingWinder on September 21, 2013, 12:00:53 pm
EDIT: How does the opening post of this thread only have 2 respect?
Because when it was posted, the respect system didn't exist.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Robz888 on September 21, 2013, 07:37:06 pm
BM+Monument is dead even with the simple Rebuild Strategy, and so is DoubleJack.
DoubleMountebank beats it 60-40. i fear I havwe to start thinking about what to do again when I see Rebuild on the board.

My thoughts exactly. Gulp.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: WanderingWinder on September 21, 2013, 07:43:30 pm
BM+Monument is dead even with the simple Rebuild Strategy, and so is DoubleJack.
DoubleMountebank beats it 60-40. i fear I havwe to start thinking about what to do again when I see Rebuild on the board.

My thoughts exactly. Gulp.
I've been saying for a while that some simple BM strategies are the way to compete with rebuild. However, I don't exactly buy that this simulator is playing rebuild near optimally....
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on September 21, 2013, 08:47:48 pm
BM+Monument is dead even with the simple Rebuild Strategy, and so is DoubleJack.
DoubleMountebank beats it 60-40. i fear I havwe to start thinking about what to do again when I see Rebuild on the board.

My thoughts exactly. Gulp.
I've been saying for a while that some simple BM strategies are the way to compete with rebuild. However, I don't exactly buy that this simulator is playing rebuild near optimally....

The Rebuild bots I wrote aren't even close to optimal. They pay no attention to the cards in their draw pile, the Duchy split, the VP totals, etc. It's easy to write nearly-optimal BM strategies, but it'll take a lot more Dominiate code to produce a bot that plays a halfway decent Rebuild game. If anyone does write a better version, send me the Dominiate code and I'll add it to the server.

Comparing DoubleJack or Monument-BM to RebuildSimple wouldn't be meaningful even if the bot was smarter. RebuildSimple doesn't use any terminals. Adding just one Jack gives you the RebuildJack strategy, and even that's enough to beat DoubleJack 60-40.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: WanderingWinder on September 21, 2013, 08:53:18 pm
BM+Monument is dead even with the simple Rebuild Strategy, and so is DoubleJack.
DoubleMountebank beats it 60-40. i fear I havwe to start thinking about what to do again when I see Rebuild on the board.

My thoughts exactly. Gulp.
I've been saying for a while that some simple BM strategies are the way to compete with rebuild. However, I don't exactly buy that this simulator is playing rebuild near optimally....

The Rebuild bots I wrote aren't even close to optimal. They pay no attention to the cards in their draw pile, the Duchy split, the VP totals, etc. It's easy to write nearly-optimal BM strategies, but it'll take a lot more Dominiate code to produce a bot that plays a halfway decent Rebuild game. If anyone does write a better version, send me the Dominiate code and I'll add it to the server.

Comparing DoubleJack or Monument-BM to RebuildSimple wouldn't be meaningful even if the bot was smarter. RebuildSimple doesn't use any terminals. Adding just one Jack gives you the RebuildJack strategy, and even that's enough to beat DoubleJack 60-40.
It's also worth noting that some of those 'baseline' strategies have colonies included - so it's much less surprising they're beating Rebuild ideas which never buy colony.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on September 22, 2013, 09:40:27 am
Are you planning on adding all cards to the simulator, AI?

No. Only the ones I'm most interested in and the most easily programmed. I plan to do Cultist next.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: markusin on September 22, 2013, 03:29:42 pm
BM+Monument is dead even with the simple Rebuild Strategy, and so is DoubleJack.
DoubleMountebank beats it 60-40. i fear I havwe to start thinking about what to do again when I see Rebuild on the board.

My thoughts exactly. Gulp.
I've been saying for a while that some simple BM strategies are the way to compete with rebuild. However, I don't exactly buy that this simulator is playing rebuild near optimally....

The Rebuild bots I wrote aren't even close to optimal. They pay no attention to the cards in their draw pile, the Duchy split, the VP totals, etc. It's easy to write nearly-optimal BM strategies, but it'll take a lot more Dominiate code to produce a bot that plays a halfway decent Rebuild game. If anyone does write a better version, send me the Dominiate code and I'll add it to the server.

Comparing DoubleJack or Monument-BM to RebuildSimple wouldn't be meaningful even if the bot was smarter. RebuildSimple doesn't use any terminals. Adding just one Jack gives you the RebuildJack strategy, and even that's enough to beat DoubleJack 60-40.
Though the Rebuild bots may not be playing optimally, it's interesting that Chapel/Young Witch really goes to town of RebuildSimple and even has a slight edge over RebuildJack. That's not the case for Witch/Chapel and Mountebank Chapel. I guess the results would be very different depending on the Young Witch Bane.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ftl on September 22, 2013, 04:16:32 pm
Without a Bane, young witch really is super-powerful.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: markusin on September 22, 2013, 05:30:51 pm
So, uh, BM-Smithy handily beats BM-Masquerade on Dominiate. I thought BM-Masquerade was supposed to be really good.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: WanderingWinder on September 22, 2013, 05:41:05 pm
So, uh, BM-Smithy handily beats BM-Masquerade on Dominiate. I thought BM-Masquerade was supposed to be really good.
Well, first thing is that the Smithy deck has Colonies. Also, the masq deck neither plays the endgame at all well, nor actually plays the tactics of masquerade super well.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: markusin on September 22, 2013, 08:46:55 pm
So, uh, BM-Smithy handily beats BM-Masquerade on Dominiate. I thought BM-Masquerade was supposed to be really good.
Well, first thing is that the Smithy deck has Colonies. Also, the masq deck neither plays the endgame at all well, nor actually plays the tactics of masquerade super well.
Thanks for the insight. I was suspicious about the Masquerade bot trashing copper when it would otherwise have $8 to spend, and it does that. I doubt I would have noticed the Colonies gaining of Smithy, but removing Colonies for BM-Smithy had next to no effect on win%.

However, Masquerade-BM seems to have a slight edge against Smithy in Geronimoo's simulator, where it holds on to copper when I needs the extra copper to buy Province or even Gold.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: WanderingWinder on September 22, 2013, 10:06:34 pm
So, uh, BM-Smithy handily beats BM-Masquerade on Dominiate. I thought BM-Masquerade was supposed to be really good.
Well, first thing is that the Smithy deck has Colonies. Also, the masq deck neither plays the endgame at all well, nor actually plays the tactics of masquerade super well.
Thanks for the insight. I was suspicious about the Masquerade bot trashing copper when it would otherwise have $8 to spend, and it does that. I doubt I would have noticed the Colonies gaining of Smithy, but removing Colonies for BM-Smithy had next to no effect on win%.
I suspect that you didn't reset the simulation - you have to do this, or it will just tack on the new games on top of what was already established, rather than starting again with your new script.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: blueblimp on September 23, 2013, 12:33:38 am
I wouldn't be surprised if BM+Masq is not much better than BM+Smithy, head-to-head. The main strength of BM+Masq is how nicely it resists junkers. Same idea as how BM+Jack isn't super fast but has very nice resilience to attacks.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: markusin on September 23, 2013, 09:45:34 am
So, uh, BM-Smithy handily beats BM-Masquerade on Dominiate. I thought BM-Masquerade was supposed to be really good.
Well, first thing is that the Smithy deck has Colonies. Also, the masq deck neither plays the endgame at all well, nor actually plays the tactics of masquerade super well.
Thanks for the insight. I was suspicious about the Masquerade bot trashing copper when it would otherwise have $8 to spend, and it does that. I doubt I would have noticed the Colonies gaining of Smithy, but removing Colonies for BM-Smithy had next to no effect on win%.
I suspect that you didn't reset the simulation - you have to do this, or it will just tack on the new games on top of what was already established, rather than starting again with your new script.
No, I was sure to reset the simulator results, and removed both Colonies and Platinums from BM-Smithy Buy priorities. BM-Smithy still wins with over 60% winrate with the default buy rules in Dominiate.

However, changing the buy rules of Masquerade to match the ones used in Geronimoo's Simulator makes it win against the default BM-Smithy bot in Dominiate. Only after adjusting the buy rules of the BM-Smithy bot similarly do the two strategies have a roughly 50-50 win%
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Schneau on September 23, 2013, 11:00:54 am
Are you planning on adding all cards to the simulator, AI?

No. Only the ones I'm most interested in and the most easily programmed. I plan to do Cultist next.

Do Rats next! Goko showed us how easy it is to implement a good Rats strategy  ;) :P ::)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on September 24, 2013, 08:39:53 am
Are you planning on adding all cards to the simulator, AI?

No. Only the ones I'm most interested in and the most easily programmed. I plan to do Cultist next.

Do Rats next! Goko showed us how easy it is to implement a good Rats strategy  ;) :P ::)

Wish granted:

http://gokologs.drunkensailor.org/static/dominiate/play.html#LordBottington/AdvisorBM
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: WalrusMcFishSr on September 24, 2013, 04:08:41 pm
Are you planning on adding all cards to the simulator, AI?

No. Only the ones I'm most interested in and the most easily programmed. I plan to do Cultist next.

Do Rats next! Goko showed us how easy it is to implement a good Rats strategy  ;) :P ::)

Wish granted:

http://gokologs.drunkensailor.org/static/dominiate/play.html#LordBottington/AdvisorBM

Just a *shade* worse than Advisor-BM (47.5-52.5)

So...pretty awesome!
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on October 01, 2013, 03:27:45 am
I've started teaching this thing how to play a reasonable Rebuild game, and he's a surprisingly fast learner:

Quote
== RebuildMirror's turn 13 ==
RebuildMirror plays Rebuild.
...RebuildMirror names Estate.
...RebuildMirror reveals [Estate, Duchy].
...RebuildMirror discards [Estate].
...RebuildMirror trashes RebuildMirror's Duchy.
...RebuildMirror gains Province.
RebuildMirror plays Rebuild.
...RebuildMirror names Province.
(RebuildMirror shuffles.)
...RebuildMirror reveals [Copper, Copper, Copper, Province, Duchy].
...RebuildMirror discards [Copper, Copper, Copper, Province].
...RebuildMirror trashes RebuildMirror's Duchy.
...RebuildMirror gains Province.
Coins: 3, Potions: 0, Buys: 1
RebuildMirror buys Estate.
RebuildMirror draws 5 cards: [Copper, Copper, Silver, Silver, Silver].

:)

BM+Monument is dead even with the simple Rebuild Strategy, and so is DoubleJack.
DoubleMountebank beats it 60-40. i fear I havwe to start thinking about what to do again when I see Rebuild on the board.

Don't worry, a few lessons were enough to reverse the score: Rebuild - DoubleMountebank: (http://gokologs.drunkensailor.org/static/dominiate/play.html#Rebuild/DoubleMountebank) ~60:40.

He still couldn't quite beat DoubleWitch (http://gokologs.drunkensailor.org/static/dominiate/play.html#Rebuild/DoubleWitch), but with a little help from alternatively some Horse Traders (http://gokologs.drunkensailor.org/static/dominiate/play.html#RebuildHorse/DoubleWitch) and a Jack (http://gokologs.drunkensailor.org/static/dominiate/play.html#RebuildJack/DoubleWitch), the Witches were soon dead.

Now his most challenging opponent is himself, in the Mirror (http://gokologs.drunkensailor.org/static/dominiate/play.html#Rebuild/Rebuild), which are really quite interesting games to watch. Please let me know if you spot something weird, because although he plays fairly well, I expect him to make the occasional blunder still.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on October 01, 2013, 11:18:55 am
Looks like RebuildJack beats all available non-Rebuild strategies, including BankWharf. Is anyone up for a challenge? :)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: achmed_sender on October 01, 2013, 12:06:18 pm
Looks like RebuildJack beats all available non-Rebuild strategies, including BankWharf. Is anyone up for a challenge? :)

They are all not on the simulator, but all these kind of cards definitely beat Rebuild-Jack: KC-Bridge with great engine support, Vineyards dreamboard, Hermit-Marketsquare, possibly some Governor strategies, Goons engines, HoP megaturns, possibly a lot more games with Colony available

But yeah, not really much more...  :(
But at least Rebuild-Jack is a two card combo of two very good cards (and you can't really change Jack with something else her), so this is coming up very rarely (0.2% of the games), but Rebuild is darn strong itself and this will come up every 21th game, so it's at least good to know it's beatable about every 5th time (without support).
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on October 01, 2013, 12:27:31 pm
Yeah, I'm obviously not claiming that RebuildJack is the strongest possible thing in the entire game :)

Quote
But at least Rebuild-Jack is a two card combo of two very good cards (and you can't really change Jack with something else her)

You actually can, but not in an "of All Trades" fashion: you have to let the companion card depend on the opposing strategy. E.g. RebuildHorse performs as well or even slightly better against DoubleWitch as RebuildJack, but BankWharf crushes RebuildHorse. RebuildMonument (not implemented atm), on the other hand, loses against DoubleWitch but beats BankWharf much harder than RebuildJack does.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: qmech on October 01, 2013, 01:09:22 pm
Looks like RebuildJack beats all available non-Rebuild strategies, including BankWharf. Is anyone up for a challenge? :)

The classic Drunk Marine Students?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 01, 2013, 01:17:52 pm
Looks like RebuildJack beats all available non-Rebuild strategies, including BankWharf. Is anyone up for a challenge? :)

The classic Drunk Marine Students?
Also,  these  (http://forum.dominionstrategy.com/index.php?topic=2193.0) guys will certainly stand a chance...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 01, 2013, 02:54:18 pm
Maybe also Beggar/Gardens with Duchy>Beggar(2--4)>Gardens>Beggar>Estate>Copper? Might be able to tie or slightly win the Duchy race and gather more points after this?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on October 01, 2013, 04:54:15 pm
Maybe also Beggar/Gardens with Duchy>Beggar(2--4)>Gardens>Beggar>Estate>Copper? Might be able to tie or slightly win the Duchy race and gather more points after this?

Good Lord!

http://gokosalvager.com/static/dominiate/play.html#RebuildJack/BeggarGardens
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 01, 2013, 05:27:54 pm
Maybe also Beggar/Gardens with Duchy>Beggar(2--4)>Gardens>Beggar>Estate>Copper? Might be able to tie or slightly win the Duchy race and gather more points after this?

Good Lord!

/bow

I probably wouldn't save it as vanilla BeggarsGardens in the simulator, because if you don't want to counter Rebuild, you will want to play it  differently...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Warfreak2 on October 01, 2013, 06:33:15 pm
How about Masterpiece/Gardens?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on October 03, 2013, 10:16:16 am
I improved my Rebuild scripts a little and added RebuildMonument (http://gokologs.drunkensailor.org/static/dominiate/play.html#BankWharf/RebuildMonument), which beats BankWharf by more than 70-30 and loses to BeggarGardens "only" 60-40 or so.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: qmech on October 03, 2013, 11:37:27 am
Naive Drunk Marine Students only gets 1 in 3 against RebuildMonument.

Code: [Select]
{
  name: 'Drunk Marine Students'
  requires: ['Potion', 'University', 'Vineyard', 'Wharf']
  gainPriority: (state, my) -> [
    "University"
    "Vineyard"
    "Potion"
    "Wharf"
    "Silver"
  ]
}
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on October 03, 2013, 12:03:36 pm
Haha, I had never seen that one before. Added it, for what is drunkensailor without some similarly drunk marine students?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 03, 2013, 01:46:36 pm
Naive Drunk Marine Students only gets 1 in 3 against RebuildMonument.

Code: [Select]
{
  name: 'Drunk Marine Students'
  requires: ['Potion', 'University', 'Vineyard', 'Wharf']
  gainPriority: (state, my) -> [
    "University"
    "Vineyard"
    "Potion"
    "Wharf"
    "Silver"
  ]
}
I'm quite sure there are also some Apothecarys in the Drunken Marine Studens (probably against the headaches...)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: XerxesPraelor on October 03, 2013, 02:03:20 pm
Um, I can't figure out how to edit Dominate, even though I've downloaded it. I don't think I can; I'm not an administer on my most used computer, so I can't install coffeescript or anything.

Because of that, could I upload code for the cards that haven't been done and maybe even a few of my fan cards and have someone else implement it in their version of it?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 03, 2013, 02:10:39 pm
Um, I can't figure out how to edit Dominate, even though I've downloaded it. I don't think I can; I'm not an administer on my most used computer, so I can't install coffeescript or anything.

Because of that, could I upload code for the cards that haven't been done and maybe even a few of my fan cards and have someone else implement it in their version of it?
I guess easiest would be to fork on github and send pull requests...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on October 03, 2013, 02:12:44 pm
Naive Drunk Marine Students only gets 1 in 3 against RebuildMonument.

Code: [Select]
{
  name: 'Drunk Marine Students'
  requires: ['Potion', 'University', 'Vineyard', 'Wharf']
  gainPriority: (state, my) -> [
    "University"
    "Vineyard"
    "Potion"
    "Wharf"
    "Silver"
  ]
}
I'm quite sure there are also some Apothecarys in the Drunken Marine Studens (probably against the headaches...)

He called them naive for a reason ;)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on October 03, 2013, 03:49:22 pm
Um, I can't figure out how to edit Dominate, even though I've downloaded it. I don't think I can; I'm not an administer on my most used computer, so I can't install coffeescript or anything.

Because of that, could I upload code for the cards that haven't been done and maybe even a few of my fan cards and have someone else implement it in their version of it?

It's hard to contribute to an open-source project if you can't test your code. ;)

Try to get your admin to install CoffeeScript. If they can't or won't, you could put another OS or a Virtual Machine on a USB and boot from that, though that solution isn't for the faint of heart. Maybe just run your code on your "less used" computer?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 04, 2013, 01:42:23 pm
Um, I can't figure out how to edit Dominate, even though I've downloaded it. I don't think I can; I'm not an administer on my most used computer, so I can't install coffeescript or anything.

Because of that, could I upload code for the cards that haven't been done and maybe even a few of my fan cards and have someone else implement it in their version of it?

It's hard to contribute to an open-source project if you can't test your code. ;)
(http://cdn.meme.li/i/5rog9.jpg)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on October 04, 2013, 01:46:45 pm
Um, I can't figure out how to edit Dominate, even though I've downloaded it. I don't think I can; I'm not an administer on my most used computer, so I can't install coffeescript or anything.

Because of that, could I upload code for the cards that haven't been done and maybe even a few of my fan cards and have someone else implement it in their version of it?

It's hard to contribute to an open-source project if you can't test your code. ;)
(http://cdn.meme.li/i/5rog9.jpg)

This is embarrassingly close to true for me.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: XerxesPraelor on October 04, 2013, 02:37:25 pm
Um, I can't figure out how to edit Dominate, even though I've downloaded it. I don't think I can; I'm not an administer on my most used computer, so I can't install coffeescript or anything.

Because of that, could I upload code for the cards that haven't been done and maybe even a few of my fan cards and have someone else implement it in their version of it?

It's hard to contribute to an open-source project if you can't test your code. ;)


I can create it in some language I have on my computer, testing it there, and then do my best to transcribe it, but you're right. I'll try.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 05, 2013, 03:41:27 pm
I've updated the Marine Students to the original and implemented Masterpiece (including Feodum/Masterpiece), but I've lost track of the branches on github.  Which on is the master branch at the moment that is on the server? Andrew's seems to be a bit behind (e.g. doesn't have Drunken Matine Students, but the server has)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on October 05, 2013, 04:08:14 pm
I've been adding stuff to the server directly while Andrew has been patiently awaiting a response to his pull-request. If you link me to the .coffee files of your strategies or just post them here I'm happy to install them as long as they don't strike me as completely terrible :P
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 05, 2013, 04:38:54 pm
So let's see, we have
 (real) Drunken Marine Students  (https://github.com/DStu-dominion/dominate/blob/strategies/strategies/DrunkenMarineStudents.coffee)
 modified Beggars/Gardens to both counter Rebuild and play good Beggars/Gardens   (https://github.com/DStu-dominion/dominate/blob/strategies/strategies/BeggarGardens.coffee)


Also
 Masterpiece/Feodum  (https://github.com/DStu-dominion/dominate/blob/Masterpiece/strategies/MasterpieceFeodum.coffee), but Masterpiece is not implemented, so you would have to merge basicAI.coffee and cards.coffee, so that is probably better done via git.


Edit: I have sent pull request to Andrew, is that the right address or still to Rob?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on October 05, 2013, 05:12:58 pm
I've added the first two strategies, you may need to empty your cache to be able to see them.

Andrew should answer the rest of your post, as I simply don't know what to tell you :)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on October 05, 2013, 05:51:48 pm
Edit: I have sent pull request to Andrew, is that the right address or still to Rob?

I accepted your pull requests (without testing them).

I also made you a collaborator on my fork, so you can check into my master or create pull requests on your fork and accept them on mine yourself. SCSN is making changes directly to my master through a user account on my server, since he doesn't have a coffeescript development environment.

I don't know if there's an official master fork per se, but I'll keep hosting my repo's version on drunkensailor. If/when Rob catches up on the code, I'm happy to link to his version instead.

Edit: Added my repo's version to the main links on drunkensailor.org
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 14, 2013, 06:56:14 am
Hi all, I implemented (https://github.com/DStu-dominion/dominate/tree/working) Baker. Pull request is send, Andrew said I would have permissions to direktly merge or something, but I don't have the time right now to look how this works.

Anyway, there are some things to say.
Obviously, there has to be a new variable
Code: [Select]
@coinTokens
in the player class.
Then, the ai has a new function
Code: [Select]
spendCoinTokens: (state, my) ->
which as default spends as many Coin Tokens as are needed to get the best buy that it can get.  This is not very clever for non-Baker bots, because they might spend their one Coin Token in a silly situation (e.g. starting 3/4 spending 1 token to get the Smithy in T1 and buying Silver with $4).  Comparing other bots against Baker you probably want to overwrite spendCoinTokens and just hard code how it should react in the first turns, it is not that difficult anyway.  Output of this function is an integer which tells how much to spend, if you want to spend more than you have, it defaults to max.  Gives a warning in the log, not sure if I want to keep that.

The AI also has a new variable
Code: [Select]
@coinTokensSpendThisTurn
This one is intended to be able to let you manage how you spend Coin Tokens in gainPriority(state, my), e.g. you can do something like "Province" if coinTokensSpendThisTurn < 3. [Actually, I haven't tested this part, so maybe I should] (done).

And then there is BigMoneyBaker.coffee in the strategies, which is just BigMoney which buys Baker at $5.  Not optimized at all, just there for testing, so whoever has done some optimization, post it here and/or on github.

And actually I don't know if we want to have "Coin Tokens" in the log or "coin Tokens" or "Coin tokens" or "Coin tokens".  Bugfixes welcome.

That's about it, hf.

Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 14, 2013, 11:46:17 am
Added Candlestick Maker and Merchant Guild, which was quite trivial after Coin Tokens were implemented.

Also added support for the possibility of multiple buys in the spendCoinTokens decision, which I didn't cared for in the first version.

Edit: Moved coinTokensSpendThisTurn to the player class (access it with my.coinTokensSpendThisTurn) to better work with hypothetical states, but realized my logic has some error still, so it does not work as it should.

Edit2: some more bugfixes, I'm quite confident that it now works mostly correct, so I merged it into aiannacc/master.  my.coinTokensSpendThisTurn still does not work as I would like it to, but I'm afraid there's not much to do about this.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 16, 2013, 12:55:10 pm
Also did Plaza (not on any github repo yet), and omg is BM-Plaza strong...

:edit Or maybe I should fix bugs before I form opinions on the strength of cards
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on October 17, 2013, 12:18:36 am
Added Candlestick Maker and Merchant Guild, which was quite trivial after Coin Tokens were implemented.

Also added support for the possibility of multiple buys in the spendCoinTokens decision, which I didn't cared for in the first version.

Edit: Moved coinTokensSpendThisTurn to the player class (access it with my.coinTokensSpendThisTurn) to better work with hypothetical states, but realized my logic has some error still, so it does not work as it should.

Edit2: some more bugfixes, I'm quite confident that it now works mostly correct, so I merged it into aiannacc/master.  my.coinTokensSpendThisTurn still does not work as I would like it to, but I'm afraid there's not much to do about this.

Great! Thanks.

I'm getting an error when I try a strategy that includes Baker:
"Uncaught TypeError: Cannot read property 'isPrize' of undefined"

Strategy code, as entered on http://gokologs.drunkensailor.org/static/dominiate/play.html:
Code: [Select]
{
  name: 'BakerBM'
  requires: ['Baker']
  gainPriority: (state, my) -> [
    "Province"
    "Duchy" if 0 < state.gainsToEndGame() <= 5
    "Estate" if 0 < state.gainsToEndGame() <= 2
    "Gold"
    "Baker"
    "Silver"
    "Copper" if state.gainsToEndGame() <= 3
  ]
}
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 17, 2013, 02:07:15 pm
Can't reproduce on my instance, and on drunkensailor Baker does not run at all. Did you compile to JS with make?

Edit: I guess that's the problem as  the JS  (http://gokologs.drunkensailor.org/static/dominiate/playWeb.js) does not contain Baker (but the other cards)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 17, 2013, 03:13:01 pm
Anyway, in the meantime I finished (I hope) Plaza. Don't want to merge it directly until the other issues are resolved, so ordinary pull request.  Check out
Code: [Select]
plazaDiscardPriority: (state, my) ->
to control the behaviour on what and when to discard treasures to Plaza. (default is
Code: [Select]
plazaDiscardPriority: (state, my) -> [
    "Copper"
    null
  ]       
until someone wants to improve it....)

Edit: If case someone is interested, I think I won't touch Butcher (can do the card but don't want to think about a default strategy on how to play it)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on October 17, 2013, 07:32:13 pm
Can't reproduce on my instance, and on drunkensailor Baker does not run at all. Did you compile to JS with make?

Edit: I guess that's the problem as  the JS  (http://gokologs.drunkensailor.org/static/dominiate/playWeb.js) does not contain Baker (but the other cards)

Oy, you're quite right. Sorry about that.

Works fine now.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 18, 2013, 02:57:02 am
So more cards.

Finishes Plaza and Bandit Camp (and Spoils), and added the reaction to Beggar. Also improved Beggars/Gardens strategy, the possibility to react on attacks increases the winchance against DoubleMilitia from 99.5% to 99.9%

New functions for AI:
Code: [Select]
wantsToDiscardBeggar: (state) ->
wantsToPlaySpoils: (state) ->
defaults: Beggar -> true. Spoils -> true if it changes what we buy this turn. else false

Gave some trivial merge conflicts (git didn't know which of wantsToDiscardBeggar or wantsToPlaySpoils should be first in the file), so I merged everything together and pushed it upstream.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Kirian on November 09, 2013, 08:43:50 pm
Maybe also Beggar/Gardens with Duchy>Beggar(2--4)>Gardens>Beggar>Estate>Copper? Might be able to tie or slightly win the Duchy race and gather more points after this?

Good Lord!

/bow

I probably wouldn't save it as vanilla BeggarsGardens in the simulator, because if you don't want to counter Rebuild, you will want to play it  differently...

Just for the hell of it I tested it out vs most of the strategies in there.  It lost only to MP/Feodum... and it was able to beat most of the strategies at a 90% or so rate.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Warfreak2 on November 10, 2013, 04:11:19 am
With Masterpiece on the board, the optimal Gardens strategy probably involves it.

How about Stonemason->2xBeggar / Gardens? If competing for Duchies, you can trash Duchies for two Gardens.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on November 26, 2013, 06:33:08 pm
With Rebuild being so awfully strong, I've been interested to see whether removing the "+1 Action" would balance it. I expected it to remain strong, while Donald X. said that this version "couldn't compete". Since I didn't know how to add new cards to the simulator, I just "simulated" this with the existent Rebuild strategy (by ragingduckd and SheCantSayNo) by setting "WantsToRebuild" to zero when there's already a Rebuild in play, which seems to work as intended. The buying strategy is still close to optimal. This "TerminalRebuild" turns out to be significantly weaker than the original card:

TerminalRebuild loses to the strongest BM cards: Wharf, Goons, GhostShip, DoubleJack, all Cursers.

It essentially ties with Monument (51:49), Envoy (48.5:51.5), Smithy (52:48) and Courtyard (50:50), and wins against all other implemented one-card strategies (Militia, Masq., HP, Amb., Library, ...).

So BM-TerminalRebuild is about as strong as standard Smithy-BM, i.e. far from overpowered, but occasionally useful on BM boards. This seems to me to be an interesting "mediocre" card: It'd be worse in an engine, but great for slogs, or when combined with Walled Village (making it non-terminal again) or Tournament.



Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on November 26, 2013, 09:32:03 pm
Nice work!

How do your results change if you remove from gainPriority the line

Code: [Select]
"Rebuild" if my.countInDeck("Rebuild") < 3 and state.countInSupply("Rebuild") == 8
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on November 27, 2013, 08:32:26 am
Thanks. Not buying the third Rebuild changes very little; TerminalRebuild seems to become marginally (<1%) weaker against most cards, but now loses also to Monument (probably because BM-Monument tends to longer games).

I've also tried replacing one Rebuild by a Gold; this marginally helps against one card but hurts against another.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: vandergus on December 17, 2013, 09:20:15 am
I'm working on a BM Masquerade bot and trying to get it to not trash copper if it would be able to buy a Province that turn. I tried to add conditions to the trash priorities but it's not working. Here's the bot.

Code: [Select]
{
  name: 'BM Masquerade'
  requires: ['Masquerade']
  gainPriority: (state, my) ->
    [
      "Province" if my.getTotalMoney() > 15
      "Duchy" if state.gainsToEndGame() <= 5
      "Estate" if state.gainsToEndGame() <= 2
      "Gold"
      "Masquerade" if my.countInDeck("Masquerade") < 1
      "Silver"
    ]
   
  trashPriority: (state, my) -> [
      "Curse"
      "Estate" if state.gainsToEndGame() > 4
      "Copper" if my.getTotalMoney() > 4 \
               and my.getTreasureInHand() != 8 \
               and my.getTreasureInHand() != 6
      "Potion" if my.turnsTaken >= 10
      "Estate" if state.gainsToEndGame() > 2
    ]
}

It's not working, though. I still get situations like this...

Code: [Select]
== BM Masquerade's turn 10 ==
BM Masquerade plays Masquerade.
BM Masquerade draws 2 cards: [Gold, Copper].
BM Masquerade passes Copper.
BigSmithy passes Copper.
BM Masquerade trashes Copper.
BM Masquerade plays Copper.
BM Masquerade plays Copper.
BM Masquerade plays Silver.
BM Masquerade plays Gold.
Coins: 7, Potions: 0, Buys: 1
BM Masquerade buys Duchy.
BM Masquerade draws 5 cards: [Gold, Copper, Gold, Silver, Copper].

I've also tried the method getAvailableMoney() but that doesn't work either. Is it possible that the methods don't see the copper that has been passed to the Masquerade player? Or is there something wrong with the way I have defined the conditions.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on December 18, 2013, 04:56:33 am
Is it possible that the methods don't see the copper that has been passed to the Masquerade player?
Just had a look pn the code of Masquerade, and the passed Copper should be in your hand when you choose to trash, so it should be seen...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: vandergus on December 18, 2013, 06:55:20 am
Is it possible that the methods don't see the copper that has been passed to the Masquerade player?
Just had a look pn the code of Masquerade, and the passed Copper should be in your hand when you choose to trash, so it should be seen...

Is trashPriority not the appropriate way to handle these decisions then? Some cards have their own unique priority list for choices but I didn't see anything for Masquerade.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on December 18, 2013, 07:11:38 am
Ok, got it.

First, trashPriority is the right way to do it. You have to change it to
Code: [Select]
trashPriority: (state, my) -> [
      "Curse"
      "Estate" if state.gainsToEndGame() > 4
      "Copper" if my.getTotalMoney() > 4 \
               and my.getTreasureInHand() != 8 \
               and my.getTreasureInHand() != 6
      "Potion" if my.turnsTaken >= 10
      "Estate" if state.gainsToEndGame() > 2
     null
in order to get it to do what you want.  I would consider this maybe as a bug as it took me half an hour to find out, despite already knowing it.

What is happening is: trashPriority is used both when you are forced to trash and when you are allowed to trash.  Additionally, trashPriority is not the only function used to find out what you want/need to trash, but only the first one, there is trashValue as a fallback.  In your case, trashPriority returns no valid choice, therefore thrashValue is used.  trashValue always returns a choice, which is good as it is for the cases where you need to trash.  Therefore, you have to return some valid choice in trashPriority, null is a valid choice an indicates that you don't want to trash if none of your proposals fits.

I think that this maybe should be the default, because usually you list everything you want to trash and are kind of surprised if something else get trashed, and putting the null at the end of the list is something you often forget. So maybe we should put the null there automaticall and give an option for getting rid of it?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: vandergus on December 18, 2013, 08:29:54 am
Ok, got it.

Excellent. Thanks for looking into that. I was wondering about the null choice but thought it was handled behind the scenes. Still got some optimization to do. This code only looks for potential Gold and Province buys but it should also look for Duchy buys at later points in the game.

The other thing I noticed about Masquerade, if I'm reading the code correctly, is that it also uses the trash priority and trash value functions to choose which card to pass. It seemed strange to me that there wasn't a separate priority list. The best card to trash is not always the best card to pass.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on December 18, 2013, 10:14:49 am
In your case, trashPriority returns no valid choice, therefore thrashValue is used.  trashValue always returns a choice, which is good as it is for the cases where you need to trash.  Therefore, you have to return some valid choice in trashPriority, null is a valid choice an indicates that you don't want to trash if none of your proposals fits.

I haven't looked at the actual code so it may not be an issue, but from your description I deduce that trashValue is called only when trashPriority does not return a valid choice, and since null is apparently a valid choice, it would allow you to trash nothing even if trashing is mandatory.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: vandergus on December 18, 2013, 11:38:24 am
I started to code all sorts of different scenarios where you wouldn't want to trash a copper (like when you have $5 for a Duchy, but only late in the game when you're in Duchy mode) and it was getting really complicated. Then I found coinLossMargin and reduced many lines of code to a single expression. This significantly improves the BM Masquerade bot on Dominiate (buy rules were taken from Geronimoo's BM Masquerade bot).

Code: [Select]
# Big Money Masquerade bot.
#
# The bot plays a typical BM strategy with some intelligence on when to trash coppers.
# Basically, if there is an important buy available that needs every copper in hand,
# it passes on the trash ability.
{
  name: 'BM Masquerade'
  requires: ['Masquerade']
  author: 'vandergus'
  gainPriority: (state, my) ->
    [
      "Province"
      "Duchy" if state.countInSupply("Province") <= 4
      "Estate" if state.countInSupply("Province") <= 2
      "Gold"
      "Duchy" if state.countInSupply("Province") <= 5
      "Masquerade" if my.countInDeck("Masquerade") < 1
      "Silver"
    ]
   
  trashPriority: (state, my) -> [
      "Curse"
      "Estate" if state.gainsToEndGame() > 4
      "Copper" if this.coinLossMargin(state) > 0
      "Potion" if my.turnsTaken >= 10
      "Estate" if state.gainsToEndGame() > 2
      null
    ]
}

The only questionable play I saw in the logs was something like this.

Code: [Select]
== BM Masquerade's turn 11 ==
BM Masquerade plays Masquerade.
BM Masquerade draws 2 cards: [Estate, Province].
BM Masquerade passes Copper.
DoubleJack passes Copper.
BM Masquerade plays Gold.
BM Masquerade plays Gold.
BM Masquerade plays Copper.
BM Masquerade plays Copper.
Buying Province will cause BM Masquerade to lose the game
Coins: 8, Potions: 0, Buys: 1
BM Masquerade buys Duchy.
BM Masquerade draws 5 cards: [Copper, Gold, Gold, Copper, Silver].

The bot wanted to buy a Province so it didn't trash the 8th coin. But then ended up buying a Duchy instead because a Province would've ended in a loss. This seems like a rather small corner case.

Not sure about the null choice turning mandatory trashes into optional trashes. But in the above case, the Masquerade bot still passes a copper when, according to the trash priority list, it wouldn't if it didn't have to.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on December 18, 2013, 04:37:37 pm
In your case, trashPriority returns no valid choice, therefore thrashValue is used.  trashValue always returns a choice, which is good as it is for the cases where you need to trash.  Therefore, you have to return some valid choice in trashPriority, null is a valid choice an indicates that you don't want to trash if none of your proposals fits.

I haven't looked at the actual code so it may not be an issue, but from your description I deduce that trashValue is called only when trashPriority does not return a valid choice, and since null is apparently a valid choice, it would allow you to trash nothing even if trashing is mandatory.
No, null is added to the se to valid choices by the function called for optional trashing, it should not be valid for mandatory trashing.

edit @vandergus: I think what you want is to see if trashing changes what your buy, not sure if there is a build-in function to do so. It's done a dozen times though, I always wanted to write a function for this, but I don't know if I did.  Look at  (iirc) Ill-gotten gains or Plaza.  If there exists a function, it should be used at Plaza, otherwise use hypothetical states to find out.

edit2: wantsToplaySpoils is also quite good to look at on how to use hypothetical states...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: vandergus on December 18, 2013, 07:40:53 pm
In your case, trashPriority returns no valid choice, therefore thrashValue is used.  trashValue always returns a choice, which is good as it is for the cases where you need to trash.  Therefore, you have to return some valid choice in trashPriority, null is a valid choice an indicates that you don't want to trash if none of your proposals fits.

I haven't looked at the actual code so it may not be an issue, but from your description I deduce that trashValue is called only when trashPriority does not return a valid choice, and since null is apparently a valid choice, it would allow you to trash nothing even if trashing is mandatory.
edit @vandergus: I think what you want is to see if trashing changes what your buy, not sure if there is a build-in function to do so. It's done a dozen times though, I always wanted to write a function for this, but I don't know if I did.  Look at  (iirc) Ill-gotten gains or Plaza.  If there exists a function, it should be used at Plaza, otherwise use hypothetical states to find out.

edit2: wantsToplaySpoils is also quite good to look at on how to use hypothetical states...

That's kind of what coinLossMargin does. Not directly but indirectly. The problem is that it doesn't seem to account for buys that would lose the game. Which is weird because coinLossMargin calls getSingleBuyDecision which uses checkSuicide. So if you have $8 but a Province would lose you the game, getSingleBuyDecision should return Duchy, which in turn should give a coinLossMargin of $3, allowing a trash. I guess I need to run this in debug mode to figure out where I'm not getting the expected value. Not sure if I have the tools to do that on my computer.

I don't think Dominiator has Spoils or Plaza. I couldn't ctrl-f them in cards.coffee.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on December 19, 2013, 02:41:02 am
I don't think Dominiator has Spoils or Plaza. I couldn't ctrl-f them in cards.coffee.

https://github.com/aiannacc/dominiate
http://gokologs.drunkensailor.org/static/dominiate/play.html
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: vandergus on December 19, 2013, 08:21:12 am
https://github.com/aiannacc/dominiate
http://gokologs.drunkensailor.org/static/dominiate/play.html

Thanks. I'll spend some time looking through here.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on March 02, 2014, 01:09:10 pm
Pull request for Hunting Grounds.
Fixed a bug with Saboteur that didn't trigger onTrashEffects
Gave a standard method to basicAI for wantsToJM


I suspect that there are some more cards that trash but don't trigger onTrashEffects, as sometimes no standard method is used to trash, but the card is just moved to the trash by hand.  Sawn this for Mint and Rebuild, I think it is the case when cards are trashed from non-standard locations, as in this cases I have not seen a genric trash method that does the job. Esp. Mint/Feodum would be important...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on April 06, 2014, 12:41:47 pm
I've noticed that JoaT is implemented suboptimally: Jack discards an Estate or Curse when it has none in hand, instead it should usually draw and trash it (at least in the early game):

Quote
== DoubleJack's turn 6 ==
DoubleJack plays Jack of All Trades.
DoubleJack gains Silver.
DoubleJack reveals and discards Estate.
DoubleJack draws 1 cards: [Copper].
DoubleJack plays Copper.
DoubleJack plays Copper.
DoubleJack plays Copper.
DoubleJack plays Silver.
Coins: 5, Potions: 0, Buys: 1
Coin Tokens left: 0
DoubleJack buys Silver.
(DoubleJack shuffles.)
DoubleJack draws 5 cards: [Copper, Copper, Copper, Gold, Silver].

This is especially bad behaviour in games against Cursers; no wonder DoubleJack currently loses to Witch and Mountebank...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on April 06, 2014, 03:56:05 pm
I've noticed that JoaT is implemented suboptimally: Jack discards an Estate or Curse when it has none in hand, instead it should usually draw and trash it (at least in the early game):

I've now tried a more reasonable discard strategy by adding

Quote
 
discardPriority: (state, my) -> [
    "Estate" if my.countInHand("Estate")+ my.countInHand("Curse")  > 0 \
    or state.countInSupply("Province") < 6 or my.coins=7
    "Curse" if my.countInHand("Estate")+ my.countInHand("Curse")  > 0 \
    or state.countInSupply("Province") < 3 or my.coins=7
    "Copper"
    "Province"
    "Duchy"
    "Jack of All Trades"
    null
 ]

to the DoubleJack bot. The improvement is astonishing: The win rate against BankWharf increases from 36% to 55%, it now wins 53-47 against DoubleWitch, 67-33 against DoubleMountebank.
And it wins 58-42 against Rebuild!!! Am I dreaming? :o I've let the simulator play 5,000 games to be sure. DoubleJack even beats RebuildRogue, RebuildHorse and RebuildDuke by 54-46 or better.

Does the discardPriority function I added mess something up with the opponent's strategy, or is Rebuild really worse than Jack when both are played reasonably (and without Shelters/Colonies)?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on April 06, 2014, 04:18:13 pm
It should still lose against RebuildJack (add the updated strategy there as well), which is the only sensible comparison.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on April 06, 2014, 05:10:22 pm
It should still lose against RebuildJack (add the updated strategy there as well), which is the only sensible comparison.

It does lose (even without the updating), but still I'm baffled by this result.
(I wouldn't call this the only reasonable comparison; on a board with Rebuild, Jack and a "better" Rebuild support like Horse Traders, I would have ignored Jack prior to this simulation.)
My impression was that almost everyone considered Rebuild to be the better 1-card BM strategy. Probably (?!) Rebuild remains the stronger card against engines due to the Duchy depletion, but still...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on April 07, 2014, 06:30:18 am
It should still lose against RebuildJack (add the updated strategy there as well), which is the only sensible comparison.

It does lose (even without the updating), but still I'm baffled by this result.
(I wouldn't call this the only reasonable comparison; on a board with Rebuild, Jack and a "better" Rebuild support like Horse Traders, I would have ignored Jack prior to this simulation.)
My impression was that almost everyone considered Rebuild to be the better 1-card BM strategy. Probably (?!) Rebuild remains the stronger card against engines due to the Duchy depletion, but still...

I suspect that what SCSN means is that on any board in which Double-Jack can face Rebuild-X, one of the options is Rebuild-Jack.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: MarkowKette on April 07, 2014, 11:53:54 am
I am actually not surprised at all of this result. Adding those rules to the Jack play has to be a big improvement. And Jack is already a very strong BM enabler that was reasonably close in power to rebuild strategies before. SCSN is of course very right about Jack also being a Prime Rebuild enabler (better than e.g. Horse Traders) As rebuild synergizes pretty well with Jack and a normal double Jack will spend $5 on a Silver in the early to midgame where a Rebuild instead is a lot more powerfull.
I wonder how a  double Jack strategy that still buys Gold on 6 (early-to-mid) and just adds rebuilds on 5 would compete with a more rebuild focused Rebuild/JAck.

What i don't really understand is why double Witch has a higher win-rate against double Jack than double Mountemank as you will block Mountebanks less often after the play-rules improvement. I guess there is a good reason for this (given such a huge difference in the win rates) but i can't see it right now.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Awaclus on April 07, 2014, 12:01:15 pm
I am actually not surprised at all of this result. Adding those rules to the Jack play has to be a big improvement. And Jack is already a very strong BM enabler that was reasonably close in power to rebuild strategies before. SCSN is of course very right about Jack also being a Prime Rebuild enabler (better than e.g. Horse Traders) As rebuild synergizes pretty well with Jack and a normal double Jack will spend $5 on a Silver in the early to midgame where a Rebuild instead is a lot more powerfull.
I wonder how a  double Jack strategy that still buys Gold on 6 (early-to-mid) and just adds rebuilds on 5 would compete with a more rebuild focused Rebuild/JAck.

What i don't really understand is why double Witch has a higher win-rate against double Jack than double Mountemank as you will block Mountebanks less often after the play-rules improvement. I guess there is a good reason for this (given such a huge difference in the win rates) but i can't see it right now.
In the late game, the Coppers are somewhat useful for big money. Maybe that has something to do with it.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: SCSN on April 07, 2014, 12:17:54 pm
Because Witch is just the better card?

Its cycling ensures that you play it more often and as long as your money density exceeds 1 its benefits to you are greater than Mountebank's.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on April 07, 2014, 02:15:07 pm
It should still lose against RebuildJack (add the updated strategy there as well), which is the only sensible comparison.

It does lose (even without the updating), but still I'm baffled by this result.
(I wouldn't call this the only reasonable comparison; on a board with Rebuild, Jack and a "better" Rebuild support like Horse Traders, I would have ignored Jack prior to this simulation.)
My impression was that almost everyone considered Rebuild to be the better 1-card BM strategy. Probably (?!) Rebuild remains the stronger card against engines due to the Duchy depletion, but still...

I suspect that what SCSN means is that on any board in which Double-Jack can face Rebuild-X, one of the options is Rebuild-Jack.

That's true, of course; but my point was that the relative strength of Rebuild and Jack can still matter if there's good enough support for one of the two that you can ignore the other. E.g. I could now imagine Jack-Mystic to be stronger than RebuildJack; so Rebuild may be ignorable on a sizable number of BM boards containing Jack.

I am actually not surprised at all of this result. Adding those rules to the Jack play has to be a big improvement. And Jack is already a very strong BM enabler that was reasonably close in power to rebuild strategies before. SCSN is of course very right about Jack also being a Prime Rebuild enabler (better than e.g. Horse Traders) As rebuild synergizes pretty well with Jack[...]
I don't think Rebuild and Jack synergize at all - the advantage of drawing an additional card when the two collide should be more than offset by the facts that Rebuild doesn't want Jack to trash all Estates, and the risk of drawing Rebuild dead with Jack; also the Silvers dilute the Rebuilds. But apparently Jack is strong enough that it still helps another card with which it has slight anti-synergy. That's why I had thought Horse Traders would be better support, because it does synergize with Rebuild (giving an almost guaranteed $5).

What i don't really understand is why double Witch has a higher win-rate against double Jack than double Mountemank as you will block Mountebanks less often after the play-rules improvement. I guess there is a good reason for this (given such a huge difference in the win rates) but i can't see it right now.
I expected this from the Rebuild comparisons: DoubleWitch is one of the very few single-card strategies that beats Rebuild, while Rebuild beats DoubleMountebank. I think Witch is just the better BM card (as Awaclus and SCSN said).

I was also surprised to see that the improved DoubleJack seemed to beat most strategies even better in Colony games (adding the "vanilla" Colony/Plat. gain rules), but there seems to be a serious bug in the simulator for these games; DoubleJack "cheats" by sometimes getting 7 extra Coins from nowhere every few turns (no Coin token cards available):

Quote
(DoubleJack shuffles.)
[...]
Tableau: [Jack of All Trades, Smithy, Spice Merchant, Remodel, Jester, Vault, Treasury, Ambassador, Familiar, Bishop, Colony, Platinum, Potion]

[...]
== DoubleJack's turn 5 ==
DoubleJack plays Jack of All Trades.
DoubleJack gains Silver.
DoubleJack reveals and discards Copper.
DoubleJack draws 1 cards: [Jack of All Trades].
DoubleJack plays Copper.
DoubleJack plays Copper.
DoubleJack plays Silver.
DoubleJack plays Silver.
Coins: 13, Potions: 0, Buys: 1
Coin Tokens left: 0
DoubleJack buys Platinum.
DoubleJack draws 5 cards: [Estate, Copper, Copper, Copper, Copper].
[...]
== DoubleJack's turn 8 ==
DoubleJack plays Jack of All Trades.
DoubleJack gains Silver.
DoubleJack reveals and discards Copper.
DoubleJack draws 1 cards: [Copper].
DoubleJack plays Silver.
DoubleJack plays Platinum.
DoubleJack plays Copper.
DoubleJack plays Copper.
DoubleJack plays Copper.
Coins: 17, Potions: 0, Buys: 1
Coin Tokens left: 0
DoubleJack buys Colony.
DoubleJack draws 5 cards: [Silver, Copper, Copper, Silver, Jack of All Trades].

[...]

== DoubleJack's turn 9 ==
DoubleJack plays Jack of All Trades.
DoubleJack gains Silver.
(DoubleJack shuffles.)
DoubleJack reveals and discards Copper.
DoubleJack draws 1 cards: [Platinum].
DoubleJack plays Silver.
DoubleJack plays Silver.
DoubleJack plays Copper.
DoubleJack plays Copper.
DoubleJack plays Platinum.
Coins: 18, Potions: 0, Buys: 1
Coin Tokens left: 0
DoubleJack buys Colony.
DoubleJack draws 5 cards: [Colony, Copper, Copper, Silver, Copper].
[...]
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Polk5440 on April 07, 2014, 02:17:05 pm
Because if you are buying only Mountebanks and treasure, you should buy more than 2 Mountebanks?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on April 07, 2014, 02:49:23 pm
Maybe I should also clarify that my surprise was not just that Jack beats Rebuild decisively, but that (unlike Rebuild) it beats practically every other BM strategy (the only defeat is against bane-less Young Witch, and very narrowly - about 48-52). The (oldish) common wisdom expressed in the Jack articles by theory and HME:

Quote from: theory, http://dominionstrategy.com/2011/12/05/hinterlands-jack-of-all-trades/
...[it] goes toe-to-toe with DoubleMountebank and DoubleWitch.

If you go in the simulator and pit single-card strategies against each other, [Double]Jack is going to win a lot. As far as I can tell, it only loses to Young Witch, Witch, Mountebank, Wharf, Masquerade, and Courtyard.

is apparently almost completely wrong; DoubleJack does beat all these other cards decisively, except Young Witch (unless their Dominiate strategies should all turn out to be as badly suboptimal as Jack's). So these articles (AdamH says of theory's that it "reflected the mentality of that time, which was that Jack [...] was overpowered[...]") still substantially underestimate Jack's power!

And the simulation results are for Estate games only - with Shelters DoubleJack should be even stronger. Only with (correctly implemented) Colonies might the other cards stand a chance...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: MarkowKette on April 07, 2014, 04:36:26 pm
Because Witch is just the better card?

Its cycling ensures that you play it more often and as long as your money density exceeds 1 its benefits to you are greater than Mountebank's.

I really have to disagree here. Yes it cycles faster. No that doesn't mean you will play more Witches!
You can draw the second Witch dead and they miss the reshuffle more often. I'm pretty sure both of those reasons together lead to you playing the card less often than if it were a Mountebank.

And to Witch being the better card overall: Mountebank destoys engine possibilities a lot more than Witch does.

@Holger i'm pretty sure they synergize very well. Yes you don't want to trash your estates but gaining Silvers is very good for your deck and having a 5 card hand even if you played a rebuild and your silvergaining card is really nice as it increases the chance of hitting 5 on a turn you played your rebuild drastically. I think the small filter option Jack gives alone nearly makes up for the small chance of drawing rebuild dead with it.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on April 10, 2014, 05:52:07 pm
I've noticed that JoaT is implemented suboptimally: Jack discards an Estate or Curse when it has none in hand, instead it should usually draw and trash it (at least in the early game):

I've now tried a more reasonable discard strategy by adding

Quote
 
discardPriority: (state, my) -> [
    "Estate" if my.countInHand("Estate")+ my.countInHand("Curse")  > 0 \
    or state.countInSupply("Province") < 6 or my.coins=7
    "Curse" if my.countInHand("Estate")+ my.countInHand("Curse")  > 0 \
    or state.countInSupply("Province") < 3 or my.coins=7
    "Copper"
    "Province"
    "Duchy"
    "Jack of All Trades"
    null
 ]

to the DoubleJack bot. The improvement is astonishing: The win rate against BankWharf increases from 36% to 55%, it now wins 53-47 against DoubleWitch, 67-33 against DoubleMountebank.
And it wins 58-42 against Rebuild!!! Am I dreaming? :o I've let the simulator play 5,000 games to be sure. DoubleJack even beats RebuildRogue, RebuildHorse and RebuildDuke by 54-46 or better.

Does the discardPriority function I added mess something up with the opponent's strategy, or is Rebuild really worse than Jack when both are played reasonably (and without Shelters/Colonies)?
I was also surprised to see that the improved DoubleJack seemed to beat most strategies even better in Colony games (adding the "vanilla" Colony/Plat. gain rules), but there seems to be a serious bug in the simulator for these games; DoubleJack "cheats" by sometimes getting 7 extra Coins from nowhere every few turns (no Coin token cards available):
[...]

It seems I WAS dreaming, and the bug was in my own code (and not just in Colony games, apparently): "my.coins=7" sometimes sets the player Coins count from 0 to 7 in spite of being in an if clause; it should read "my.coins==7" instead. When fixing this, DoubleJack does lose against Rebuild and DoubleWitch.
(My improvement only increases the win rate by 0-4%, far from enough.)
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: GeoLib on April 10, 2014, 06:50:01 pm
I've noticed that JoaT is implemented suboptimally: Jack discards an Estate or Curse when it has none in hand, instead it should usually draw and trash it (at least in the early game):

I've now tried a more reasonable discard strategy by adding

Quote
 
discardPriority: (state, my) -> [
    "Estate" if my.countInHand("Estate")+ my.countInHand("Curse")  > 0 \
    or state.countInSupply("Province") < 6 or my.coins=7
    "Curse" if my.countInHand("Estate")+ my.countInHand("Curse")  > 0 \
    or state.countInSupply("Province") < 3 or my.coins=7
    "Copper"
    "Province"
    "Duchy"
    "Jack of All Trades"
    null
 ]

to the DoubleJack bot. The improvement is astonishing: The win rate against BankWharf increases from 36% to 55%, it now wins 53-47 against DoubleWitch, 67-33 against DoubleMountebank.
And it wins 58-42 against Rebuild!!! Am I dreaming? :o I've let the simulator play 5,000 games to be sure. DoubleJack even beats RebuildRogue, RebuildHorse and RebuildDuke by 54-46 or better.

Does the discardPriority function I added mess something up with the opponent's strategy, or is Rebuild really worse than Jack when both are played reasonably (and without Shelters/Colonies)?
I was also surprised to see that the improved DoubleJack seemed to beat most strategies even better in Colony games (adding the "vanilla" Colony/Plat. gain rules), but there seems to be a serious bug in the simulator for these games; DoubleJack "cheats" by sometimes getting 7 extra Coins from nowhere every few turns (no Coin token cards available):
[...]

It seems I WAS dreaming, and the bug was in my own code (and not just in Colony games, apparently): "my.coins=7" sometimes sets the player Coins count from 0 to 7 in spite of being in an if clause; it should read "my.coins==7" instead. When fixing this, DoubleJack does lose against Rebuild and DoubleWitch.
(My improvement only increases the win rate by 0-4%, far from enough.)

Probably this uses lazy evaluation, so it only looks at that last condition if it can't figure out the result from all the others. That's why you only saw the bug some turns. If it gets to that part it makes sense that it will perform that action though.

I'm glad order has been restored to the universe. Those were some pretty surprising results!
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on April 11, 2014, 08:07:07 am
Probably this uses lazy evaluation, so it only looks at that last condition if it can't figure out the result from all the others. That's why you only saw the bug some turns. If it gets to that part it makes sense that it will perform that action though.
That's a possible explanation, but in the turns I posted, the simulator shouldn't even have looked at the Estate condition (if it's really lazy :P), since discarding an Estate wasn't even possible with a Copper revealed; also the command inside an if-clause should have triggered an error warning IMO. I was using a single "=" because that's used as the mathematical equality sign in many languages, but of course it's a command in JavaScript. :-[

I'm glad order has been restored to the universe. Those were some pretty surprising results!
I couldn't agree more. Though I would have liked Rebuild to be substantially weaker than some card...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on April 11, 2014, 08:51:33 am
Probably this uses lazy evaluation, so it only looks at that last condition if it can't figure out the result from all the others. That's why you only saw the bug some turns. If it gets to that part it makes sense that it will perform that action though.
That's a possible explanation, but in the turns I posted, the simulator shouldn't even have looked at the Estate condition (if it's really lazy :P), since discarding an Estate wasn't even possible with a Copper revealed; also the command inside an if-clause should have triggered an error warning IMO.
No, I don't think it is that lazy.  The function discardPriority is called to return the priority of your discards given the (state, my). Afterwards, the possible choices and your priority are matched (iirc).
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on April 20, 2014, 04:33:44 pm
Hey all.

I kind of took a year and a half off from Dominion because of Goko. I feel bad that I didn't do any maintenance of Dominiate during that time, but just thinking about Dominion was pretty depressing when I could only play it in person.

I'm back to playing Dominion Online now. It's playable! All the credit goes to the Salvager team, not to Making Fun/Goko.

So now I look at Dominiate and I see that ragingduckd (that's AI, right?) is maintaining a better version of it. That's great! I'm really happy to see that development could carry on without me. And, of course, there are some absolutely enormous pull requests in my GitHub for Dominiate now. I thought that merging the pull requests would be a good way to get back into development, until yesterday I looked at AI's pull request and backed away slowly. That's a lot of code to review on a code base I haven't looked at in a long time.

So here's my question. Should I try to update rspeer/dominiate to once again be the "master" version? Or should I let AI stay in charge and submit pull requests to him? He's of course been much more reliable than me. I think it comes down to whether AI is happy to be running this project when he runs so many other Dominion projects.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Awaclus on April 20, 2014, 04:37:28 pm
It's playable! All the credit goes to the Salvager team, not to Making Fun/Goko.
Well, some of it goes to Making Fun. Before Making Fun, it was literally not playable at times.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on April 21, 2014, 08:17:42 am
So here's my question. Should I try to update rspeer/dominiate to once again be the "master" version? Or should I let AI stay in charge and submit pull requests to him? He's of course been much more reliable than me. I think it comes down to whether AI is happy to be running this project when he runs so many other Dominion projects.

By all means, take it back.  I haven't actually worked on it in several months, nor am I really planning to.  I just wanted to add a few DA cards and make it publiclly accessible.  I'll change my link to point to your site whenever you're ready.

FYI, I'm pretty sure I made some mistakes when I added those cards, as I didn't fully appreciate the framework.  I seem to recall that I failed to add default decision rules to the "basic strategy" or something like that.  It resulted in errors when, say, a non-Rebuild strategy somehow ended up with a Rebuild in its deck.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on April 21, 2014, 09:06:51 am
So here's my question. Should I try to update rspeer/dominiate to once again be the "master" version? Or should I let AI stay in charge and submit pull requests to him? He's of course been much more reliable than me. I think it comes down to whether AI is happy to be running this project when he runs so many other Dominion projects.

By all means, take it back.  I haven't actually worked on it in several months, nor am I really planning to.  I just wanted to add a few DA cards and make it publiclly accessible.  I'll change my link to point to your site whenever you're ready.

FYI, I'm pretty sure I made some mistakes when I added those cards, as I didn't fully appreciate the framework.  I seem to recall that I failed to add default decision rules to the "basic strategy" or something like that.  It resulted in errors when, say, a non-Rebuild strategy somehow ended up with a Rebuild in its deck.

I fixed these if I happen to run into them.

Anyway, I think what one thing that someone might want to take a decision on is some generic trashing function, as there are some problems with onTrash effects. See http://forum.dominionstrategy.com/index.php?topic=619.msg349859#msg349859
Fixed a problem for Saboteur there, saw it for Mint and Rebuild.

I don't see an easy way for a generic function, maybe we should just fix the cards where it is the case.  But maybe someone has an idea...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on April 29, 2014, 06:47:28 pm
So here's my question. Should I try to update rspeer/dominiate to once again be the "master" version? Or should I let AI stay in charge and submit pull requests to him? He's of course been much more reliable than me. I think it comes down to whether AI is happy to be running this project when he runs so many other Dominion projects.

By all means, take it back.  I haven't actually worked on it in several months, nor am I really planning to.  I just wanted to add a few DA cards and make it publiclly accessible.  I'll change my link to point to your site whenever you're ready.

BTW, is there a list of all implemented cards somewhere? It seems most but not all pre-DA cards are included, plus a few DA cards...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on April 29, 2014, 10:07:47 pm
The only complete list is the code and its semi-documentation (http://rspeer.github.io/dominiate/docs/cards.html).

I could summarize, though, that the implemented cards are:

Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on April 30, 2014, 12:36:44 pm
The only complete list is the code and its semi-documentation (http://rspeer.github.io/dominiate/docs/cards.html).

I could summarize, though, that the implemented cards are:

  • All but 11 of the pre-Dark Ages cards -- the missing ones are listed on the issues page (https://github.com/rspeer/dominiate/issues)
  • Sage, Graverobber, and Poor House

Thanks for the summary; that's quite a lot of cards. But I'd also be interested in the list of cards added on AI's version (like Rebuild), which are not in the code's documentation.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on April 30, 2014, 06:45:24 pm
The only complete list is the code and its semi-documentation (http://rspeer.github.io/dominiate/docs/cards.html).

I could summarize, though, that the implemented cards are:

  • All but 11 of the pre-Dark Ages cards -- the missing ones are listed on the issues page (https://github.com/rspeer/dominiate/issues)
  • Sage, Graverobber, and Poor House

Thanks for the summary; that's quite a lot of cards. But I'd also be interested in the list of cards added on AI's version (like Rebuild), which are not in the code's documentation.

You can download my version here (https://github.com/aiannacc/dominiate).  If my server weren't down right now, you'd be able to run it at gokosalvager.com (follow the link at the top).

I think Dstu's version is the most recent, however: https://github.com/DStu-dominion/dominate [Edit: Nope, see Dstu's response below]

Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on April 30, 2014, 06:47:51 pm
The only complete list is the code and its semi-documentation (http://rspeer.github.io/dominiate/docs/cards.html).

I could summarize, though, that the implemented cards are:

  • All but 11 of the pre-Dark Ages cards -- the missing ones are listed on the issues page (https://github.com/rspeer/dominiate/issues)
  • Sage, Graverobber, and Poor House

Thanks for the summary; that's quite a lot of cards. But I'd also be interested in the list of cards added on AI's version (like Rebuild), which are not in the code's documentation.

You can download my version here (https://github.com/aiannacc/dominiate).  If my server weren't down right now, you'd be able to run it at gokosalvager.com (follow the link at the top).

I think Dstu's version is the most recent, however: https://github.com/DStu-dominion/dominate

https://github.com/DStu-dominion/dominate/network looks like everything is merged.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on May 01, 2014, 01:38:50 am
I did the merge! I also implemented default strategies for Rats and Rebuild, so they wouldn't crash SillyAI or any other AI that finds itself holding those cards.

The default Rebuild strategy is basically the same as the Rebuild.coffee AI. The default Rats strategy is
Code: [Select]
  wantsToPlayRats: (state) -> no

So the new version is up at its old place: http://rspeer.github.io/dominiate/play.html
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: c4master on May 24, 2014, 03:49:43 am
Are you going to implement a "basic engine bot", e.g. some strategy that tries to go for the engine on every board? It would be nice to see how it competes against the other AIs.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: ragingduckd on May 26, 2014, 10:44:06 pm
So the new version is up at its old place: http://rspeer.github.io/dominiate/play.html

Finally fixed the links to this on gokosalvager.com.  Sorry I forgot to do it earlier.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on June 02, 2014, 09:55:03 am
I don't know these parts of the program good enough, but how much work would it to get some sort of console mode?

I mean there is play.coffee, this is great for testing as it plays one game with log.
What I would want is a variant that for 2 given strategies plays N games and just outputs the result.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: BierDaniel on October 25, 2014, 03:14:08 pm
Hi. I dont know if someone is still workimg on this project or even looking in this thread. But perhaps someone may help me. On the github page is written this can be run on windows using the compile.bat in the web folder:
On Windows: you can now compile the CoffeeScript files on Windows, using an included CoffeeScript compiler, windows/coffee.exe. (Being an .exe file 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.


In the README is written:
- Edit the *.coffee files however you want (using a good editor such as
  Notepad++)
- Run "compile.bat" from this folder, which will compile them into web\playWeb.js
- Assuming that worked, open web\play.html in Firefox or Chrome and test it
  out.


I tried to do it, but it doent work. After running compile.bat there exists no playWeb.js in the web folder. I can start play.html and there opens a page very similiar to the link from the webstart given in this thread, but there are no strategies to choose (empty boxes) and if I write or copy them and hit the start playing button nothing happens.
Perhaps I do some mistake or there is a small mistake in the compile.bat?
Looking at the compile.bat with notepad+ shows:
coffee.exe -c -j ..\web\playWeb.js ..\playWeb.coffee ..\basicAI.coffee ..\cards.coffee ..\gameState.coffee
coffee.exe -c ..\web\multiLog.coffee
coffee.exe -c ..\web\scoreTracker.coffee


Sorry for my bad english and I hope someone may help me.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on October 25, 2014, 03:18:36 pm
Sounds like compile.bat didn't actually work. Did you see any output?

By the way, does anyone know if there's a more modern way to support compiling CoffeeScript in Windows, now that people actually use node.js in Windows?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: BierDaniel on October 25, 2014, 03:48:11 pm
Thanks for the very fast answer. Starting compile.bat opens a black window: C:\Windows\system32\cmd.exe with the following text:

C:\Users\Daniel\Downloads\dominiate-master\dominiate-master\windows>coffee.exe -
c -j ..\web\playWeb.js ..\playWeb.coffee ..\basicAI.coffee ..\cards.coffee ..\ga
meState.coffee


Then it works a while, after this come a few more lines, but the window closes very fast after it.
I added pause to the bat and get the following:

C:\Users\Daniel\Downloads\dominiate-master\dominiate-master\windows>coffee.exe -
c -j ..\web\playWeb.js ..\playWeb.coffee ..\basicAI.coffee ..\cards.coffee ..\ga
meState.coffee
coffee-script-builtin.js:8      out of memory
Execution error in main.js.

C:\Users\Daniel\Downloads\dominiate-master\dominiate-master\windows>coffee.exe -
c ..\web\multiLog.coffee

C:\Users\Daniel\Downloads\dominiate-master\dominiate-master\windows>coffee.exe -
c ..\web\scoreTracker.coffee

C:\Users\Daniel\Downloads\dominiate-master\dominiate-master\windows>pause
Drücken Sie eine beliebige Taste . . .

What can I do?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on October 27, 2014, 03:16:32 am
Out of memory? Well, I guess that's one way to show that the random standalone CoffeeScript compiler I included doesn't work.

If you don't mind running a few more things at the command line, here's a link that I think is up to date about how to install CoffeeScript on Windows: http://stackoverflow.com/a/14981509

There's lots of answers on that page, but I'm suggesting in particular the one where you install node.js and use npm. I haven't tried it, but it's the most similar to what you'd do on other OSes.

You also may be able to get it as a plugin for a particular development environment, such as Visual Studio.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: BierDaniel on October 27, 2014, 07:07:09 am
I installed nodejs and and coffescript the way written in your link.
I get following message installing coffescript:

C:\>npm install -g coffee-script
C:\Users\Daniel\AppData\Roaming\npm\coffee -> C:\Users\Daniel\AppData\Roaming\np
m\node_modules\coffee-script\bin\coffee
C:\Users\Daniel\AppData\Roaming\npm\cake -> C:\Users\Daniel\AppData\Roaming\npm\
node_modules\coffee-script\bin\cake
coffee-script@1.8.0 C:\Users\Daniel\AppData\Roaming\npm\node_modules\coffee-scri
pt
└── mkdirp@0.3.5


so it seemed to work, but when I tried to run I get the following:

C:\Users\Daniel\Downloads\dominiate-master\dominiate-master>coffee play.coffee s
trategies/BigMoney.coffee strategies/ChapelWitch.coffee
Error: Cannot find module 'coffee-script'
  at Function.Module._resolveFilename (module.js:338:15)
  at Function.Module._load (module.js:280:25)
  at Module.require (module.js:364:17)
  at require (module.js:380:17)
  at Object.<anonymous> (C:\Users\Daniel\Downloads\dominiate-master\dominiate-ma
ster\play.coffee:9:10)
  at Object.<anonymous> (C:\Users\Daniel\Downloads\dominiate-master\dominiate-ma
ster\play.coffee:6:1)
  at Module._compile (module.js:456:26)


Any ideas what am I making wrong?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: rspeer on October 29, 2014, 10:40:10 am
No. I'm sorry, but I really don't know. It might be time to ask on StackOverflow or something, where you might find someone who has used Node and CoffeeScript on Windows.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: BierDaniel on October 31, 2014, 04:04:30 pm
Perhaps another approach. I forked your project on github, so that I can implement new strategies or new cards. How can I do a website like your "http://rspeer.github.io/dominiate/play.html#DoubleJack/BankWharf" and test my new strategies or cards. If I get to my browser "http://bierdaniel.github.io/dominiate/play.html#DoubleJack/BankWharf" I get a error file not found. I can work with your webapp, so there must be a possibility to run it from my account with nearly the same files, or? I am thanking for your much help and if I get something productive to work and you want to use it I will obvisouly give it to you.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on October 31, 2014, 06:36:38 pm
I don't want to sound unconstructive, but if you are able to let dominiate run anywhere,  you are able to install a Linux and apache and run it on localhost.  And it's probably also the easiest way...

But nice to see someone else again getting into this, I've been missing the time/energy to do much on it recently...
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Seprix on March 13, 2015, 11:44:32 pm
This is all I have for Dominion Sims, since I have a Mac, and I'm not planning on getting a PC or buying Licenses for Windows so I can use a VM.

Sadly I'm terrible at coding, so this probably won't be fantastic for me anyways. :/
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on March 14, 2015, 03:38:05 am
Geronimoo's is java and works on Linux, certainly also works on mac
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: h1402686 on April 26, 2015, 01:29:42 pm
I can't get Dominiate to play Lookout. The code in cards.coffee looks like the simulator should be happy to play Lookout until it gets close to the end of the game:

Code: [Select]
makeCard "Lookout", action, {
  ...

  ai_playValue: (state, my) ->
    if state.gainsToEndGame >= 5 or state.cardInfo.Curse in my.draw
      895
    else
      -5

}

Yet the following bot buys Lookout, but never plays it:

Code: [Select]
{
  name: 'LookBug'
  requires: ['Lookout']
  gainPriority: (state, my) -> [
    "Colony" if my.countInDeck("Platinum") > 0
    "Province" if state.countInSupply("Colony") <= 6 \
               or state.countInSupply("Province") <= 6
    "Duchy" if 0 < state.gainsToEndGame() <= 5
    "Estate" if 0 < state.gainsToEndGame() <= 2
    "Platinum"
    "Gold" if my.countInDeck("Gold") < 2
    "Lookout"
    "Silver"
  ]
}
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on April 26, 2015, 01:47:05 pm
Found the bug.

My version is too far behind to patch fastly, but patch is in ai_value from Lookout
Code: [Select]
-- if state.gainsToEndGame >= 5 or state.cardInfo.Curse in my.draw
++ if state.gainsToEndGame() >= 5 or state.cardInfo.Curse in my.draw

gainsToEndGame is a function.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: h1402686 on April 26, 2015, 02:08:57 pm
Thanks, DStu. Is there a way I can patch it for myself if I'm running from a browser? Just dumping the fixed makeCard code into the "Player 1" window in my browser doesn't work.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on April 26, 2015, 02:15:30 pm
Thanks, DStu. Is there a way I can patch it for myself if I'm running from a browser? Just dumping the fixed makeCard code into the "Player 1" window in my browser doesn't work.

I don't thin you can patch, but you can workaround:

Code: [Select]
{
  name: 'LookBug'
  requires: ['Lookout']
  gainPriority: (state, my) -> [
    "Colony" if my.countInDeck("Platinum") > 0
    "Province" if state.countInSupply("Colony") <= 6 \
               or state.countInSupply("Province") <= 6
    "Duchy" if 0 < state.gainsToEndGame() <= 5
    "Estate" if 0 < state.gainsToEndGame() <= 2
    "Platinum"
    "Gold" if my.countInDeck("Gold") < 2
    "Lookout"
    "Silver"
  ]

  actionPriority: (state, my) ->
    if state.gainsToEndGame() > 5 or ...
       "Lookout"
   
}

so just add an actionPriority function to your bot, which returns a list containing the priorities you want your cards played. Note that you have to add all the cards of you bot there, as this overwrites the call of ai_value from cards (IIRC).  You might want to look into old_actionPriority in basicAI.cofffee if you have some more cards in your bot to see how they used to be prioritized.
Maybe
Code: [Select]
  actionPriority: (state, my) ->
    old_actionPriority(state,my)
does also work, at least Lookout is implemented correctly there, but there might be some newer cards (like from Guilds and Dark Ages) that are not listed there anymore.

:e corrected name of old_actionPriority.  Maybe you also have to reference it over the ai, in this case it is
Code: [Select]
my.ai.old_actionPriority(state,my)
I'm not sure what exactly the scope is from which the code is called here.

edit: OK, actionPriority seems to be not called anymore, it's now playPriority if I understand this correctly. Problem is that this one is merged with the Treasures, so you must inculde all the treasures in your list, too, otherwise the bot does not play Treasures.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on April 26, 2015, 03:04:32 pm
Yeah, why and since when don't we call actionPriority anymor when it exists? It feels like playPriority is much more of a hassle to define costumely, as you also have to care for tje Treasures.  So why is this mixed?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: h1402686 on April 26, 2015, 03:21:13 pm
I ended up downloading the code and making the fix. As far as I can tell I couldn't push the fix so I created an issue instead: https://github.com/rspeer/dominiate/issues/85
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: h1402686 on May 17, 2015, 04:47:24 pm
I made the following updates to the code:
I'm new to GitHub and am not sure I submitted the patch the right way, as I can't tell if anyone has seen it. So I'm posting it here as well: https://github.com/rspeer/dominiate/pull/86.

For fun, here's my first Forager result. When running SeaHag vs. a Forager/SeaHag bot, the Forager bot dominates, 89-11 (not surprisingly). Maybe more interesting, the Forager/SeaHag bot wants three Foragers and only one SeaHag. Code for the bots is attached.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: DStu on May 17, 2015, 05:12:35 pm
I made the following updates to the code:
  • Fixed the Lookout bug
  • Fixed another bug, this one related to trashing
  • Implemented Forager
I'm new to GitHub and am not sure I submitted the patch the right way, as I can't tell if anyone has seen it. So I'm posting it here as well: https://github.com/rspeer/dominiate/pull/86.

For fun, here's my first Forager result. When running SeaHag vs. a Forager/SeaHag bot, the Forager bot dominates, 89-11 (not surprisingly). Maybe more interesting, the Forager/SeaHag bot wants three Foragers and only one SeaHag. Code for the bots is attached.

Looks fine.
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: joejoe22802 on July 21, 2017, 05:49:26 pm
Is this Git repo dead at this point or is there a fork that's still chugging?
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Seprix on July 24, 2017, 12:27:44 pm
Is this Git repo dead at this point or is there a fork that's still chugging?

It's dead, Jim
Title: Re: Dominiate: a Dominion simulator that runs on the Web
Post by: Holger on December 30, 2017, 09:02:25 am
Is there a way to define new cards or change properties of existing cards in the web browser interface? I'd like to test Adventurer at a cheaper cost...