From da83f6eda18f0166b704843cb9aa0ab671c07611 Mon Sep 17 00:00:00 2001
From: Nemo
Date: Thu, 11 Jun 2020 03:45:17 +0530
Subject: [PATCH] Implemented Nominal Turn Counting
 This ensures that every player gets atleast TT1 turns per round.
 Comments out drawone stuff for simplicity for now
 Does not consider double cards either

awards.mzn  2 +
dealing.mzn  27 ++++++++++
double.mzn  34 ++++++++++++
enumtest.mzn  14 +++++
gameplay.mzn  142 +++++++++++++++++++++++++++++++++
modernart.mzn  22 ++++
ranking.mzn  2 +
sanity.mzn  14 ++++
scoring.mzn  6 +
9 files changed, 193 insertions(+), 70 deletions()
create mode 100644 dealing.mzn
create mode 100644 double.mzn
create mode 100644 enumtest.mzn
diff git a/awards.mzn b/awards.mzn
index 1548b72..8193126 100644
 a/awards.mzn
+++ b/awards.mzn
@@ 17,7 +17,7 @@ constraint forall(a in Artists) ( sum(col(awards_per_round_per_artist,a)) = 1 );
% awards can only be given if an artist's card was played that turn
constraint forall(r in Rounds, a in Artists) (
 awards_per_round_per_artist[r,a] > cards_per_artist_per_round[r,a] > 0
+ awards_per_round_per_artist[r,a] > CardsForArtist[r,a] > 0
);
% Set award_bonus_per_round_per_artist = array[5] with bonus that can be added to ranking scores
diff git a/dealing.mzn b/dealing.mzn
new file mode 100644
index 0000000..cfb18c0
 /dev/null
+++ b/dealing.mzn
@@ 0,0 +1,27 @@
+% This file deals with dealing of new cards every Round
+
+% Usable variable from here is CardsDealtPerRound[Rounds]
+array[Rounds] of var int: CardsDealtPerRound;
+
+constraint CardsDealtPerRound[Round1] = 13;
+constraint CardsDealtPerRound[Round2] =
+ if card(Players) < 4 then
+ 6
+ else if card(Players) = 4 then
+ 4
+ else
+ 2
+ endif
+endif;
+
+constraint CardsDealtPerRound[Round3] =
+ if card(Players) < 4 then
+ 6
+ else if card(Players) = 4 then
+ 4
+ else
+ 2
+ endif
+endif;
+
+constraint CardsDealtPerRound[Round4] = if card(Players) = 2 then 3 else 0 endif;
\ No newline at end of file
diff git a/double.mzn b/double.mzn
new file mode 100644
index 0000000..a1e8e52
 /dev/null
+++ b/double.mzn
@@ 0,0 +1,34 @@
+% DOUBLE CARDS
+%  Double cards are counted as VISIBLE
+%  Double cards CANNOT breach the 6 LIMIT
+% Total number of DOUBLE CARDS for each artist = 1
+% FOR EVERY ROUND+ARTIST combination, only 1 player should have played a double card
+% TODO: Check if this is still correct after a second round
+
+% Whether you played a double this round
+array[Rounds,Players,Artists] of var bool: double_played;
+
+
+constraint forall(a in Artists) (
+ sum(p in Players, r in Rounds) (double_played[r,p,a]) = 1
+);
+
+% What is the extra cards you can possibly play
+array[Rounds,Players,Artists] of var bool: bonus_due_to_double_cards;
+
+constraint forall(a in Artists, r in Rounds, p in Players) (
+ % If this player played more than 2 cards of this artist
+ if visible_count_per_round_per_artist_per_player[r,p,a] >=2
+ % And this artist is the winning artist this round
+ /\ row(sorted_artists_per_round,r)[1] = a
+ % And you closed this round
+ /\ visible_count_per_round_per_artist_per_player[r,p,a] = max_visible_cards
+ % and they are claiming their double now
+ /\ double_played[r,p,a] then
+ bonus_due_to_double_cards[r,p,a] = true
+ else
+ bonus_due_to_double_cards[r,p,a] = false
+ endif
+);
+
+% array[Rounds,Players] of var int: negs_due_to_double_cards;
\ No newline at end of file
diff git a/enumtest.mzn b/enumtest.mzn
new file mode 100644
index 0000000..a85047a
 /dev/null
+++ b/enumtest.mzn
@@ 0,0 +1,14 @@
+include "globals.mzn";
+% Since the documentation is unclear, wrote this test to figure
+% out whether enums wrap around or not.
+enum Letters;
+Letters= {A,B,C};
+
+var Letters: x;
+var Letters: y;
+var Letters: z;
+
+constraint x = enum_next(Letters, y);
+constraint y = B;
+% This is unsatisfiable, because nothing comes after x=C
+constraint z = enum_next(Letters, x);
\ No newline at end of file
diff git a/gameplay.mzn b/gameplay.mzn
index 82d9c07..0b08ddf 100644
 a/gameplay.mzn
+++ b/gameplay.mzn
@@ 5,6 +5,12 @@ include "ranking.mzn";
include "scoring.mzn";
include "sanity.mzn";
include "artists.mzn";
+include "dealing.mzn";
+% Ignoring these for now
+% include "double.mzn";
+% include "drawone.mzn";
+% include "hidden.mzn";
+% include "simultaneous.mzn";
/*
This file includes the core gameplay rules
@@ 14,65 +20,103 @@ include "artists.mzn";
% Calculate total cards of an artist played per round
constraint forall (a in Artists, r in Rounds) (
 cards_per_artist_per_round[r, a] = sum(p in Players) (visible_count_per_round_per_artist_per_player[r,p,a])
+ CardsForArtist[r, a] = sum(p in Players) (visible_count_per_round_per_artist_per_player[r,p,a])
);
% Max number of visible cards can be 6 for any artist per player
var 5..6: max_visible_cards;
constraint max_visible_cards = if card(Players)>2 then 6 else 5 endif;
+var 5..6: MaxVisibleCards;
+constraint MaxVisibleCards = if card(Players)>2 then 6 else 5 endif;
% Maximum max_visible_cards of the artist with maximum cards
constraint forall(r in Rounds) (max(row(cards_per_artist_per_round,r)) = max_visible_cards);
+% Maximum MaxVisibleCards of the artist with maximum cards
+constraint forall(r in Rounds) (max(row(CardsForArtist,r)) = MaxVisibleCards);
% second highest value should not be the max
constraint forall(r in Rounds) (sort(row(cards_per_artist_per_round, r))[4] != max_visible_cards);

% DOUBLE CARDS
%  Double cards are counted as VISIBLE
%  Double cards CANNOT breach the 6 LIMIT
% Total number of DOUBLE CARDS for each artist = 1
% FOR EVERY ROUND+ARTIST combination, only 1 player should have played a double card
% TODO: Check if this is still correct after a second round
constraint forall(a in Artists) (
 sum(p in Players, r in Rounds) (double_played[r,p,a]) = 1
+constraint forall(r in Rounds) (sort(row(CardsForArtist, r))[4] != MaxVisibleCards);
+
+% Temporary variable to see how many cards you've played TOTAL per round
+array[Rounds,Players] of var int: TotalCardsPlayed;
+constraint forall(r in Rounds, p in Players) (
+% TODO: Change this to played cards from VISIBLE (hidden)
+ TotalCardsPlayed[r,p] = sum(a in Artists) (visible_count_per_round_per_artist_per_player[r,p,a])
+);
+
+% Calculate maximum cards any player can play in first round
+array[Rounds,Players] of var int: StartingCardsInHand;
+% Round 1 Starting Hand is 13 cards
+constraint forall(p in Players) (StartingCardsInHand[Round1,p] = CardsDealtPerRound[Round1]);
+constraint forall(p in Players) (
+ StartingCardsInHand[Round2,p] = StartingCardsInHand[Round1,p]  TotalCardsPlayed[Round1,p] + CardsDealtPerRound[Round2]
+);
+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]
);
array[Rounds,Players] of var int: max_cards_per_round_per_player;

% What is the extra cards you can possibly play
array[Rounds,Players,Artists] of var bool: bonus_due_to_double_cards;

constraint forall(a in Artists, r in Rounds, p in Players) (
 % If this player played more than 2 cards of this artist
 if visible_count_per_round_per_artist_per_player[r,p,a] >=2
 % And this artist is the winning artist this round
 /\ row(sorted_artists_per_round,r)[1] = a
 % And you closed this round
 /\ visible_count_per_round_per_artist_per_player[r,p,a] = max_visible_cards
 % and they are claiming their double now
 /\ double_played[r,p,a] then
 bonus_due_to_double_cards[r,p,a] = true
 else
 bonus_due_to_double_cards[r,p,a] = false
 endif
+% TURN ORDER STUFF
+constraint forall(r in Rounds) (
+ NominalTurnCount[r] = TotalCardsPlayed[r, last_player[r]]
);
% array[Rounds,Players] of var int: negs_due_to_double_cards;
+%All players who played nominal turns
+var set of Players: Pn1;
+var set of Players: Pn2;
+var set of Players: Pn3;
+var set of Players: Pn4;
+%All players who played subnominal turns
+var set of Players: Px1;
+var set of Players: Px2;
+var set of Players: Px3;
+var set of Players: Px4;
% constraint forall(r in Rounds, p in Players) (

% );
+set of int: emptySet = 1..0;
% Calculate maximum cards any player can play in first round
% constraint forall(p in Players) (
% CardsInHand[Round1,p] = 13
% );

% TODO: This is actual not VISIBLE, but TOTAL cards LIMIT
% TODO: This does not consider any of the symbols
% IMPLIED RULE: You can max play 13 cards in Round 1
constraint forall(p in Players) (
 sum(a in Artists) (
 visible_count_per_round_per_artist_per_player[Round1,p,a]
 ) <= max_cards_per_round_per_player[Round1,p]
+constraint Pn1 = if (first_player[Round1] < last_player[Round1]) then
+ first_player[Round1]..last_player[Round1]
+ else
+ set_diff(Players,first_player[Round1]..last_player[Round1])
+ endif;
+
+
+constraint Pn2 = if (first_player[Round2] < last_player[Round2]) then
+ first_player[Round2]..last_player[Round2]
+ else
+ set_diff(Players,first_player[Round2]..last_player[Round2])
+ endif;
+
+
+constraint Pn3 = if (first_player[Round3] < last_player[Round3]) then
+ first_player[Round3]..last_player[Round3]
+ else
+ set_diff(Players,first_player[Round3]..last_player[Round3])
+ endif;
+
+
+constraint Pn4 = if (first_player[Round4] < last_player[Round4]) then
+ first_player[Round4]..last_player[Round4]
+ else
+ set_diff(Players,first_player[Round4]..last_player[Round4])
+ endif;
+
+constraint Px1 = set_diff(Players,Pn1);
+constraint Px2 = set_diff(Players,Pn2);
+constraint Px3 = set_diff(Players,Pn3);
+constraint Px4 = set_diff(Players,Pn4);
+
+constraint forall(p in Players) (p in Pn1 > TotalCardsPlayed[Round1, p] = NominalTurnCount[Round1]);
+constraint forall(p in Players) (p in Pn2 > TotalCardsPlayed[Round2, p] = NominalTurnCount[Round2]);
+constraint forall(p in Players) (p in Pn3 > TotalCardsPlayed[Round3, p] = NominalTurnCount[Round3]);
+constraint forall(p in Players) (p in Pn3 > TotalCardsPlayed[Round4, p] = NominalTurnCount[Round4]);
+
+constraint forall(p in Players) (p in Px1 > TotalCardsPlayed[Round1, p] = NominalTurnCount[Round1]  1);
+constraint forall(p in Players) (p in Px2 > TotalCardsPlayed[Round2, p] = NominalTurnCount[Round2]  1);
+constraint forall(p in Players) (p in Px3 > TotalCardsPlayed[Round3, p] = NominalTurnCount[Round3]  1);
+constraint forall(p in Players) (p in Px3 > TotalCardsPlayed[Round4, p] = NominalTurnCount[Round4]  1);
+
+% 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]
);
diff git a/modernart.mzn b/modernart.mzn
index 5587b7c..ee50a0d 100644
 a/modernart.mzn
+++ b/modernart.mzn
@@ 3,9 +3,9 @@ enum Players;
enum Artists;
enum Rounds;
Players = {Nemo,Jana};
+Players = {Nemo,Jana, Adam};
Artists = {Krypto,KarlGitter,ChristinP,Yoko,LiteMetal};
Rounds = {Round1};
+Rounds = {Round1, Round2, Round3, Round4};
% Number of cards per round per player per artist
array[Rounds,Players,Artists] of var int: visible_count_per_round_per_artist_per_player;
@@ 19,20 +19,16 @@ array[Rounds] of var Players: last_player;
% Total points that an artist has in a given round
array[Rounds,Artists] of var int: total_score_per_round_per_artist;
% Whether you played a double this round
array[Rounds,Players,Artists] of var bool: double_played;

% Score a player gets in each given round
array[Rounds,Players] of var int: score_per_round_per_player;
+array[Rounds,Players] of var int: RoundScore;
% Final score of a player
array[Players] of var int: score_per_player;
+array[Players] of var int: Score;
% Total number of a cards of an artist that were PLAYED this round
array[Rounds, Artists] of var int: cards_per_artist_per_round;
+array[Rounds, Artists] of var int: CardsForArtist;
+
+% Number of Turns played by the closing player this round
+array[Rounds] of var int: NominalTurnCount;
% Dumb constraints to help maximize score
constraint score_per_round_per_player[Round1,Nemo] > score_per_round_per_player[Round1,Jana];
% constraint score_per_round_per_player[Round1,Jana] > 10;
% constraint score_per_round_per_player[Round1,Adam] > 5;
solve maximize sum(p in Players)(score_per_player[p]);
\ No newline at end of file
+solve maximize Score[Nemo];
\ No newline at end of file
diff git a/ranking.mzn b/ranking.mzn
index 75cf873..f4d1232 100644
 a/ranking.mzn
+++ b/ranking.mzn
@@ 5,7 +5,7 @@ array[Rounds,Artists] of var int: ranking_score_per_artist_per_round;
array[Rounds,1..card(Artists)] of var Artists: sorted_artists_per_round;
% Decide the top artists by picking the cards per artist for that round, and sorting them
constraint forall(r in Rounds)(row(sorted_artists_per_round,r)= reverse(arg_sort(row(cards_per_artist_per_round, r))));
+constraint forall(r in Rounds)(row(sorted_artists_per_round,r)= reverse(arg_sort(row(CardsForArtist, r))));
% Top three artists get ranking score in each round as 3,2,1 others get 0
constraint forall(r in Rounds) (ranking_score_per_artist_per_round[r, row(sorted_artists_per_round,r)[1]] = 3);
diff git a/sanity.mzn b/sanity.mzn
index 00524f6..52c1921 100644
 a/sanity.mzn
+++ b/sanity.mzn
@@ 1,6 +1,6 @@
% Sanity check
constraint forall (a in Artists, r in Rounds) (
 cards_per_artist_per_round[r,a]>=0
+ CardsForArtist[r,a]>=0
);
% So they don't go negative
constraint forall (a in Artists, r in Rounds, p in Players) (
@@ 12,10 +12,20 @@ constraint forall (a in Artists, r in Rounds) (
ranking_score_per_artist_per_round[r,a] >=0
);
+% No game can have less than 1 Nominal Turn (Number of turns played by the Closing Player)
+constraint forall(r in Rounds) (NominalTurnCount[r] >=1);
+
+constraint forall(r in Rounds, p in Players) (
+ StartingCardsInHand[r,p] >=0
+);
+
% Round 1 Player 1
constraint first_player[Round1] = Nemo;
% Visible Cards per round per player for every artist > 0
constraint forall(a in Artists) (
sum(p in Players, r in Rounds) (visible_count_per_round_per_artist_per_player[r,p,a])>=0
);
\ No newline at end of file
+);
+
+% This is a 25 player game
+constraint 2<= assert(card(Players)) <=5
\ No newline at end of file
diff git a/scoring.mzn b/scoring.mzn
index 74d25d5..dc89f3e 100644
 a/scoring.mzn
+++ b/scoring.mzn
@@ 8,14 +8,12 @@ constraint forall(r in Rounds, a in Artists) (
% 1. Per Round
constraint forall(r in Rounds, p in Players) (
 score_per_round_per_player[r,p] =

 sum(a in Artists) (
+ RoundScore[r,p] = sum(a in Artists) (
visible_count_per_round_per_artist_per_player[r,p,a] * ranking_score_per_artist_per_round[r,a]
)
);
% 2. For the whole game
constraint forall(p in Players) (
 score_per_player[p] = sum(r in Rounds) (score_per_round_per_player[r,p])
+ Score[p] = sum(r in Rounds) (RoundScore[r,p])
);