|
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.
|