Dominion Strategy Forum

Please login or register.

Login with username, password and session length

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - Sparafucile

Filter to certain boards:

Pages: [1]
1
I’ve been playing through the recommended sets.   Got to a set with battle plan and catapult.    Now catapult is a split pile with rocks as the second 5 cards - and battle plan let’s you rotate any pile.

I’ve played catapult many times - but this is the first time I’ve actually used rocks.    In most games it’s just not worth it to empty like 3 more catapults to get to the rocks beneath them.  Battle plan let’s you rotate them and make them accessible early.   I really hope that catapult gets a rework that lets you optionally rotate the rocks pile.

It might be interesting to have all top cards from split piles get the rotate ability.  I think this would make the piles more interesting - though I think catapult would benefit from this mechanism the most.    The other split piles you often want the top card in multiples anyways - and the one that you might not - gladiator - has a way to burn through the pile.  Having rotate on the gladiator pile might be the only split pile where that option would reduce the strategy - as timing the burn down of gladiators to get the fortune is an interesting part of this pile.   

2
Dominion General Discussion / Allies rule book is now available
« on: March 10, 2022, 10:00:27 am »
As always, all cards are listed, rules and recommended sets

https://www.riograndegames.com/wp-content/uploads/2021/09/Dominion-Allies-Rules.pdf

3
Dominion General Discussion / Haggler and debt is bugged online
« on: July 22, 2020, 11:40:51 am »
Having a haggler in play and buying a city quarter forces you to gain either copper or curse. 

Frustrating because I wanted to use city quarter as money source to pay off debt.

Game number: 51144739

This is incorrect - as city quarter cost debt, and so Copper is NOT cheaper than city quarter.

http://wiki.dominionstrategy.com/index.php/Cost


4
Dominion Articles / Combo: Dismantle, Catapult and Spices
« on: July 14, 2019, 10:11:56 am »
Unexpected little combo I came across in  recent game.

Context:  The only chaining in the deck is from Apothecary and Alchemist.  On any given turn, could only play a total of 2 terminal actions.  (due to the event citadel enabling +1 extra action).  You already own at least a gold, and a spices, and are roughly chaining your deck.

Execution:  Dismantle a gold into a spices (giving +2 coffers) and a gold.  Then Catapult a spices.  This curses your opponent and forces them to discard down to 3.

Net Effect:  +2 coffers, +1 coin and the brutal attack of opponent gains a curse and opponent discards down to 3.   Interestingingly, this dismantle + catapult play is similar to playing 2 giants.   The economy is a little weaker.  (+3 coin instead of +6) but the attack is much stronger IMHO.   This combo always forces a curse on opponent AND makes them discard down to 3.  Giant only sometimes gains a curse.

Optional Econ building step:   Adding a middle step of dismantling the spices to a gold + silver - and then catapulting the silver instead, allows you to gain a gold out of the sequence.  so Dismantle, Dismantle, Catapult = Gain a gold, +2 coffers, +1 coin, opponent gains curse and opponent discards to 3.

5
I had 5 money, and a haggler in player, while herald was on the board.  (changeling was around ... in case that's relevent for a bug report)

Haggler - While this is in play, when you buy a card, gain a cheaper non-Victory card.
Herald - When you buy this, you may overpay for it.   For each 1 you overpaid, look through your discard pile and put a card from it onto your deck.

My plan was to buy a Herald for 5(overpay by 1) .  Since there were 2 on buy abilities - one from herald and one from haggler, i should get to choose the order.

I wanted to do the overpay first, topdecking my herald i just bought . and then gain the cheaper card.  (Changeling in this case).

What actually happened - was when I bought the herald for 5 - the UI showed up allowing me to overpay for it.  I couldn't move the slide from 0-1 - and I could hit the "overpay" button.   But then
i was never given an opportunity to look through my discard.

I feel like this was a bug .... (unless i'm interpretting the rules wrong and somehow the lose-track rule applies ... which I could see happening if I gained the haggler card first and then tried the overpay mechanic.

Thoughts? 

6
Dominion General Discussion / Dominion Anthology/Fan edtion PLEASE
« on: March 17, 2018, 02:04:55 pm »
Making a request for a dominion expansion in case Donald sees it :)

If there were another dominion expansion, I would really like to see Dominion: Anthology/Fan edition
No new mechanics introduced :)   Instead - reuse and revisit the existing ones in new combinations.

There's many awesome mechanics introduced in the expansions - but the dominion universe is so big, one often doesn't see them that frequently. 

Mechanics to revisit/expand would include:

Ruins, Cards that leverage Shelters (from Dark Ages)
Boons/Hexes, Night (from Noctune)
Reserve Cards (From Adventures)
Potion Cost (From Alchemy)
Over pay, Coin Tokens (from Guilds)
Debt, Gathering Piles, Split Piles (from Empires)
Cards that Require/encourage Platinum/Colony (from Prosperity)
When Gain/When Buy effects (from Hinterlands)

One could even mix and match.  Potion cost cards that hand out Boons!  Reserve cards that cost debt!   Cards that give out ruins and coin tokens.  Get creative :).

I dont think that the expansion would need to include all the necessary supporting pieces.  (another copy of Runes, Boons, etc etc).
Players would get to use the cards that match the expansions they already own - and then would be inspired to buy the missing expansions :)

Please upvote and include your ideas for what you might want included!

7
Variants and Fan Cards / Alternative Kingdom setup rules
« on: February 13, 2017, 02:29:30 pm »
This forum sees a lot of fan cards being made - but I'm wondering if there has been much discussion on how to play the offical cards, but with modified kingdom setup rules.    So in regular Dominion, during setup we choose 10 kingdom cards - available to all players for purchase.   Has anyone tried variations on this?  Ideas might include:
  • Different numbers of kingdom cards.  e.g. 12
  • Some kingdom cards randomly determined, 8 for example, with the remaining (2 in this case) chosen by the players
  • Mixing larger number of kingdom cards together into a "center deck" and then playing a la that style of deck builder
  • Assymetric kingdoms - where not all kingdom cards are available to both players

One idea I'm toying around with is a variation where, in a 2 person game, we randomly choose 8 kingdom cards - then each player gets to add 2 more kingdom cards for only their own use - to round out what they think is missing.  (village, +buy, +cards, gainer, trasher, vp, +cards, curser, etc etc)  Maybe everyone would pick the same power cards - don't know.

Any other ideas or thoughts?  If you have something that you have tried, I would love to hear it.

8
Rules Questions / Games that never end
« on: December 03, 2016, 03:17:21 pm »
I post this in rules question so people can confirm that we played this game correctly.  (recommended game from Empires + Darkages).

Tomb of the Rat King: Advance, Tomb • Castles, Chariot Race, City Quarter, Legionary,
Sacrifice • Death Cart, Fortress, Pillage, Rats, Storeroom

The following combo:

Landmark (+1 point on trash) + rats (trash a card from hand) + Fortress (return card to hand when trashed)

Became the winning strategy on our first play of these cards.   The winner obtained a few fortress, as mans rats as possible.  Every turn consisted of playing like 9 rats or so, trashing a fortress, and getting like 9 points.  It was very quick.  And the deck was a gold deck in that it could generate points forever without destroying the deck or ending the game.


One of the things I've always enjoyed about dominion is that increasing your deck and obtaining points has always brought a game closer to conclusion.  Growing your deck and obtaining victory points (via Goons for example) more or less required emptying piles.

In Prosperity there was one major exception -  Monument.  This card could gain points infinitely without causing the game to end.  In practice, this never comes up because it's too slow compared to other point gaining options.  Later, once cards could be gained out of the trash, an edge case entered with Bishop as well.    First with monument, and later via a combo with Bishop, it's possible to gain points forever without actually ending the game.

It seems that with empires though (an expansion I'm very grateful for Donald :) ) - there are now many more ways to competitively gain points without ending the game.

If Donald happens to see this, i humbly request a rules modification or addition should more 2nd edition rule books come out, that limits these types of games somehow.   One example modification would be to make a certain number of alternate victory points generated be a terminating game condition.  This could be done without contradiction of the current rules - no limit needed on gaining points on your turn after the threshhold for game finish has been met.   Perhaps could the threshhold could be equal to the number of province points, or colony points in a colony game.  Setting it lower might make for interesting "point rushes" instead of "3 pile rushes".  Just brainstorming. 

If such a rule exists already - in which case please let me know so we don't get stuck with infinite games.

9
In celebration of the upcoming Adventures expansion, I'm making available a beta version of the Dominulator UI.   The simulator has been around for a while, but is now much easier to use for simple results.   Use the UI to assemble a purchase order.  The cards will play be via very simple rules.  Excellent for deciding simple questions, like does Witch beat SoothSayer?

If you don't want to use the simulator, you can still use it as a randomizer which includes all released Dominion cards, including Adventures.

Full source code and installation instructions (windows 8 only) are available at

Github source

Or get the installation package here:

Release

Sorry, not in the app store yet, so it requires a developer licence.  Which is free. 

I welcome any feedback.    Sorry, not all cards are implemented for simulation yet - including most of Adventures.  Stay tuned for updates though!

10
Simulation / Ambassador, the card of openning luck?
« on: November 20, 2013, 02:23:38 am »
So.  Dominion is a game of luck.  We all know this - and this luck aspect makes the game appealing for many people.   Pulling out a victory from certain defeat is a nice nelson "haha" moment.  However, some of us like to believe that through superior playing we can beat even the worst odds.   Just how bad can the odds be anyways?

The issue of opening luck i started thinking about early in my dominion playing.  When hinterlands game out, as with all other expansions, me and my friends started playing through the recommended sets.  We got to the Traveling Circus" set - where for the first time we feature Nomad Camp and Hunting Party.   I thought the nomad camps "place on top of deck" was really cool - so I opened with that on a 4/3 split.  With a little luck, I ended up with a Nomad Camp, Hunting party opening.   After that, I continued to hit 5 coin every turn.  If the nomad camp OR hunting party is in your hand, u will probably hit 5, so it's hard to hit repeated 5s with this combo.  My poor friend struggled around with some silvers a long time before getting his first 5.  By the time he did, I had already scooped up most of the hunting parties.   That game didn't go well for him.  I declared - huh, I think that with that kind of opening luck, you will lose every time.  He didn't believe me.  We recreated the openning sequence - and the exact same thing happened.    Now I doubt we played that set optimally - would probably play it very different today - but we were both relatively noob.   Among us players of roughly equal skill the opening luck   This was my first suspicion that maybe there were some boards where opening luck is the dominating factor in victory.

Let's take a look at some basic luck numbers alone for reference.   

If you play big money vs big money, going first gives:

61.6% win for BigMoney First Player
31.6% win for BigMoney Second Player
6.8% there is a tie.

So we can roughly quantify a 60/30 split on wins as a one turn advantage.   Fortunately, simulators can correct for this bias just by alternating which strategy goes first.  In the following simulations, we will swap who goes first.

Now, if I were to tell you that smithy is on the board - clearly buying a single smithy is better than not.  You won't always win though:

23.8% win for BigMoney
71.7% win for BigMoneySingleSmithy
4.5% there is a tie.

Even with this clearly superior strategy, you only win in a 3:1 ratio.  If you are losing in a 3:1 ratio, you are pretty much losing as poorly has someone who chooses bigmoney vs BigMoneySmithy.  None of this is new to any of you I'm sure.   Most of you have probably seen the thread discussing the possibility of a strategy that will beat big money all the time.  The best we have found is one that wins like 99.98% or something like that.  I wanted to rehash some basic numbers to put in some context for the topic I wanted to discuss - Ambassador.  I've felt for a while that games involving Ambassador are particularly luck prone.   I'm pretty well known among my friends to declare - that's it, game over - after turn 3 or 4.   Am I being pessimistic, or can the odds really be that bad.  Lets find out.

Lets discuss Ambassador tactics.   Always ambassador Estates and coppers.  Return as many copies to the supply as possible.  Don't return estates when the game is ending please. (I've tried variants where we return fewer copies of cards if it improves the buy - and for the most part that tactic makes things worst - a separate post :) )

How does ambassador fair vs BigMoney?  Not great - but a little better than statistical noise:

57.9% win for Ambassador
39.7% win for BigMoney
2.4% there is a tie.

So now lets tip the scales.  We will play ambassador vs ambassador but force the shuffle luck for the first 3 turns.   Each player will always start with a 3/4 split - opening silver + ambassador.    On Turn 3 there will be a lucky player, and an unlucky player.  For example, if a player has 1 ambassador + 4 copper on turn 3, this will force a double copper return.  Lets see some numbers:

1)  Ambassador 2 Copper (unlucky) vs Ambassador 1 Estate. 

36.7% win for Unlucky
61.3% win for Lucky
2% there is a tie.

2)  Ambassador 2 Copper (unlucky) vs Ambassador 2 Estates. 

28.1% win for Unlucky
69.8% win for Lucky
2.1% there is a tie.

3) Ambassador 1 Estate (unlucky) vs Ambassador 2 Estates

42.2% win for Unlucky
53.9% win for Lucky
3.9% there is a tie.

So as long as you get to ambassador on turn 3 or turn 4 things aren't bad.  If you get to return an estate, there's not much effect.  If you have to return a copper though - things start looking little worse.   If your opponent gets to ambassador 2 estates and you just get to ambassador 2 coppers - it's a little worse than going second.  Not great.

Oh, but it gets better, what happens if you miss your ambassador turn because your ambassador is at card 11 or card 12 in the shuffle? Meanwhile, your opponent gets to ambassador on turn 3 or 4.   This will happen to you in about 10% of your ambassador games.  After the opening purchase, lets put an estate as card 11 and ambassador as card 12 in the shuffle and see how our luck fares:  (we also assume our unlucky player does NOT receive a lucky early gold and is forced into a silver silver purchase).

4)  No Ambassador on turn 3/4 (silver silver purchase) vs Ambassador 2 copper
35.1% win for Unlucky
62.4% win for Lucky
2.5% there is a tie.

5)  No Ambassador on turn 3/4 (silver silver purchase) vs Ambassador 1 estate
20.6% win for Unlucky
77.3% win for Lucky
2.1% there is a tie.

6)  No Ambassador on turn 3/4 (silver silver purchase) vs Ambassador 2 estate
15.6% win for Unlucky
82.7% win for Lucky
1.7% there is a tie.

Whoa.  I would put that last one in the solid - you're screwed category.  And if we were playing in real life, you'ld probably hear me rant about it the whole game ;)

What's interesting is if you score an early gold, things may not be as bad:  Lets assume our unlucky player can buy a gold:

7)  No Ambassador on turn 3/4 buys gold (unlucky) vs Ambassador 2 copper
59.2% win for Unlucky
37% win for Lucky
3.8% there is a tie.

8 )  No Ambassador on turn 3/4 buys gold (unlucky) vs Ambassador 1 Estate
48.9% win for Unlucky
48.2% win for Lucky
2.9% there is a tie.

9)  No Ambassador on turn 3/4 buys gold (unlucky) vs Ambassador 2 Estate
38.1% win for Unlucky
56.8% win for Lucky
5.1% there is a tie.

So if you don't get ambassador, but you get an early gold - you may even come out ahead!   However, not even an early gold can not make up for your opponent ambassador 2 estates.  But if you do score an early gold - keep your chin up.  Worst case scenario, you are down one turn. 

While this gives you a pretty good idea of your odds when playing with just big money and ambassador.  Lets take a look at a game involving other cards.  Based off a game I played recently, consider if the following cards are available:

Ambassador, Caravan, Apprentice and Merchant Guild.   

I like this set of test cards, as there is opportunity for purchase at the 3, 4, 5 and 6 level.   (Big money biases our results sometimes, as there is  no benefit to hitting the 4 or 5 in a big money game - and frankly, how many boards are missing 4s and 5s?!)

So the baseline strategy is open Ambassador + Caravan on a 3/4 split.  Purchase up to 5 Caravans, 1 Merchant guild.  Get gold whenever possible and silver otherwise.  How does this fair vs bigmoney (always a good check):

83.9% win for AmbassadorCaravanMerchantGuild
14.8% win for BigMoney
1.3% there is a tie.

Not too bad.

Now let's do a mirror match and throw a little luck in there.  Both players will open ambassador + caravan.  One unfortunate player will get the following sequence:

Turn 3) Copper, Copper, Copper, Copper, Estate,
Turn 4) Caravan, Copper, Copper, Copper, Estate, Estate
Turn 5) Ambassador + 4 Coppers + 1 Silver.

Even with the caravan in play (which misses the reshuffle because it's on turn 4), the ambassador is in position 12 - so no play till turn 5 - and even then no estate.

Compare this to the more fortunate player:

Turn 3) Caravan, Copper, Copper, Copper, Estate, Estate,
Turn 4) Estate, Copper, Copper, Copper, Copper Ambassador

What are you the odds of winning this?

23.1% win for Unlucky
74.8% win for Lucky
2.1% there is a tie.

In this real life scenario - the odds of winning with a little misfortune are actually quite similar to the earlier data.  (Compare with the scenario: Ambassador 1 estate vs no Ambassador).  So I will probably use the above big money data to extrapolate my odds in the future.

What is the value in knowing these numbers?  Well - when you are playing an ambassador opening - it's useful to know where you stand.  If your odds are not great in an equal strategy, mix it up a little.  Play more risky - what have you got to lose?   Defer buying that first province, try something you may otherwise not.

You have noticed that in the above strategy, I did not mention apprentice!   Maybe our unlucky player can add an apprentice to his deck to make a come back:

12.2% win for Unlucky (if buys apprentice)
86.2% win for Lucky
1.6% there is a tie.

Actually - purchasing apprentice makes things worse.  This was a counter intuitive result for myself.   In fact, I've tried adding many variants to this strategy - and adding the apprentice seems to almost always makes things worse.  In fact, if your unlucky player skips apprentice and the lucky player buys apprentice:

35.8% win for Unlucky (skip apprentice)
61.4% win for Lucky (buys an apprentice)
2.8% there is a tie.

Of course simulators don't play perfect - and probably play apprentice poorly in the late game.  The takeaway though is that all it took was for the "lucky" player to make one bad call among otherwise equal strategies - buying the apprentice - and a 2 turn advantage was reduced to a one turn advantage.   So With 10 cards on the table - be vigilant.  If you make just a couple calls better than your opponent you may be able to make up even the worst of ambassador luck.    If you have an unfortunate opening with ambassador, you are like going to be practicing more sportsmanship than dominion skills if your opponent is relatively close to you in skill.

(In case you are curious, here's that last example showing how one sets shuffle luck in Dominulator)
Code: [Select]
        var player1 = Strategies.AmbassadorCaravanApprenticeMerchantGuild.PlayerCustom(playerName: "Unlucky", shouldApprentice:false);
            var player2 = Strategies.AmbassadorCaravanApprenticeMerchantGuild.PlayerCustom(playerName: "Lucky", shouldApprentice: true);                                   
           

            var builder = new GameConfigBuilder();
           
            builder.SetShuffleLuckPerPlayer( new CardCountPair[][] {                                 
                new CardCountPair[] { new CardCountPair(Cards.Copper, 4), new CardCountPair(Cards.Estate, 1),
                                      new CardCountPair(Cards.Copper, 3), new CardCountPair(Cards.Estate, 2),                                                                           
                                      new CardCountPair(Cards.Copper, 4), new CardCountPair(Cards.Estate, 1),
                                      new CardCountPair(Cards.Caravan, 1), new CardCountPair(Cards.Copper, 3), new CardCountPair(Cards.Estate, 2),
                                      new CardCountPair(Cards.Ambassador, 1), new CardCountPair(Cards.Silver, 1), new CardCountPair(Cards.Copper, 4),
                },               

                new CardCountPair[] { new CardCountPair(Cards.Copper, 4), new CardCountPair(Cards.Estate, 1),
                                      new CardCountPair(Cards.Copper, 3), new CardCountPair(Cards.Estate, 2),                                     
                                      new CardCountPair(Cards.Caravan, 1), new CardCountPair(Cards.Copper, 3), new CardCountPair(Cards.Estate, 2),
                                      new CardCountPair(Cards.Ambassador, 1), new CardCountPair(Cards.Copper, 4), new CardCountPair(Cards.Estate, 1),
                },
            });
           
            PlayerAction.SetKingdomCards(builder, player1, player2);

            ComparePlayers(
                player1,
                player2,
                builder.ToGameConfig(),
                firstPlayerAdvantage:false,
                createHtmlReport: true,
                numberOfGames: 1000,
                shouldParallel: false);

11
Simulation / Graphing the end game
« on: October 26, 2013, 02:10:54 pm »
Hey guys.  I've been working on creating some visualizations for Dominulator, and I came across something I thought you would find interesting.   The tl;dr is that performing analysis by averaging data at a given turn is useful for analyzing openings, it has some drawbacks when analyzing the end game.  For that, a different approach is needed.

Consider the following strategy involving Salvager, lookout, Library, Highway and Festival.   We open with a salvager and lookout, trash quickly, picking up highways festivals and a couple of libraries.   The idea is to get an uber turn where you have lots of coin, lots of buys, and provinces are cheap.  Here's the precise purchase/trash/action order.

Code: [Select]
private static ICardPicker PurchaseOrder()
            {
                var highPriority = new CardPickByPriority(
                     CardAcceptance.For(Cards.Province, ShouldBuyProvinces),
                     CardAcceptance.For(Cards.Duchy, gameState => CountAllOwned(Cards.Province, gameState) >= 3),
                     CardAcceptance.For(Cards.Estate, gameState => CountOfPile(Cards.Province, gameState) <= 1),
                     CardAcceptance.For(Cards.Salvager, gameState => CountAllOwned(Cards.Copper, gameState) >= 6 && CountAllOwned(Cards.Salvager, gameState) == 0),
                     CardAcceptance.For(Cards.Lookout, gameState => CountAllOwned(Cards.Copper, gameState) >= 6 && CountAllOwned(Cards.Lookout, gameState) == 0),
                     CardAcceptance.For(Cards.Silver, gameState => CountAllOwned(Cards.Silver, gameState) + CountAllOwned(Cards.Festival, gameState) < 2)
                     );
               
                var buildOrder = new CardPickByBuildOrder(
                    CardAcceptance.For(Cards.Festival),
                    CardAcceptance.For(Cards.Library),
                    CardAcceptance.For(Cards.Festival),
                    CardAcceptance.For(Cards.Highway),
                    CardAcceptance.For(Cards.Highway),
                    CardAcceptance.For(Cards.Festival),
                    CardAcceptance.For(Cards.Festival),
                    CardAcceptance.For(Cards.Library),
                    CardAcceptance.For(Cards.Festival)
                    );

                var lowPriority = new CardPickByPriority(
                    CardAcceptance.For(Cards.Highway));

                return new CardPickConcatenator(highPriority, buildOrder, lowPriority);
            }

            private static bool ShouldBuyProvinces(GameState gameState)
            {
                return CostOfCard(Cards.Province, gameState) <= 4 || CountAllOwned(Cards.Province, gameState) > 0;
            }

            private static CardPickByPriority ActionOrder()
            {
                return new CardPickByPriority(
                           CardAcceptance.For(Cards.Lookout),
                           CardAcceptance.For(Cards.Highway),
                           CardAcceptance.For(Cards.Festival),
                           CardAcceptance.For(Cards.Salvager),
                           CardAcceptance.For(Cards.Necropolis),
                           CardAcceptance.For(Cards.Library)
                           );
            }           

            private static CardPickByPriority TrashOrder()
            {
                return new CardPickByPriority(                           
                           CardAcceptance.For(Cards.Curse),
                           CardAcceptance.For(Cards.Lookout, gameState => CountAllOwned(Cards.Copper, gameState) <= 4),                                               
                           CardAcceptance.For(Cards.Estate),
                           CardAcceptance.For(Cards.OvergrownEstate),
                           CardAcceptance.For(Cards.Hovel),
                           CardAcceptance.For(Cards.Necropolis),
                           CardAcceptance.For(Cards.Silver, gameState => gameState.Self.ExpectedCoinValueAtEndOfTurn == 4 && CardBeingPlayedIs(Cards.Salvager, gameState)),
                           CardAcceptance.For(Cards.Copper),
                           CardAcceptance.For(Cards.Silver));
            }     

How well, how does this engine compare to big money?  Quite well in fact.   This engine wins 82% of the time:


A more detailed breakdown shows that the engine wins by quite a large margin a majority of the games.  8 points or more ...


And the average coin graph doesn't immediately go against expectations.  Big money is ahead in average spending power, but the engine supercedes eventually.


So it looks like the engine does quite well vs big money.   Lets take a look at the average victory points per turn.

Hmm.  That's weird.  It looks like on average, at any given turn, bigmoney is ahead.   Seems like the engine never gets ahead.  Perhaps the notion of an average is misleading.  Consider for example 3 games being played with the following scores:  30-25, 31-28, 10-40.   Even though the first player wins a majority of the games, the second players average score would be higher.   Let's try something other than average.  How about we just count who is ahead at every turn, and ignore by how much. 


Equally unexpected.  It seems like probabilistically, the engine is never winning - yet it usually wins games.  How is this possible? 

I thought about it for a bit, and I realized that the problem is with averaging data based on turn count.  This is misleading for analyzing the end of the game.  This particular engine is going to peak in strength at around turn 14-16 or so.   It will then attempt to buy many provinces and duchies all at once.   Unfortuantely, the uber turn doesn't happen on the same turn every game.   Consider 2 games, one where the uber turn happens on turn 15, and one where the uber turn happens on turn 16.  Average just those 2 games, you will find that the average score for just half of what the actual score is for those turns.   As a result of this effect, it never looks like the engine is ahead, even though it usually wins.

When averaging turns measured from the beginning of the game the end game data does not lined up.   It becomes difficult to see how a strategy is adjusting to finish the game.   Instead of counting turn 1, turn 2, etc, lets line the data up differently!   We will play though the entire game, find out where the game ends, call that turn 0, and count backwards to label the other turns.  The second last turn is -1, third last turn -2 etc etc.   Now the end game strategy becomes apparent.   


You can easily see that the engine shoots for an uber turn and usually wins on average 35 points to 25 ...   

Now while this approach is good for analyzing the end game, it would be unsuitable for analyzing opennings.  (using similar logic).    There are two approaches to counting turns - counting turns from beginning and counting from the end of the game.  Both are needed to comprehensively understand a strategy's performance

Full comparison report attached.

12
Hey guys.  Here's a game I played last night:

Butcher, Great hall, Horn of Plenty, Horse Traders, Minion, Pawn, Remake, Soothsay, Stonemason, Swindler

We disagreed on the opening.  Horse traders into minion, or Remake to thin the deck.  We both agreed we wanted lots of soothsayer action.   So I wrote up a strategy to simulate roughly what we did.  Can you guess which simulation does better vs big money?  Which simulator wins head to head?   Have a good idea of how you would have played this set of cards?  Let me know what your build was, and I may code it up for you.

Spoiler:


89.4% win for HorseTraderSoothsayerMinionGreatHall
8.8% win for BigMoney
1.8% there is a tie.

82.3% win for RemakeSoothsayer
17% win for BigMoney
0.7% there is a tie.

44.6% win for RemakeSoothsayer
53.3% win for HorseTraderSoothsayerMinionGreatHall
2.1% there is a tie.


Here's the Horse traders into minion variant:

Code: [Select]

            class MyPlayerAction
                : PlayerAction
            {
                 ...

                public override PlayerActionChoice ChooseBetween(GameState gameState, IsValidChoice acceptableChoice)
                {
                    if (gameState.CurrentCardBeingPlayed.Is<CardTypes.Minion>())
                    {
                        if (CountInHand<CardTypes.Minion>(gameState) >= 2)
                            return PlayerActionChoice.PlusCoin;

                        if (HasCardInHand<CardTypes.Butcher>(gameState) && HasCardInHand<CardTypes.Gold>(gameState))
                            return PlayerActionChoice.PlusCoin;

                        if(gameState.Self.ExpectedCoinValueAtEndOfTurn + CountInHand<CardTypes.Minion>(gameState) * 2 >= 6)
                            return PlayerActionChoice.PlusCoin;

                        if (HasCardInHand<CardTypes.Soothsayer>(gameState))
                        {                           
                            return PlayerActionChoice.PlusCoin;                           
                        }

                        return PlayerActionChoice.Discard;
                    }
               
                    return base.ChooseBetween(gameState, acceptableChoice);
                }
            }

            private static CardPickByPriority PurchaseOrder(bool shouldButcher)
            {
                return new CardPickByPriority(
                           CardAcceptance.For<CardTypes.Province>    (CardAcceptance.AlwaysMatch, CardAcceptance.OverPayMaxAmount),
                           CardAcceptance.For<CardTypes.Duchy>       (gameState => CountOfPile<CardTypes.Province>(gameState) <= 6, CardAcceptance.OverPayMaxAmount),
                           CardAcceptance.For<CardTypes.Soothsayer>  (1),
                           CardAcceptance.For<CardTypes.Butcher>     (1, gameState => CountAllOwned<CardTypes.Minion>(gameState) >= 3),
                           CardAcceptance.For<CardTypes.Gold>        (gameState => CountAllOwned<CardTypes.Minion>(gameState) >= 3),                           
                           CardAcceptance.For<CardTypes.Minion>      (),
                           CardAcceptance.For<CardTypes.HorseTraders>(1),
                           CardAcceptance.For<CardTypes.Silver>      (1),
                           CardAcceptance.For<CardTypes.GreatHall>   (gameState => CountOfPile<CardTypes.GreatHall>(gameState) >= 1),
                           CardAcceptance.For<CardTypes.Estate>      (gameState => CountOfPile<CardTypes.Province>(gameState) <= 4),
                           CardAcceptance.For<CardTypes.Silver>      (),
                           CardAcceptance.For<CardTypes.Estate>      (gameState => CardBeingPlayedIs<CardTypes.Butcher>(gameState))
                           );
            }

            private static CardPickByPriority ActionOrder()
            {
                return new CardPickByPriority(
                           CardAcceptance.For<CardTypes.GreatHall>(),
                           CardAcceptance.For<CardTypes.Minion>(),
                           CardAcceptance.For<CardTypes.Butcher>(),
                           CardAcceptance.For<CardTypes.Soothsayer>(),
                           CardAcceptance.For<CardTypes.HorseTraders>());
            }

            private static CardPickByPriority TrashOrder()
            {
                return new CardPickByPriority(
                        CardAcceptance.For<CardTypes.Gold>(gameState => CardBeingPlayedIs<CardTypes.Butcher>(gameState)),
                        CardAcceptance.For<CardTypes.Soothsayer>(gameState => CardBeingPlayedIs<CardTypes.Butcher>(gameState)),
                        CardAcceptance.For<CardTypes.HorseTraders>(gameState => CardBeingPlayedIs<CardTypes.Butcher>(gameState)),
                        CardAcceptance.For<CardTypes.Curse>(),                       
                        CardAcceptance.For<CardTypes.Copper>(gameState => gameState.Self.ExpectedCoinValueAtEndOfTurn < 8),
                        CardAcceptance.For<CardTypes.Estate>());
            }




Here's the Remodel variant:

Code: [Select]
            private static CardPickByPriority PurchaseOrder()
            {
                return new CardPickByPriority(
                           CardAcceptance.For<CardTypes.Province>(),
                           CardAcceptance.For<CardTypes.Duchy>(gameState => CountOfPile<CardTypes.Province>(gameState) <= 4),
                           CardAcceptance.For<CardTypes.Soothsayer>(1),                                                     
                           CardAcceptance.For<CardTypes.Gold>(1),
                           CardAcceptance.For<CardTypes.Soothsayer>(2),
                           CardAcceptance.For<CardTypes.Gold>(),
                           CardAcceptance.For<CardTypes.Duchy>(gameState => CardBeingPlayedIs<CardTypes.Remake>(gameState)),
                           CardAcceptance.For<CardTypes.Remake>(1),
                           //CardAcceptance.For<CardTypes.Remake>(gameState => ((double)CountAllOwned(TrashOrderWithoutRemake(), gameState)) / gameState.Self.AllOwnedCards.Count > 0.4),
                           CardAcceptance.For<CardTypes.Estate>(gameState => CountOfPile<CardTypes.Province>(gameState) <= 2),
                           CardAcceptance.For<CardTypes.GreatHall>(gameState => CountAllOwned<CardTypes.Silver>(gameState) >= 2),
                           CardAcceptance.For<CardTypes.Silver>()
                           );
            }

            private static CardPickByPriority ActionOrder()
            {
                return new CardPickByPriority(
                           CardAcceptance.For<CardTypes.GreatHall>(),
                           CardAcceptance.For<CardTypes.Soothsayer>(),
                           CardAcceptance.For<CardTypes.Remake>(ShouldPlayRemake));
            }

            private static CardPickByPriority TrashOrder()
            {
                return new CardPickByPriority(
                        CardAcceptance.For<CardTypes.Curse>(),
                        CardAcceptance.For<CardTypes.Estate>(gameState => CountOfPile<CardTypes.Province>(gameState) > 2),
                        CardAcceptance.For<CardTypes.Remake>(),
                        CardAcceptance.For<CardTypes.Copper>());
            }

            private static CardPickByPriority TrashOrderWithoutRemake()
            {
                return new CardPickByPriority(
                        CardAcceptance.For<CardTypes.Curse>(),
                        CardAcceptance.For<CardTypes.Estate>(gameState => CountOfPile<CardTypes.Province>(gameState) > 2),                       
                        CardAcceptance.For<CardTypes.Copper>());
            }

            private static bool ShouldPlayRemake(GameState gameState)
            {               
                return CountInHandFrom(TrashOrderWithoutRemake(), gameState) >= 2;
            }

13
Simulation / Dominulator: A flexible dominion engine simulator
« on: October 04, 2013, 02:00:42 pm »
Hey All, I would like to introduce you to a new simulator for Dominion that I have been working on.  Now called Dominulator

What makes this simulator different?

The other simulators I have seen have an emphasis on allowing non-programmers to easily create new strategies.  There are many obvious advantages this approach.  Sometimes, however, you may be interested in expressing a strategy that is tough to capture with a restricted language.   

This simulator focuses on creating a game engine that is completely separate from play decisions.  Every play decision should be able to be customized - but this also involves writing to a more complicated interface using c# code.   On top of the game engine, I have built enough infrastructure to provide high level strategies similar to what the other simulators have done.  You can create a buy order, trash order etc.  The strategies created tend to be relatively readable.

The goal is to eventually be complete, with all cards playable, and with all bugs squashed ;)   

Its not done yet - but done enough I thought I would share.  I have tested it with some cards from all sets - including Guilds, and Dark ages.   It can simulate games with Coin Tokens, and Ruins and Shelters, and Spoils etc etc...

Where can I find the code and learn more?

https://github.com/NathanTeeuwen/Dominulator

There is a readme in the GIT repository that I will be trying to keep up to date. 

Please make feature requests or report bugs by creating Issues on Github.   You can also reply to this post, and I will try to keep on top of it. 

If you would like to make a contribution, let me know.

14
Simulation / How much difference the shelters can make?
« on: October 02, 2013, 06:52:04 pm »
I played an interesting game the other day, and got me thinking, how much difference do the shelters really make?  Well, with this combination of cards, it really isnt better than big money with a 53% win rate.  With shelters, it has a 89% win rate.  Quite the difference.  Lets take a closer look what's going on:

The cards for the combo are Armory, Conspirator, Forager and Great hall.

The strategy is simple.  Open Armory to gain cards, and forager to trash cards.  Gain great halls and conspirators in a 1:1 ratio until you have enough money to buy provinces.

The interesting thing is how this strategy performs with shelters and without shelters:

89.1% win rate again Big money with shelters
53.9% win rate again Big money with estates

Lets take a closer look at each shelter and what effect is having. 

Hovel
If we pretend that the hovel card does not have a reaction - i.e. it can no longer trash itself on gaining a victory.  That brings the win rate down to 74%.   That's 15% win rate just for the reaction!

Necropolis
The default strategy actually attempts to keep the necroplis.  The +2 actions are good for starting off the conspirator chain, which we like.  It also allows us to play the armory for conspirator, top decking it, and then still have actiosn left to draw it for play this turn.  If we trash the necropolis after the overgrown estate, then the win rate goes down to 83%.   

Overgrown estate
The +1 card from trashing this card is very minimal.   1% difference in win rate.

Opportunity cost of points vs Shelters
One of the benefits of estates over shelters is they have victory points.   If our combo is trashing the starting estates, that gives big money a 3 point lead that must be overcome.  A shelter game typically favors the trashing engine.   If we pretend the shelters each worth 1 point, the win rate for the combo is down to 83%.   

In summary:
  • 15% comes from hovel
  • 1% comes from overgrown estate
  • 5% comes from necropolis
  • 5% comes from opportunity cost of victory points
So there you have it.  The hovel reaction actually had the largest impact on win rate.  They are not addiditive effects, in combination this produces 36% win rate difference for this strategy.

The above analysis is for only one strategy, your mileage will vary.   This set of cards is particularly sensitive to the bonus trashing from hovel.   Dont ignore the impact of shelters!

Here's the code for the strategy:

Code: [Select]
private static CardPickByPriority PurchaseOrder()
{
    return new CardPickByPriority(
                CardAcceptance.For<CardTypes.Armory>(gameState => CountAllOwned<CardTypes.Armory>(gameState) < 1),
                CardAcceptance.For<CardTypes.Forager>(gameState => CountAllOwned<CardTypes.Forager>(gameState) < 1),
                CardAcceptance.For<CardTypes.Province>(),
                CardAcceptance.For<CardTypes.Duchy>(gameState => CountOfPile<CardTypes.Province>(gameState) <= 1),                           
                CardAcceptance.For<CardTypes.Estate>(gameState => CountOfPile<CardTypes.Province>(gameState) == 0),
                CardAcceptance.For<CardTypes.GreatHall>(gameState => gameState.players.CurrentPlayer.AvailableBuys > 1 && gameState.players.CurrentPlayer.AvailableCoins == 6),
                CardAcceptance.For<CardTypes.GreatHall>(gameState => gameState.players.CurrentPlayer.Hand.HasCard<CardTypes.Hovel>()),
                CardAcceptance.For<CardTypes.GreatHall>(gameState => CountAllOwned<CardTypes.GreatHall>(gameState) < CountAllOwned<CardTypes.Conspirator>(gameState)),
                CardAcceptance.For<CardTypes.Conspirator>(),
                CardAcceptance.For<CardTypes.GreatHall>());
}

private static CardPickByPriority ActionOrder()
{
    return new CardPickByPriority(
                CardAcceptance.For<CardTypes.Necropolis>(),
                CardAcceptance.For<CardTypes.Armory>(gameState => gameState.players.CurrentPlayer.AvailableActions > 0),                           
                CardAcceptance.For<CardTypes.GreatHall>(),
                CardAcceptance.For<CardTypes.Conspirator>(gameState => gameState.players.CurrentPlayer.CountCardsPlayedThisTurn >= 2),
                CardAcceptance.For<CardTypes.Forager>(gameState => HasCardFromInHand(TrashOrder(), gameState)),                           
                CardAcceptance.For<CardTypes.Conspirator>(),
                CardAcceptance.For<CardTypes.Armory>());
}

private static CardPickByPriority TrashOrder()
{
    return new CardPickByPriority(                           
                CardAcceptance.For<CardTypes.OvergrownEstate>(),
                CardAcceptance.For<CardTypes.Estate>(),                           
                CardAcceptance.For<CardTypes.Necropolis>(),
                CardAcceptance.For<CardTypes.Copper>(),
                CardAcceptance.For<CardTypes.Hovel>());
}

15
This topic was inspired by the following forum post, but this forum seems more appropriate to the discussion about simulation.  Please see this topic for discussion:

http://forum.dominionstrategy.com/index.php?topic=9456.0

the tl;dr is that you can beat big money over 95% of the time quite easily with the cards in that post.

It took a bit to get the simulation working, but a tuned engine handidly can beat big money over 96% of the time on a board with Rats, Watchtower, Armory, Wandering Minstrell amd Bridge.   It also beats many many other strategies I have tried it against.   When comparing against BigMoney, here's some interesting things I learned.

For an opening build order, my initial guess was ok, but not optimal.
  • Initial guess: Armory, Silver, WanderingMinstrel, Watchtower, Rats, Watchtower:   89% win rate
  • Rats, Watchtower, Watchtower, Armory: 93.5% win rate
  • Rats, Watchtower, Armory, Watchtower: 95.3% win rate
  • Armory, Watchtower, Rats, Watchtower: 96.7% win rate

The quickest build seems to favor getting Watchtower/Rats fairly early for maximal trashing.

I confirmed the suspicion mentioned in the other post that adding a jester actually hurts vs big money.  Adding a jester brings the win rate down to 82%.
What effect does the armory have on the strategy?  If you ignore the armory, your winrate goes down to 82%.
Dont want to get the rats for the trashing?  Your win rate goes down to 85%
Wandering minstrell allows you to order the actions placed on top of the deck.  Just placing the cards randomly results in a 83.9%.  Using a relatively naive ordering, achieved the 96% win rate.
What effect does shelters have?  If you play with estates instead of shelters, win rate goes down to 90%.
3 watchtowers seems to be the right number.  After all, u need a wandering minstrell for every watchtower you play to keep chaining...

