diff --git a/README.md b/README.md index 1857877..605cb70 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,7 @@ This is a [MiniZinc](https://www.minizinc.org/) based attempt to solve the [Modern Art: Masters Gallery](https://boardgamegeek.com/boardgame/40381/masters-gallery) game. -The current partial implementation (see below for missing rules) results in a highest possible score of 242. (`*` = Award given to artist). - -|Player 1|Player 2|Player 3|A|B|C|D|E| -|--------|--------|--------|-|-|-|-|-| -|AA* |AA |AA |5|0|0|1|2| -|AAAEE* |BBCC*E |D*EEEE |7|0|0|4|7| -|AAAAAEEEE|ABBBDDDDE|BBCCCCCA|10|0|0|5|9| -|AAAAAAEEE|BBBBCCCDD|B*CCDDDEE|13|0|0|6|11| -|*242* = 10+35+86+111|*65* = 10+4+39+12|*87* = 10+32+5+40| +The current partial implementation (see below for missing rules) results in a highest possible score of 298 for a 2 player game. See [games/03.md](games/03.md) for the complete episode. There are a few more games available in [the games directory](games/) ## Plan @@ -119,8 +111,8 @@ We subdivide the score into the following sections: Outside of constraints, I've to get to the following: -- [ ] Improve output formatting -- [ ] Get JSON output to render outside of the solver +- [x] Improve output formatting +- [x] Get JSON output to render outside of the solver - [x] Get Gecode and other solvers working ## Cards Dealt Table diff --git a/games.php b/games.php new file mode 100644 index 0000000..42d392e --- /dev/null +++ b/games.php @@ -0,0 +1,109 @@ + 0) + echo "Count(" . $A[$a].'='.$AA[$a] . ") = " . $data['CardsForArtist'][$i][$a] . $ranks[$a] . PHP_EOL. PHP_EOL; + } + + // Awards + $awards = []; + for($a=0;$a<5;$a++) { + if ($data['AwardGiven'] and $AwardPlayedInRound[$a] == $i) { + $awards [] = $A[$a] . ">" . $AA[$AwardedArtistIndex[$a]]; + } + } + if (count($awards) > 0) + echo "Awards: " . implode(", ", $awards) .PHP_EOL; + echo "\n**Artist Scores**:".NL2; + for($a=0;$a<5;$a++) { + echo $AA[$a] .":".$data['ArtistScore'][$i][$a] .NL2; + } + + echo "\n**Player Scores**" . NL2; + for ($p=0; $p<$playerCount;$p++) { + $pp = $p+1; + echo "Player " . $pp . " : " . $data['RoundScore'][$i][$p] . NL2; + } +} +echo "\n\n## Final Scores".NL2; +for ($p=0; $p<$playerCount;$p++) { + $pp = $p+1; + echo "Player " . $pp . " : " . $data['Score'][$p] . NL2; +} +?> + +### Info + +A=LiteMetal (17) +B=Yoko (18) +C=ChristinP (19) +D=KarlGitter (20) +E=Krypto (21) + +Since this is a -player game, the maximum number of visible cards for any artist is +Scores for unranked artists are 0 for that round. + +The syntax for awards is AwardTokenArtist > Awarded Artist (ie, the Award card for `AwardTokenArtist` was played, and the award was given to the `Awarded Artist`). +Krypto, D>Yoko, C>Krypto, B>Krypto + +**Artist Scores**: + +Krypto:9 + +KarlGitter:0 + +ChristinP:1 + +Yoko:4 + +LiteMetal:0 + + +**Player Scores** + +Player 1 : 36 + +Player 2 : 14 + + +### Round (2) +Player 1 : EDDCCBBBAA + +Player 2 : EEDDCCBBAA + +Count(E=Krypto) = 3 + +Count(D=KarlGitter) = 4 + +Count(C=ChristinP) = 4 (THIRD=1) + +Count(B=Yoko) = 5 (FIRST=3) + +Count(A=LiteMetal) = 4 (SECOND=2) + +Awards: A>Yoko + +**Artist Scores**: + +Krypto:0 + +KarlGitter:0 + +ChristinP:2 + +Yoko:9 + +LiteMetal:2 + + +**Player Scores** + +Player 1 : 35 + +Player 2 : 26 + + +### Round (3) +Player 1 : EEEEBBBB + +Player 2 : DDDCCBAA + +Count(E=Krypto) = 4 (SECOND=2) + +Count(D=KarlGitter) = 3 (THIRD=1) + +Count(C=ChristinP) = 2 + +Count(B=Yoko) = 5 (FIRST=3) + +Count(A=LiteMetal) = 2 + + +**Artist Scores**: + +Krypto:11 + +KarlGitter:1 + +ChristinP:0 + +Yoko:12 + +LiteMetal:0 + + +**Player Scores** + +Player 1 : 92 + +Player 2 : 15 + + +### Round (4) +Player 1 : EEEEBBBB + +Player 2 : DDDDDAAA + +Count(E=Krypto) = 4 (THIRD=1) + +Count(D=KarlGitter) = 5 (FIRST=3) + +Count(B=Yoko) = 4 (SECOND=2) + +Count(A=LiteMetal) = 3 + + +**Artist Scores**: + +Krypto:12 + +KarlGitter:4 + +ChristinP:0 + +Yoko:14 + +LiteMetal:0 + + +**Player Scores** + +Player 1 : 104 + +Player 2 : 20 + + + +## Final Scores + +Player 1 : 267 + +Player 2 : 75 + + +### Info + +A=LiteMetal (17) +B=Yoko (18) +C=ChristinP (19) +D=KarlGitter (20) +E=Krypto (21) + +Since this is a 2-player game, the maximum number of visible cards for any artist is 5Scores for unranked artists are 0 for that round. + +The syntax for awards is AwardTokenArtist > Awarded Artist (ie, the Award card for `AwardTokenArtist` was played, and the award was given to the `Awarded Artist`). diff --git a/games/02.json b/games/02.json new file mode 100644 index 0000000..58f1f23 --- /dev/null +++ b/games/02.json @@ -0,0 +1,28 @@ +{ + "visible_count_per_round_per_artist_per_player" : [[[0, 0, 4, 1, 0], [1, 0, 0, 4, 0]], [[0, 0, 2, 4, 0], [0, 2, 1, 1, 2]], [[0, 1, 0, 4, 4], [4, 0, 4, 0, 1]], [[0, 0, 5, 4, 1], [3, 4, 0, 0, 3]]], + "first_player" : [{"e":"Nemo"}, {"e":"Nemo"}, {"e":"Nemo"}, {"e":"Nemo"}], + "last_player" : [{"e":"Jana"}, {"e":"Jana"}, {"e":"Jana"}, {"e":"Nemo"}], + "total_score_per_round_per_artist" : [[1, 0, 4, 5, 0], [1, 0, 8, 12, 1], [1, 0, 9, 14, 4], [1, 0, 12, 15, 6]], + "CardsForArtist" : [[1, 0, 4, 5, 0], [0, 2, 3, 5, 2], [4, 1, 4, 4, 5], [3, 4, 5, 4, 4]], + "NominalTurnCount" : [5, 6, 9, 10], + "Score" : [283, 101], + "MaxVisibleCards" : 5, + "TotalCardsPlayed" : [[5, 5], [6, 6], [9, 9], [10, 10]], + "StartingCardsInHand" : [[13, 13], [15, 14], [15, 16], [10, 11]], + "CardsDealtPerRound" : [13, 6, 6, 3], + "PlayableCards" : [[14, 13], [15, 16], [16, 17], [10, 11]], + "sorted_artists_per_round" : [{"e":"Yoko"}, {"e":"ChristinP"}, {"e":"Krypto"}, {"e":"LiteMetal"}, {"e":"KarlGitter"}, {"e":"Yoko"}, {"e":"ChristinP"}, {"e":"LiteMetal"}, {"e":"KarlGitter"}, {"e":"Krypto"}, {"e":"LiteMetal"}, {"e":"Yoko"}, {"e":"ChristinP"}, {"e":"Krypto"}, {"e":"KarlGitter"}, {"e":"ChristinP"}, {"e":"LiteMetal"}, {"e":"Yoko"}, {"e":"KarlGitter"}, {"e":"Krypto"}], + "Pn1" : {"set":[{"e":"Nemo"}, {"e":"Jana"}]}, + "Pn2" : {"set":[{"e":"Nemo"}, {"e":"Jana"}]}, + "Pn3" : {"set":[{"e":"Nemo"}, {"e":"Jana"}]}, + "Pn4" : {"set":[{"e":"Jana"}]}, + "award_bonus_per_round_per_artist" : [[0, 0, 2, 2, 0], [0, 0, 2, 4, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], + "AwardGiven" : [true, true, true, true, true], + "AwardPlayedInRound" : [{"e":"Round1"}, {"e":"Round2"}, {"e":"Round2"}, {"e":"Round1"}, {"e":"Round2"}], + "AwardedArtist" : [{"e":"Yoko"}, {"e":"Yoko"}, {"e":"Yoko"}, {"e":"ChristinP"}, {"e":"ChristinP"}], + "ranking_score_per_artist_per_round" : [[1, 0, 2, 3, 0], [0, 0, 2, 3, 1], [0, 0, 1, 2, 3], [0, 0, 3, 1, 2]], + "IsArtistRanked" : [[true, false, true, true, false], [false, false, true, true, true], [false, false, true, true, true], [false, false, true, true, true]], + "RoundScore" : [[21, 21], [64, 22], [72, 40], [126, 18]], + "ArtistScore" : [[1, 0, 4, 5, 0], [0, 0, 8, 12, 1], [0, 0, 9, 14, 4], [0, 0, 12, 15, 6]], + "DrawOneCard" : [[[false, false, true, false, false], [false, false, false, false, false]], [[false, false, false, false, false], [false, false, false, true, true]], [[false, true, false, false, false], [true, false, false, false, false]], [[false, false, false, false, false], [false, false, false, false, false]]] +} \ No newline at end of file diff --git a/games/02.md b/games/02.md new file mode 100644 index 0000000..6022f76 --- /dev/null +++ b/games/02.md @@ -0,0 +1,160 @@ + +### Round (1) +Player 1 : CCCCB + +Player 2 : EBBBB + +Count(E=Krypto) = 1 (THIRD=1) + +Count(C=ChristinP) = 4 (SECOND=2) + +Count(B=Yoko) = 5 (FIRST=3) + +Awards: E>Yoko, B>ChristinP + +**Artist Scores**: + +Krypto:1 + +KarlGitter:0 + +ChristinP:4 + +Yoko:5 + +LiteMetal:0 + + +**Player Scores** + +Player 1 : 21 + +Player 2 : 21 + + +### Round (2) +Player 1 : CCBBBB + +Player 2 : DDCBAA + +Count(D=KarlGitter) = 2 + +Count(C=ChristinP) = 3 (SECOND=2) + +Count(B=Yoko) = 5 (FIRST=3) + +Count(A=LiteMetal) = 2 (THIRD=1) + +Awards: D>Yoko, C>Yoko, A>ChristinP + +**Artist Scores**: + +Krypto:0 + +KarlGitter:0 + +ChristinP:8 + +Yoko:12 + +LiteMetal:1 + + +**Player Scores** + +Player 1 : 64 + +Player 2 : 22 + + +### Round (3) +Player 1 : DBBBBAAAA + +Player 2 : EEEECCCCA + +Count(E=Krypto) = 4 + +Count(D=KarlGitter) = 1 + +Count(C=ChristinP) = 4 (THIRD=1) + +Count(B=Yoko) = 4 (SECOND=2) + +Count(A=LiteMetal) = 5 (FIRST=3) + + +**Artist Scores**: + +Krypto:0 + +KarlGitter:0 + +ChristinP:9 + +Yoko:14 + +LiteMetal:4 + + +**Player Scores** + +Player 1 : 72 + +Player 2 : 40 + + +### Round (4) +Player 1 : CCCCCBBBBA + +Player 2 : EEEDDDDAAA + +Count(E=Krypto) = 3 + +Count(D=KarlGitter) = 4 + +Count(C=ChristinP) = 5 (FIRST=3) + +Count(B=Yoko) = 4 (THIRD=1) + +Count(A=LiteMetal) = 4 (SECOND=2) + + +**Artist Scores**: + +Krypto:0 + +KarlGitter:0 + +ChristinP:12 + +Yoko:15 + +LiteMetal:6 + + +**Player Scores** + +Player 1 : 126 + +Player 2 : 18 + + + +## Final Scores + +Player 1 : 283 + +Player 2 : 101 + + +### Info + +A=LiteMetal (17) +B=Yoko (18) +C=ChristinP (19) +D=KarlGitter (20) +E=Krypto (21) + +Since this is a 2-player game, the maximum number of visible cards for any artist is 5Scores for unranked artists are 0 for that round. + +The syntax for awards is AwardTokenArtist > Awarded Artist (ie, the Award card for `AwardTokenArtist` was played, and the award was given to the `Awarded Artist`). diff --git a/games/03.json b/games/03.json new file mode 100644 index 0000000..d34fdc9 --- /dev/null +++ b/games/03.json @@ -0,0 +1,28 @@ +{ + "visible_count_per_round_per_artist_per_player" : [[[0, 0, 2, 4, 0], [5, 0, 0, 0, 1]], [[0, 0, 1, 3, 1], [0, 1, 4, 0, 0]], [[1, 0, 4, 4, 0], [3, 2, 1, 0, 3]], [[0, 1, 5, 4, 0], [4, 3, 0, 0, 3]]], + "first_player" : [{"e":"Nemo"}, {"e":"Nemo"}, {"e":"Nemo"}, {"e":"Nemo"}], + "last_player" : [{"e":"Jana"}, {"e":"Jana"}, {"e":"Jana"}, {"e":"Nemo"}], + "total_score_per_round_per_artist" : [[3, 0, 3, 8, 0], [3, 0, 6, 10, 1], [4, 0, 11, 12, 1], [4, 1, 14, 14, 1]], + "CardsForArtist" : [[5, 0, 2, 4, 1], [0, 1, 5, 3, 1], [4, 2, 5, 4, 3], [4, 4, 5, 4, 3]], + "NominalTurnCount" : [6, 5, 9, 10], + "Score" : [298, 65], + "MaxVisibleCards" : 5, + "TotalCardsPlayed" : [[6, 6], [5, 5], [9, 9], [10, 10]], + "StartingCardsInHand" : [[13, 13], [13, 14], [17, 16], [11, 10]], + "CardsDealtPerRound" : [13, 6, 6, 3], + "PlayableCards" : [[13, 14], [16, 15], [17, 16], [11, 10]], + "sorted_artists_per_round" : [{"e":"Krypto"}, {"e":"Yoko"}, {"e":"ChristinP"}, {"e":"LiteMetal"}, {"e":"KarlGitter"}, {"e":"ChristinP"}, {"e":"Yoko"}, {"e":"LiteMetal"}, {"e":"KarlGitter"}, {"e":"Krypto"}, {"e":"ChristinP"}, {"e":"Yoko"}, {"e":"Krypto"}, {"e":"LiteMetal"}, {"e":"KarlGitter"}, {"e":"ChristinP"}, {"e":"Yoko"}, {"e":"KarlGitter"}, {"e":"Krypto"}, {"e":"LiteMetal"}], + "Pn1" : {"set":[{"e":"Nemo"}, {"e":"Jana"}]}, + "Pn2" : {"set":[{"e":"Nemo"}, {"e":"Jana"}]}, + "Pn3" : {"set":[{"e":"Nemo"}, {"e":"Jana"}]}, + "Pn4" : {"set":[{"e":"Jana"}]}, + "award_bonus_per_round_per_artist" : [[0, 0, 2, 6, 0], [0, 0, 0, 0, 0], [0, 0, 2, 0, 0], [0, 0, 0, 0, 0]], + "AwardGiven" : [true, true, true, true, true], + "AwardPlayedInRound" : [{"e":"Round1"}, {"e":"Round3"}, {"e":"Round1"}, {"e":"Round1"}, {"e":"Round1"}], + "AwardedArtist" : [{"e":"Yoko"}, {"e":"ChristinP"}, {"e":"Yoko"}, {"e":"Yoko"}, {"e":"ChristinP"}], + "ranking_score_per_artist_per_round" : [[3, 0, 1, 2, 0], [0, 0, 3, 2, 1], [1, 0, 3, 2, 0], [0, 1, 3, 2, 0]], + "IsArtistRanked" : [[true, false, true, true, false], [false, false, true, true, true], [true, false, true, true, false], [false, true, true, true, false]], + "RoundScore" : [[38, 15], [37, 24], [96, 23], [127, 3]], + "ArtistScore" : [[3, 0, 3, 8, 0], [0, 0, 6, 10, 1], [4, 0, 11, 12, 0], [0, 1, 14, 14, 0]], + "DrawOneCard" : [[[false, false, false, false, false], [true, false, false, false, false]], [[false, false, true, true, true], [false, true, false, false, false]], [[false, false, false, false, false], [false, false, false, false, false]], [[false, false, false, false, false], [false, false, false, false, false]]] +} \ No newline at end of file diff --git a/games/03.md b/games/03.md new file mode 100644 index 0000000..05fd3d4 --- /dev/null +++ b/games/03.md @@ -0,0 +1,162 @@ + +### Round (1) +Player 1 : CCBBBB + +Player 2 : EEEEEA + +Count(E=Krypto) = 5 (FIRST=3) + +Count(C=ChristinP) = 2 (THIRD=1) + +Count(B=Yoko) = 4 (SECOND=2) + +Count(A=LiteMetal) = 1 + +Awards: E>Yoko, C>Yoko, B>Yoko, A>ChristinP + +**Artist Scores**: + +Krypto:3 + +KarlGitter:0 + +ChristinP:3 + +Yoko:8 + +LiteMetal:0 + + +**Player Scores** + +Player 1 : 38 + +Player 2 : 15 + + +### Round (2) +Player 1 : CBBBA + +Player 2 : DCCCC + +Count(D=KarlGitter) = 1 + +Count(C=ChristinP) = 5 (FIRST=3) + +Count(B=Yoko) = 3 (SECOND=2) + +Count(A=LiteMetal) = 1 (THIRD=1) + + +**Artist Scores**: + +Krypto:0 + +KarlGitter:0 + +ChristinP:6 + +Yoko:10 + +LiteMetal:1 + + +**Player Scores** + +Player 1 : 37 + +Player 2 : 24 + + +### Round (3) +Player 1 : ECCCCBBBB + +Player 2 : EEEDDCAAA + +Count(E=Krypto) = 4 (THIRD=1) + +Count(D=KarlGitter) = 2 + +Count(C=ChristinP) = 5 (FIRST=3) + +Count(B=Yoko) = 4 (SECOND=2) + +Count(A=LiteMetal) = 3 + +Awards: D>ChristinP + +**Artist Scores**: + +Krypto:4 + +KarlGitter:0 + +ChristinP:11 + +Yoko:12 + +LiteMetal:0 + + +**Player Scores** + +Player 1 : 96 + +Player 2 : 23 + + +### Round (4) +Player 1 : DCCCCCBBBB + +Player 2 : EEEEDDDAAA + +Count(E=Krypto) = 4 + +Count(D=KarlGitter) = 4 (THIRD=1) + +Count(C=ChristinP) = 5 (FIRST=3) + +Count(B=Yoko) = 4 (SECOND=2) + +Count(A=LiteMetal) = 3 + + +**Artist Scores**: + +Krypto:0 + +KarlGitter:1 + +ChristinP:14 + +Yoko:14 + +LiteMetal:0 + + +**Player Scores** + +Player 1 : 127 + +Player 2 : 3 + + + +## Final Scores + +Player 1 : 298 + +Player 2 : 65 + + +### Info + +A=LiteMetal (17) +B=Yoko (18) +C=ChristinP (19) +D=KarlGitter (20) +E=Krypto (21) + +Since this is a 2-player game, the maximum number of visible cards for any artist is 5Scores for unranked artists are 0 for that round. + +The syntax for awards is AwardTokenArtist > Awarded Artist (ie, the Award card for `AwardTokenArtist` was played, and the award was given to the `Awarded Artist`). diff --git a/modernart.mzn b/modernart.mzn index 5bacd03..5de6f00 100644 --- a/modernart.mzn +++ b/modernart.mzn @@ -33,4 +33,6 @@ array[Rounds] of var 0..10: NominalTurnCount; % Symmetry Breaking constraint Score[Nemo] > Score[Jana]; -solve maximize Score[Nemo]; \ No newline at end of file +solve maximize Score[Nemo]; + +output outputJSON();