At least

at most

 
   


sdfsdfsdfsfd

Show/Hide Design Details

Conception

I set out to design a Dominion set randomizer that might eliminate "bad draws." Taking the completely random approach to selecting your 10 cards can be fun, but it becomes less fun when you don't have a buy card, or if you don't have any village cards. Hence my idea was born to enable randomization in picking Dominion games, but with some customization.

Requiring a +buy or a village was obvious, but then I decided why not just increase the options? I like having alternate victory point possibilities, and sometimes getting hit repeatedly with hand size reducing attacks makes for a frustrating experience. Then I just went through different card themes and whether it would be reasonable that someone might absolutely want to include or exclude one.

and now for some dirty details ...

Strongly enforced set restrictions

The set restrictions were one of the first problems I ran into. A person doesn't have Seaside? No problem, just exclude it and make sure they can't demand a duration card. But what if they do have Seaside, and really want a duration card, but for some reason just don't want to use the rest of Seaside? "Why would someone want to do that?" you might ask. Doesn't matter, it's better to just include the option for the user. That's where the idea of strongly enforced set restrictions came from.

Pre vs post

The next issue was when to do a "general populate" with respect to adding cards the user has requested. Initially I thought I would pick 10 cards at random and then replace some as needed to make sure all the requested cards were included. However, it seemed like "at least" would essentially be "exactly one." For example, the user requests +buy and nothing else. Pick 10 cards at random from the selected expansions. "Is there a +buy in the set already? No? OK, put one in. Yes? OK, we're done here." Including the requested cards before filling in the rest of the kingdom randomly made more sense to me. That opens the possibility of more than one of the requested card type.

Order of operations and unique types

A user requests both a +buy and a village card. The random card generator puts a Woodcutter in the kingdom as the +buy, and a Village for the village type. OK that looks good, but what if they get a Festival for the +buy? The Festival also falls under the village category, so do we add another village card? If it had picked Woodcutter first instead we would still need another card to play the village role, but not the other way around. I don't think there is a best option, and right now it does not check for overlapping card types like the Festival. In that situation, you might get stuck with the Festival acting as both your +buy and your village.

Potions

The recommended number of potion cards, i.e. cards that cost potion as well as coins, is 3 - 5. You can require potion cards and use whatever upper/lower bound you like, but what if you decide to play your luck and look at all 206 kingdom cards? Do you really want to get stuck with just one card that costs a potion? Maybe you don't care, but again it is better to have the option available.

Moats moats moats!

The "must have moat/reaction" options were massive undertakings. Large pieces for this program were redone specifically to accomodate these two options, which brings me to ...

Young Witch

This card was the bane of getting this program to work. Everything must consider the possibility of the inclusion of the Young Witch and the need for an 11th kingdom card. Side note: The Moat will not be the bane card.

Future Customization

The ability to include or exclude individual cards was one of my original intentions, but has been put in the "to do" list for now.

Card type details

  • villages types: did not include Tournament (Trusty Steed), Hermit (Madman), or Knights (Dame Molly), Tribute, Ironmonger, Golem, Herald, King's Court, Throne Room, or Procession
  • +buy types: did not include Tournament (Princess), Black Market, City, Knights (Sir martin), or Tactician
  • curser types: did not include Ambassador or Masquerade; included Torturer, Tournament (Followers), Jester, Embargo
  • hand size attack types: did not include Bureaucrat or Mountebank; included Tournament (Followers), Knights (Sir Michael), Torturer
  • trasher types: did not include Knights (Dame Anna), Procession, Rebuild, or Watchtower; included Urchin (Mercenary), Transmute, Farmland, Spice Merchant, Jack of all Trades, Hermit, Loan, Moneylender, and Mine

Algorithm and Design

The goal is to selected 10 (sometimes 11) Card() objects and add them to the final CardCollection() kingdom.

The conditions set by the user, such as which sets to include or any "at least" conditions, are used to build a query for the database of cards. From there, individual Card() objects are constructed and added to the CardCollection() of available cards.

A CardCollection() of extra cards may need to be utilized in case a weak restriction is put on the sets to include and a card that is not in one of the desired sets is requested. For each of those instances, the collection is constructed and one card is chosen randomly to be added to the kingdom.

For each "at least" condition, the subset of the CardCollection() of available cards that meet the given criteria is extracted. Assuming the kingdom has room (either there are less than 10 cards; or there is a Young Witch without a bane), one of these cards is added to the kingdom and then deleted from the set of available cards to avoid repetition.

Once all "at least" cards have been added, fill in the remainder of the kingdom (including a bane) with any available cards, assuming there are enough available cards to do so. When there are not, it may reach into other sets that were not included if it can (set restrictions are not strongly enforced). Also, more cards must be made available if there is a chance of running over the potion limit upper bound, and potion cards are removed from the collection of available cards until there is no chance of exceeding the limit.

Finally, check to ensure any "if ... then" requirements are met. If there was a moat requested with attacks, look for any attack cards. If there are, remove a card that was not added at the beginning as an "at least" card that is also not an attack card (because this may be the only attack card ... the code does not currently check for multiple attacks). Do the same for the reaction requirement. If there is at least one potion, it will replace non-potions with potions in the same way until reaching the lower bound.

The kingdom is then sorted and displayed.