Furthermore, a tuned engine with these cards can beat out otherwise simple but strong contenders:
  • 77.6% win vs DoubleWitch
  • 72.6% win vs DoubleJack
It can go toe to toe with interesting engine combinations, for example:
  • 60.4% win vs EmbassyTunnelSpiceMerchantPlaza
  • 53.7% win vs FishingVillageChapelPoorHouse
  • 52.3% win vs Rebuild
It can even take some games off of a deck tuned to beat big money 99.89% of the time.  (though the strategies aren't tuned against each other)
  • 33.8% win vs GardensBeggarIronworks

Here's the complete strategy, using the simulator I've been playing around with.

Code: [Select]
private static ICardPicker PurchaseOrder()
{
    var highPriority = new CardPickByPriority(
            CardAcceptance.For<CardTypes.Province>(gameState => gameState.players.CurrentPlayer.AvailableBuys >= 4 || CountAllOwned<CardTypes.Province>(gameState) > 0),
            CardAcceptance.For<CardTypes.Duchy>(gameState => CountAllOwned<CardTypes.Province>(gameState) >= 3),
            CardAcceptance.For<CardTypes.Estate>(gameState => CountOfPile<CardTypes.Province>(gameState) <= 1));
                               
    var buildOrder = new CardPickByBuildOrder(
        new CardTypes.Armory(),
        new CardTypes.Watchtower(),                   
        new CardTypes.Rats(),                   
        new CardTypes.Watchtower());
               

    var lowPriority = new CardPickByPriority(
            CardAcceptance.For<CardTypes.Bridge>(ShouldBuyBridge),                       
            CardAcceptance.For<CardTypes.WanderingMinstrell>(),                       
            CardAcceptance.For<CardTypes.Watchtower>(gameState => CountAllOwned<CardTypes.Watchtower>(gameState) < 3));

    return new CardPickConcatenator(highPriority, buildOrder, lowPriority);
}

private static bool ShouldBuyBridge(GameState gameState)
{
    return CountAllOwned<CardTypes.WanderingMinstrell>(gameState) > CountAllOwned<CardTypes.Bridge>(gameState) + CountAllOwned<CardTypes.Watchtower>(gameState) + 1;
}

private static bool ShouldPlayArmory(GameState gameState)
{
    return CountAllOwned<CardTypes.Bridge>(gameState) < 5;
}

private static bool CanPlayTerminalWhileChaining(GameState gameState)
{
    return gameState.players.CurrentPlayer.AvailableActions >= 1;
}

private static bool CanPlay2TerminalsWhileChaining(GameState gameState)
{
    return gameState.players.CurrentPlayer.AvailableActions >= 2;
}

private static bool WillRatsComboWork(GameState gameState)
{
    return HasCardInHand<CardTypes.Watchtower>(gameState) &&
            HasCardInHand<CardTypes.Rats>(gameState) &&
            HasCardFromInHand(TrashOrderWithoutRats(), gameState);
}

private static CardPickByPriority ActionOrder()
{
    return new CardPickByPriority(
                CardAcceptance.For<CardTypes.Armory>(gameState => CanPlay2TerminalsWhileChaining(gameState) && ShouldPlayArmory(gameState)),
                CardAcceptance.For<CardTypes.Jester>(gameState => CanPlay2TerminalsWhileChaining(gameState)),
                CardAcceptance.For<CardTypes.Bridge>(gameState => CanPlay2TerminalsWhileChaining(gameState)),
                CardAcceptance.For<CardTypes.Watchtower>(gameState => CanPlayTerminalWhileChaining(gameState) && !WillRatsComboWork(gameState) && gameState.players.CurrentPlayer.Hand.Count() <= 5),
                CardAcceptance.For<CardTypes.Rats>(gameState => WillRatsComboWork(gameState)),
                CardAcceptance.For<CardTypes.WanderingMinstrell>(),
                CardAcceptance.For<CardTypes.Necropolis>(),
                CardAcceptance.For<CardTypes.Jester>(),
                CardAcceptance.For<CardTypes.Armory>(ShouldPlayArmory),
                CardAcceptance.For<CardTypes.Bridge>(),                           
                CardAcceptance.For<CardTypes.Watchtower>());
}

// dicard order used to tune which actions to put back with wandering minstrell
private static CardPickByPriority DiscardOrder()
{
    return new CardPickByPriority(
        CardAcceptance.For<CardTypes.Armory>(),
        CardAcceptance.For<CardTypes.Bridge>(),
        CardAcceptance.For<CardTypes.Necropolis>(),
        CardAcceptance.For<CardTypes.Watchtower>(),
        CardAcceptance.For<CardTypes.WanderingMinstrell>(),
        CardAcceptance.For<CardTypes.Rats>());
}

private static CardPickByPriority TrashOrder()
{
    return new CardPickByPriority(
                CardAcceptance.For<CardTypes.Rats>(gameState => CountAllOwned<CardTypes.Rats>(gameState) > 0),
                CardAcceptance.For<CardTypes.Curse>(),
                CardAcceptance.For<CardTypes.Estate>(),
                CardAcceptance.For<CardTypes.OvergrownEstate>(),                         
                CardAcceptance.For<CardTypes.Hovel>(),
                CardAcceptance.For<CardTypes.Necropolis>(),
                CardAcceptance.For<CardTypes.Copper>());
}

private static CardPickByPriority TrashOrderWithoutRats()
{
    return new CardPickByPriority(
                CardAcceptance.For<CardTypes.Curse>(),
                CardAcceptance.For<CardTypes.Estate>(),
                CardAcceptance.For<CardTypes.OvergrownEstate>(),
                CardAcceptance.For<CardTypes.Hovel>(),
                CardAcceptance.For<CardTypes.Necropolis>(),                           
                CardAcceptance.For<CardTypes.Copper>()
                );
}

Pages: [1]

Page created in 0.058 seconds with 17 queries.