Commit bdaabbcf authored by Vivien Kraus's avatar Vivien Kraus
Browse files

Check that a card is correct even when we do not know the cards

If someone claims to trump but later does not respect this, we need to
deny it.
parent 4b601455
......@@ -116,6 +116,7 @@
/src/libtarot/pkgconfig/libtarot.pc
/src/libtarot/semantic-api/api.sxml
/src/libtarot/semantic-api/api.xml
/src/libtarot/test/cheating.c
/src/libtarot/test/dog-impossible
/src/libtarot/test/dog-impossible.c
/src/libtarot/test/empty-status
......
......@@ -29,6 +29,7 @@
#include <tarot/handfuls_private.h>
#include <tarot/tricks_private.h>
#include <tarot/trick_private.h>
#include <tarot/counter_private.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
......@@ -1745,7 +1746,8 @@ game_check_handful (const TarotGameHandle * game, const TarotHand * handful)
}
static inline int
game_check_card_full_aux (const TarotGameHandle * game, TarotCard played,
game_check_card_full_aux (const TarotGame * game_for_counter,
const TarotGameHandle * game, TarotCard played,
int *cnf, TarotSuit * lead_suit, int *cno,
TarotNumber * max_trump, int *cnu)
{
......@@ -1753,15 +1755,6 @@ game_check_card_full_aux (const TarotGameHandle * game, TarotCard played,
int ok = (game_get_step (game) == TAROT_TRICKS);
TarotPlayer next = tricks_next (&(game->tricks));
const TarotTrickHandle *current = &(game->tricks.tricks[i_current]);
size_t played_in_trick, played_at_position;
if (tricks_locate
(&(game->tricks), played, &played_in_trick, &played_at_position) == 0)
{
/* This card has already been played */
ok = 0;
}
/* We cannot use the Counter API because counter_and_game_add_event
* would recursively call this function for /each card/! */
if (ok && hands_known (&(game->hands), next))
{
const TarotHand *next_hand = &(game->hands.hands[next]);
......@@ -1784,6 +1777,18 @@ game_check_card_full_aux (const TarotGameHandle * game, TarotCard played,
ok = hand_check_card_without_lead_not_first (next_hand, played);
}
}
else if (ok)
{
/* We need to check if this card does not violate the rules.
* This is subtle: what if the player trumps clubs but later it
* is found that she has clubs? For this we need a counter.
* Fortunately, the counter API does not call this function
* during its construction. */
TarotCounter validator;
counter_initialize (&validator);
counter_load_from_game (&validator, game_for_counter);
ok = (counter_may_own (&validator, 1, &next, played));
}
if (ok)
{
assert (played < 78);
......@@ -1801,8 +1806,8 @@ game_check_card (const TarotGame * game, TarotCard played,
TarotGameHandle h;
game_generalize ((TarotGame *) game, &h);
assert (played < 78);
return game_check_card_full_aux (&h, played, cnf, lead_suit, cno, max_trump,
cnu);
return game_check_card_full_aux (game, &h, played, cnf, lead_suit, cno,
max_trump, cnu);
}
static void
......@@ -1820,7 +1825,8 @@ copy_cards (TarotHand * dest, size_t n, const TarotCard * buffer)
}
static inline int
game_check_event_aux (const TarotGameHandle * game,
game_check_event_aux (const TarotGame * game_not_generalized,
const TarotGameHandle * game,
const TarotGameEvent * event)
{
size_t n_players, n_in_hand = 0;
......@@ -1883,8 +1889,9 @@ game_check_event_aux (const TarotGameHandle * game,
int cno;
TarotNumber max_trump;
int cnu;
return game_check_card_full_aux (game, card, &cnf, &lead_suit, &cno,
&max_trump, &cnu);
return game_check_card_full_aux (game_not_generalized, game, card,
&cnf, &lead_suit, &cno, &max_trump,
&cnu);
}
}
(void) error;
......@@ -1896,7 +1903,7 @@ game_check_event (const TarotGame * game, const TarotGameEvent * event)
{
TarotGameHandle h;
game_generalize ((TarotGame *) game, &h);
return game_check_event_aux (&h, event);
return game_check_event_aux (game, &h, event);
}
static inline TarotHand
......@@ -2364,7 +2371,8 @@ get_partner_or (const TarotGameHandle * game, TarotPlayer taker)
}
static inline int
game_add_card_aux (TarotGameHandle * game, TarotCard card)
game_add_card_aux (TarotGame * game_not_generalized, TarotGameHandle * game,
TarotCard card)
{
int cnf;
TarotSuit lead_suit;
......@@ -2372,7 +2380,8 @@ game_add_card_aux (TarotGameHandle * game, TarotCard card)
TarotNumber max_trump;
int cnu;
int check =
game_check_card_full_aux (game, card, &cnf, &lead_suit, &cno, &max_trump,
game_check_card_full_aux (game_not_generalized, game, card, &cnf,
&lead_suit, &cno, &max_trump,
&cnu);
int error = (check == 0);
if (error == 0)
......@@ -2492,7 +2501,7 @@ game_add_event_aux (TarotGame * game, const TarotGameEvent * event)
case TAROT_CARD_EVENT:
error = event_get_card (event, &card);
assert (error == 0);
return game_add_card_aux (&h, card);
return game_add_card_aux (game, &h, card);
}
(void) error;
return 0;
......@@ -2864,5 +2873,6 @@ game_iterator_next_value (TarotGameIterator * iterator)
#include <tarot/tricks_private_impl.h>
#include <tarot/trick_private_impl.h>
#include <tarot/game_event_private_impl.h>
#include <tarot/counter_private_impl.h>
#endif /* H_TAROT_GAME_PRIVATE_IMPL_INCLUDED */
......@@ -19,21 +19,26 @@ EXTRA_DIST += %reldir%/test-compiler.xslt
check_PROGRAMS += \
%reldir%/empty-status \
%reldir%/no-slam \
%reldir%/dog-impossible
%reldir%/dog-impossible \
%reldir%/cheating
EXTRA_DIST += \
%reldir%/empty-status.tarottest \
%reldir%/no-slam.tarottest \
%reldir%/dog-impossible.tarottest
%reldir%/dog-impossible.tarottest \
%reldir%/cheating.tarottest
MAINTAINERCLEANFILES += \
$(srcdir)/%reldir%/empty-status.c \
$(srcdir)/%reldir%/no-slam.c \
$(srcdir)/%reldir%/dog-impossible.c
$(srcdir)/%reldir%/dog-impossible.c \
$(srcdir)/%reldir%/cheating.c
%canon_reldir%_empty_status_LDADD = src/libtarot/libtarot.la
%canon_reldir%_no_slam_LDADD = src/libtarot/libtarot.la
%canon_reldir%_dog_impossible_LDADD = src/libtarot/libtarot.la
%canon_reldir%_cheating_LDADD = src/libtarot/libtarot.la
%canon_reldir%_empty_status_SOURCES = $(srcdir)/%reldir%/empty-status.c
%canon_reldir%_no_slam_SOURCES = $(srcdir)/%reldir%/no-slam.c
%canon_reldir%_dog_impossible_SOURCES = $(srcdir)/%reldir%/dog-impossible.c
%canon_reldir%_cheating_SOURCES = $(srcdir)/%reldir%/cheating.c
SUFFIXES += .c .tarottest
......
<?xml version="1.0"?>
<!-- tarot implements the rules of the tarot game
Copyright (C) 2019 Vivien Kraus
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<test xmlns="http://planete-kraus.eu/tarot">
<status>
<cannot-play card="5C" />
</status>
<game xmlns:tarot="http://planete-kraus.eu/tarot">
<setup n-players="3" with-call="no"/>
<deal to="P2">
<card card="7H"/>
<card card="JH"/>
<card card="CH"/>
<card card="7C"/>
<card card="9C"/>
<card card="KC"/>
<card card="4D"/>
<card card="6D"/>
<card card="8D"/>
<card card="9D"/>
<card card="10D"/>
<card card="JD"/>
<card card="AS"/>
<card card="2S"/>
<card card="7S"/>
<card card="JS"/>
<card card="QS"/>
<card card="3T"/>
<card card="7T"/>
<card card="8T"/>
<card card="9T"/>
<card card="10T"/>
<card card="13T"/>
<card card="16T"/>
</deal>
<bid bid="double-keep"/>
<decl slam="no"/>
<decl slam="no"/>
<decl slam="no"/>
<handful/>
<card card="4H"/>
<handful/>
<card card="7H"/>
<handful/>
<card card="AH"/>
<card card="KC"/>
<card card="AC"/>
<card card="2C"/>
<card card="7C"/>
<card card="3S"/>
<card card="QC"/>
<card card="5H"/>
<card card="CH"/>
<card card="2H"/>
<card card="9C"/>
</game>
</test>
......@@ -498,4 +498,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<xsl:template match="cannot-autoreveal">
<xsl:text>&#xA; {&#xA; size_t n_dog;&#xA; assert (!tarot_game_can_autoreveal (game, &amp;n_dog, 0, 0, NULL));&#xA; }</xsl:text>
</xsl:template>
<xsl:template match="cannot-play">
<xsl:text>&#xA; {&#xA; TarotGameEvent *ev = tarot_game_event_alloc_card (played_card);&#xA; assert (tarot_game_check_event (game, ev) != TAROT_GAME_OK);&#xA; }</xsl:text>
</xsl:template>
</xsl:stylesheet>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment