Adds Draw One support

This commit is contained in:
Nemo 2020-06-14 02:36:04 +05:30
parent f4df68533b
commit 3e64db3c10
4 changed files with 63 additions and 26 deletions

View File

@ -107,12 +107,13 @@ We subdivide the score into the following sections:
### Missing Constraints ### Missing Constraints
- [ ] Symbol(■) - Draw One Card - [x] Symbol (■) - Draw One Card
- [ ] Symbol - Second card face up - [ ] Symbol (**=**) - Second card face up
- [ ] Symbol - Second card face down - [ ] Symbol (≂) - Second card face down
- [ ] Symbol (✠) - Simultaneous play - [ ] Symbol (✠) - Simultaneous play
- [ ] Since the model misses out on the turn-dynamics, and treats symbols as global counters (instead of being attached to specific cards), there are some additional constraints that will be required. Without these, I'm expecting to see the same card being used for multiple symbols. Some sort of **Symbol counter** per round that keeps track of total number of cards you've claimed for symbols would be a better approach. - [ ] Since the model misses out on the turn-dynamics, and treats symbols as global counters (instead of being attached to specific cards), there are some additional constraints that will be required. Without these, I'm expecting to see the same card being used for multiple symbols. Some sort of **Symbol counter** per round that keeps track of total number of cards you've claimed for symbols would be a better approach.
- [ ] **Additional Card Play**. Every round, all players can opt to play one extra card per artist they've already played. Note that this rule is very ambigously worded in the rules. I'm planning to implement the "blessed" variant. See https://boardgamegeek.com/thread/473713/playing-additional-cards-during-scoring for more details. - [ ] **Additional Card Play**. Every round, all players can opt to play one extra card per artist they've already played. Note that this rule is very ambigously worded in the rules. I'm planning to implement the "blessed" variant. See https://boardgamegeek.com/thread/473713/playing-additional-cards-during-scoring for more details.
- [ ] In case `DrawOne` card is the last card of a round, then `PlayableCards` for that round does not increase by 1, but only for the subsequent rounds. Since I'm maintaining awards as a boolean on the (Round,Artist) tuple, this becomes quite hard to model. Unless this gets violated in the winning entries, I don't plan to model this.
## TODO ## TODO

19
drawone.mzn Normal file
View File

@ -0,0 +1,19 @@
array[Rounds,Players,Artists] of var bool: DrawOneCard;
% Total Playable Cards for any round are set equal to the Starting Hand
array[Rounds,Players] of var int: PlayableCards;
% Playable Cards in any round = Starting Cards + Draw One cards that give you an extra playable card
constraint forall(p in Players, r in Rounds) (
PlayableCards[r,p] = StartingCardsInHand[r,p] + sum(a in Artists) (DrawOneCard[r,p,a])
);
% Every artist only has a single Draw One Card
constraint forall(a in Artists) (
sum(p in Players, r in Rounds) (DrawOneCard[r,p,a]) = 1
);
% Isolated count for DrawOne, you can only play your draw one, if you've atleast played that artist this round
constraint forall(p in Players, r in Rounds, a in Artists) (
visible_count_per_round_per_artist_per_player[r,p,a] >= DrawOneCard[r,p,a]
);

View File

@ -8,9 +8,10 @@ include "artists.mzn";
include "dealing.mzn"; include "dealing.mzn";
% Ignoring these for now % Ignoring these for now
% include "double.mzn"; % include "double.mzn";
% include "drawone.mzn"; include "drawone.mzn";
% include "hidden.mzn"; % include "hidden.mzn";
% include "simultaneous.mzn"; % include "simultaneous.mzn";
include "symbols.mzn";
/* /*
This file includes the core gameplay rules This file includes the core gameplay rules
@ -42,18 +43,26 @@ constraint forall(r in Rounds, p in Players) (
% Calculate maximum cards any player can play in first round % Calculate maximum cards any player can play in first round
array[Rounds,Players] of var int: StartingCardsInHand; array[Rounds,Players] of var int: StartingCardsInHand;
% Round 1 Starting Hand is 13 cards
constraint forall(p in Players) (StartingCardsInHand[Round1,p] = CardsDealtPerRound[Round1]); % Starting Cards for First Round = Cards Dealt
constraint forall(p in Players) ( constraint forall(p in Players) (
StartingCardsInHand[Round2,p] = StartingCardsInHand[Round1,p] - TotalCardsPlayed[Round1,p] + CardsDealtPerRound[Round2] StartingCardsInHand[Round1,p] = CardsDealtPerRound[Round1]
);
constraint forall(p in Players) (
StartingCardsInHand[Round3,p] = StartingCardsInHand[Round2,p] - TotalCardsPlayed[Round2,p] + CardsDealtPerRound[Round3]
);
constraint forall(p in Players) (
StartingCardsInHand[Round4,p] = StartingCardsInHand[Round3,p] - TotalCardsPlayed[Round3,p] + CardsDealtPerRound[Round4]
); );
% Playable Card Calculation in drawone.mzn
% Starting cards for subsequent rounds = Playable Cards from previous round - Cards Played + cards dealt
constraint forall(p in Players) (
StartingCardsInHand[Round2,p] = PlayableCards[Round1,p] - TotalCardsPlayed[Round1,p] + CardsDealtPerRound[Round2]
);
constraint forall(p in Players) (
StartingCardsInHand[Round3,p] = PlayableCards[Round2,p] - TotalCardsPlayed[Round2,p] + CardsDealtPerRound[Round3]
);
constraint forall(p in Players) (
StartingCardsInHand[Round4,p] = PlayableCards[Round3,p] - TotalCardsPlayed[Round3,p] + CardsDealtPerRound[Round4]
);
% For every round, you must start with more cards than you play
constraint forall(r in Rounds, p in Players) ( constraint forall(r in Rounds, p in Players) (
StartingCardsInHand[r,p] >= TotalCardsPlayed[r,p] StartingCardsInHand[r,p] >= TotalCardsPlayed[r,p]
); );
@ -82,39 +91,32 @@ constraint first_player[Round4] = if last_player[Round3] = card(Players) then 1
constraint Pn1 = if (first_player[Round1] < last_player[Round1]) then constraint Pn1 = if (first_player[Round1] < last_player[Round1]) then
first_player[Round1]..last_player[Round1] first_player[Round1]..last_player[Round1]
else else
Players diff (first_player[Round1]..last_player[Round1]) Players diff (first_player[Round1]..last_player[Round1])
endif; endif;
constraint Pn2 = if (first_player[Round2] < last_player[Round2]) then constraint Pn2 = if (first_player[Round2] < last_player[Round2]) then
first_player[Round2]..last_player[Round2] first_player[Round2]..last_player[Round2]
else else
Players diff first_player[Round2]..last_player[Round2] Players diff first_player[Round2]..last_player[Round2]
endif; endif;
constraint Pn3 = if (first_player[Round3] < last_player[Round3]) then constraint Pn3 = if (first_player[Round3] < last_player[Round3]) then
first_player[Round3]..last_player[Round3] first_player[Round3]..last_player[Round3]
else else
Players diff first_player[Round3]..last_player[Round3] Players diff first_player[Round3]..last_player[Round3]
endif; endif;
constraint Pn4 = if (first_player[Round4] < last_player[Round4]) then constraint Pn4 = if (first_player[Round4] < last_player[Round4]) then
first_player[Round4]..last_player[Round4] first_player[Round4]..last_player[Round4]
else else
Players diff first_player[Round4]..last_player[Round4] Players diff first_player[Round4]..last_player[Round4]
endif; endif;
constraint forall(p in Players) (TotalCardsPlayed[Round1, p] = if p in Pn1 then NominalTurnCount[Round1] else NominalTurnCount[Round1] - 1 endif); constraint forall(p in Players) (TotalCardsPlayed[Round1, p] = if p in Pn1 then NominalTurnCount[Round1] else NominalTurnCount[Round1] - 1 endif);
constraint forall(p in Players) (TotalCardsPlayed[Round2, p] = if p in Pn2 then NominalTurnCount[Round2] else NominalTurnCount[Round2] - 1 endif); constraint forall(p in Players) (TotalCardsPlayed[Round2, p] = if p in Pn2 then NominalTurnCount[Round2] else NominalTurnCount[Round2] - 1 endif);
constraint forall(p in Players) (TotalCardsPlayed[Round3, p] = if p in Pn3 then NominalTurnCount[Round3] else NominalTurnCount[Round3] - 1 endif); constraint forall(p in Players) (TotalCardsPlayed[Round3, p] = if p in Pn3 then NominalTurnCount[Round3] else NominalTurnCount[Round3] - 1 endif);
constraint forall(p in Players) (TotalCardsPlayed[Round4, p] = if p in Pn3 then NominalTurnCount[Round4] else NominalTurnCount[Round4] - 1 endif); constraint forall(p in Players) (TotalCardsPlayed[Round4, p] = if p in Pn3 then NominalTurnCount[Round4] else NominalTurnCount[Round4] - 1 endif);
% Total Playable Cards for any round are set equal to the Starting Hand
% TODO: Move this to `drawone`
array[Rounds,Players] of var int: PlayableCards;
constraint forall(p in Players, r in Rounds) (
PlayableCards[r,p] = StartingCardsInHand[r,p]
);

15
symbols.mzn Normal file
View File

@ -0,0 +1,15 @@
% This file maintains common symbol constraints
% Since we are modelling each symbol individually (and not "on-a-card"), this results in
% symbol counts being calculated in isolation.
% Sanity constraints on each symbol file individually ensure
% that atleast one card of the symbol was played by the correct played
% they do not ensure that across symbols
% and hence, the same card may end up getting counted twice for different symbols.
% this file prevents such issues
% and may ultimately end up replacing separate symbol counters
constraint forall(r in Rounds, a in Artists) (
sum (p in Players) (
visible_count_per_round_per_artist_per_player[r,p,a] - DrawOneCard[r,p,a]
) >= awards_per_round_per_artist[r,a]
);