int main(int argc, char **argv) { int i; int player = 0; int numPlayers = 2; int kingdomCardTypes[10] = { adventurer, smithy, village, salvager, minion, feast, gardens, mine, remodel, baron }; int randomSeed = time(NULL); int ret; struct gameState game; // Setup a contrived game state for testing. { initializeGame(numPlayers, kingdomCardTypes, randomSeed, &game); game.whoseTurn = player; // Three of the five cards in the deck are treasures. int preDeck[] = {copper, silver, smithy, estate, gold}; int preDeckCount = 5; for (i = 0; i < preDeckCount; i++) { game.deck[player][i] = preDeck[i]; } game.deckCount[player] = preDeckCount; // One of the three cards in the hand is a treasure. int preHand[] = {copper, curse, remodel}; int preHandCount = 3; for (i = 0; i < preHandCount; i++) { game.hand[player][i] = preHand[i]; } game.handCount[player] = preHandCount; // The discard pile is empty. game.discardCount[player] = 0; } // Apply the adventurer card effect. ret = adventurerCardEffect(&game); // Compare the actual results against expectations. { // The operations should be successful. if (ret == 0) { printf("adventurerCardEffect() PASSED: Return value check\n"); } else { printf("adventurerCardEffect() FAILED: Return value check\n"); printf(" Expected: %d, Resulted: %d", 0, ret); } // Four cards needed to be drawn in order to acquire two treasures. int postDeck[] = {copper}; int postDeckCount = 1; if (game.deckCount[player] == postDeckCount && cardArrayCmp(game.deck[player], postDeck, postDeckCount) == 0 ) { printf("adventurerCardEffect() PASSED: Deck check \n"); } else { printf("adventurerCardEffect() FAILED: Deck check \n"); printf(" Expected: "); printCardArray(postDeck, postDeckCount); printf(", Resulted: "); printCardArray(game.deck[player], game.deckCount[player]); printf("\n"); } // The hand then contains the two drawn treasure cards. int postHand[] = {copper, curse, remodel, gold, silver}; int postHandCount = 5; if (game.handCount[player] == postHandCount && cardArrayCmp(game.hand[player], postHand, postHandCount) == 0 ) { printf("adventurerCardEffect() PASSED: Hand check\n"); } else { printf("adventurerCardEffect() FAILED: Hand check\n"); printf(" Expected: "); printCardArray(postHand, postHandCount); printf(", Resulted: "); printCardArray(game.hand[player], game.handCount[player]); printf("\n"); } // A total of three treasures should now be in hand. int treasures = 0; for (i = 0; i < game.handCount[player]; i++) { int card = game.hand[player][i]; if (card == copper || card == silver || card == gold) { treasures++; } } if (treasures == 3) { printf("adventurerCardEffect() PASSED: Hand treasure count check\n"); } else { printf("adventurerCardEffect() FAILED: Hand treasure count check\n"); printf(" Expected: %d, Resulted: %d\n", 3, treasures); } // Two cards were discarded during the treasure drawing process. int postDiscard[] = {estate, smithy}; int postDiscardCount = 2; if (game.discardCount[player] == postDiscardCount && cardArrayCmp(game.discard[player], postDiscard, postDiscardCount) == 0 ) { printf("adventurerCardEffect() PASSED: Discard check\n"); } else { printf("adventurerCardEffect() FAILED: Discard check\n"); printf(" Expected: "); printCardArray(postDiscard, postDiscardCount); printf(", Resulted: "); printCardArray(game.discard[player], game.discardCount[player]); printf("\n"); } } return 0; }
int main() { printf("*** Testing adventurerCardEffect *** \n"); struct gameState game; int cards[10] = { adventurer, council_room, feast, gardens, mine, remodel, smithy, village, baron, great_hall }; int all_cards[17] = { adventurer, council_room, feast, gardens, mine, remodel, smithy, village, baron, great_hall, copper, silver, gold, estate, duchy, province, curse }; int player = 0; int other_player = 1; initializeGame(2, cards, 1, &game); //Test if two treatures added to hand with normal deck int handSize = game.handCount[player] + 1; adventurerCardEffect(player, 0, &game); if (handSize == game.handCount[player]) { printf("Player hand size increased by one.\n"); } else { printf("FAIL: Player hand size failed to increase. Got %d, expected %d.\n", game.handCount[player], handSize); } int hand_count = game.handCount[player]; int top_hand = game.hand[player][hand_count - 1]; int sec_hand = game.hand[player][hand_count - 2]; if ((top_hand >= 4 && top_hand <=6) && (sec_hand >= 4 && sec_hand <=6) ) { printf("Two treasure cards added to hand.\n"); } else { printf("FAIL: two treasure cards not drawn.\n"); } //Test to make sure additional treasures not added to deck int orig_copp = fullDeckCount(player, copper, &game); int orig_silv = fullDeckCount(player, silver, &game); int orig_gold = fullDeckCount(player, gold, &game); adventurerCardEffect(player, 0, &game); int new_copp = fullDeckCount(player, copper, &game); int new_silv = fullDeckCount(player, silver, &game); int new_gold = fullDeckCount(player, gold, &game); if ((orig_copp == new_copp) && (orig_silv == new_silv) && (orig_gold == new_gold)) { printf("No new treasures added to take.\n"); } else { printf("FAIL: treasures added or removed from deck.\n"); } // Test if other players are unaffected. int orig_deck_count = game.deckCount[other_player]; int orig_hand_count = game.handCount[other_player]; villageCardEffect(player, 0, &game); if (orig_deck_count == game.deckCount[other_player]) { printf("Other player's deck unaffected.\n"); } else { printf("FAIL: other player's deck changed\n"); } if (orig_hand_count == game.handCount[other_player]) { printf("Other player's hand unaffected.\n"); } else { printf("FAIL: other player's hand changed\n"); } // Test if global supplies unaffected int i; int changed = 0; int changed_card; int orig_supplies[17]; for (i = 0; i < 17; i++) { orig_supplies[i] = game.supplyCount[all_cards[i]]; } adventurerCardEffect(player, 0, &game); for (i = 0; i < 17; i++) { if (orig_supplies[i] != game.supplyCount[all_cards[i]]) { changed = 1; changed_card = all_cards[i]; } } if (changed == 0) { printf("Supplies unchanged.\n"); } else { printf("FAIL: supplies changed. Last cards supply changed was #%d\n.", changed_card); } return 0; }
int main() { srand(time(NULL)); struct gameState game; int cards[10] = { adventurer, council_room, feast, gardens, mine, remodel, smithy, village, baron, great_hall }; int all_cards[17] = { adventurer, council_room, feast, gardens, mine, remodel, smithy, village, baron, great_hall, copper, silver, gold, estate, duchy, province, curse }; int player = 0; int other_player = 1; int failed = 0; int fail_iteration; printf("Starting random testing for adventurerCardEffect.\n"); int i; for (i = 0; i < 30000; i++) { //Randomize the game initializeGame(2, cards, 1, &game); game.playedCardCount = 0; genRandomDeck(player, &game); genRandomHand(player, &game); genRandomDiscard(player, &game); printf("Random iteration #%d, Deck size: %d, Hand size: %d, Discard size: %d\n", i, game.deckCount[player], game.handCount[player], game.discardCount[player]); int card_pos = pickHandCard(player, &game); game.hand[player][card_pos] = adventurer; //Capture preconditions int pre_money_count_deck = moneyCountDeck(player, &game); int pre_money_count_hand = moneyCountHand(player, &game); int start_hand_size = game.handCount[player]; int total_cards = game.deckCount[player] + game.handCount[player] + game.discardCount[player]; int j; int orig_supplies[17]; for (j = 0; j < 17; j++) { orig_supplies[j] = game.supplyCount[all_cards[j]]; } int orig_deck_count = game.deckCount[other_player]; int orig_hand_count = game.handCount[other_player]; int orig_disc_count = game.discardCount[other_player]; //Run method adventurerCardEffect(player, card_pos, &game); //Check postconditions int post_money_count_deck = moneyCountDeck(player, &game); int post_money_count_hand = moneyCountHand(player, &game); if (pre_money_count_deck == 0) { if (start_hand_size - 1 != game.handCount[player]) { printf("Failed: No money in deck or discard, so handsize should decrease by 1.\n"); printf("Expected %d, got %d\n", start_hand_size - 1, game.handCount[player]); failed++; fail_iteration = i; } if (post_money_count_deck != pre_money_count_deck || post_money_count_hand != pre_money_count_hand) { printf("Failed: No money in deck or discard, so number of coins should be unchanged in hand and deck.\n"); failed++; fail_iteration = i; } } else if (pre_money_count_deck == 1) { if (start_hand_size != game.handCount[player] ) { printf("Failed: One money in deck or discard, so handsize should stay the same.\n"); failed++; fail_iteration = i; } if (post_money_count_deck != pre_money_count_deck - 1 || post_money_count_hand != pre_money_count_hand + 1) { printf("Failed: One money in deck or discard, so number of coins should be +1 in hand and -1 in deck.\n"); failed++; fail_iteration = i; } } else if (pre_money_count_deck > 1) { if (start_hand_size + 1 != game.handCount[player]) { printf("Failed: At least two money in deck or discard, so handsize should increase by 1.\n"); failed++; fail_iteration = i; } if (post_money_count_deck != pre_money_count_deck - 2 || post_money_count_hand != pre_money_count_hand + 2) { printf("Failed: Two money in deck or discard, so number of coins should be +2 in hand and -2 in deck.\n"); failed++; fail_iteration = i; } } int post_total_cards = game.deckCount[player] + game.handCount[player] + game.discardCount[player] + game.playedCardCount; if (total_cards != post_total_cards) { printf("Failed: started with %d cards total, ended with %d\n", total_cards, post_total_cards); failed += 1; fail_iteration = i; } int post_deck_count = game.deckCount[other_player]; int post_hand_count = game.handCount[other_player]; int post_disc_count = game.discardCount[other_player]; if (post_deck_count != orig_deck_count || post_hand_count != orig_hand_count || post_disc_count != orig_disc_count) { printf("Failed: other player's cards were affected.\n"); failed++; fail_iteration = i; } int changed = 0; int changed_card; for (j = 0; j < 17; j++) { if (orig_supplies[j] != game.supplyCount[all_cards[j]]) { changed = 1; changed_card = all_cards[j]; } } if (changed != 0) { printf("FAIL: supplies changed. Last cards supply changed was #%d\n.", changed_card); failed++; fail_iteration = i; } } if (failed == 0) { printf("All tests passed!\n"); } else { printf("FAILED: Number of failed tests: %d. Last failure was for iteration #%d.\n", failed, fail_iteration); } return 0; }
int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus) { int i; int j; int x; int currentPlayer = whoseTurn(state); int nextPlayer = currentPlayer + 1; int tributeRevealedCards[2] = {-1, -1}; int temphand[MAX_HAND]; // moved above the if statement if (nextPlayer > (state->numPlayers - 1)) { nextPlayer = 0; } //uses switch to select card and perform actions switch (card) { case adventurer: return adventurerCardEffect(currentPlayer, state); case council_room: //+4 Cards for (i = 0; i < 4; i++) { drawCard(currentPlayer, state); } //+1 Buy state->numBuys++; //Each other player draws a card for (i = 0; i < state->numPlayers; i++) { if (i != currentPlayer) { drawCard(i, state); } } //put played card in played card pile discardCard(handPos, currentPlayer, state, 0); return 0; case feast: //gain card with cost up to 5 //Backup hand for (i = 0; i <= state->handCount[currentPlayer]; i++) { temphand[i] = state->hand[currentPlayer][i]; //Backup card state->hand[currentPlayer][i] = -1; //Set to nothing } //Backup hand //Update Coins for Buy updateCoins(currentPlayer, state, 5); x = 1; //Condition to loop on while (x == 1) { //Buy one card if (supplyCount(choice1, state) <= 0) { if (DEBUG) { printf("None of that card left, sorry!\n"); } if (DEBUG) { printf("Cards Left: %d\n", supplyCount(choice1, state)); } } else if (state->coins < getCost(choice1)) { printf("That card is too expensive!\n"); if (DEBUG) { printf("Coins: %d < %d\n", state->coins, getCost(choice1)); } } else { if (DEBUG) { printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]); } gainCard(choice1, state, 0, currentPlayer); //Gain the card x = 0; //No more buying cards if (DEBUG) { printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]); } } } //Reset Hand for (i = 0; i <= state->handCount[currentPlayer]; i++) { state->hand[currentPlayer][i] = temphand[i]; temphand[i] = -1; } //Reset Hand return 0; case gardens: return -1; case mine: j = state->hand[currentPlayer][choice1]; //store card we will trash if (state->hand[currentPlayer][choice1] < copper || state->hand[currentPlayer][choice1] > gold) { return -1; } if (choice2 > treasure_map || choice2 < curse) { return -1; } if ((getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2)) { return -1; } gainCard(choice2, state, 2, currentPlayer); //discard card from hand discardCard(handPos, currentPlayer, state, 0); //discard trashed card for (i = 0; i < state->handCount[currentPlayer]; i++) { if (state->hand[currentPlayer][i] == j) { discardCard(i, currentPlayer, state, 0); break; } } return 0; case remodel: j = state->hand[currentPlayer][choice1]; //store card we will trash if ((getCost(state->hand[currentPlayer][choice1]) + 2) > getCost(choice2)) { return -1; } gainCard(choice2, state, 0, currentPlayer); //discard card from hand discardCard(handPos, currentPlayer, state, 0); //discard trashed card for (i = 0; i < state->handCount[currentPlayer]; i++) { if (state->hand[currentPlayer][i] == j) { discardCard(i, currentPlayer, state, 0); break; } } return 0; case smithy: return smithyCardEffect(currentPlayer, handPos, state); case village: //+1 Card drawCard(currentPlayer, state); //+2 Actions state->numActions = state->numActions + 2; //discard played card from hand discardCard(handPos, currentPlayer, state, 0); return 0; case baron: state->numBuys++; //Increase buys by 1! if (choice1 > 0) { //Boolean true or going to discard an estate int p = 0; //Iterator for hand! int card_not_discarded = 1; //Flag for discard set! while (card_not_discarded) { if (state->hand[currentPlayer][p] == estate) { //Found an estate card! state->coins += 4; //Add 4 coins to the amount of coins state->discard[currentPlayer][state->discardCount[currentPlayer]] = state->hand[currentPlayer][p]; state->discardCount[currentPlayer]++; for (; p < state->handCount[currentPlayer]; p++) { state->hand[currentPlayer][p] = state->hand[currentPlayer][p + 1]; } state->hand[currentPlayer][state->handCount[currentPlayer]] = -1; state->handCount[currentPlayer]--; card_not_discarded = 0; //Exit the loop } else if (p > state->handCount[currentPlayer]) { if (DEBUG) { printf("No estate cards in your hand, invalid choice\n"); printf("Must gain an estate if there are any\n"); } if (supplyCount(estate, state) > 0) { gainCard(estate, state, 0, currentPlayer); state->supplyCount[estate]--; //Decrement estates if (supplyCount(estate, state) == 0) { isGameOver(state); } } card_not_discarded = 0; //Exit the loop } else { p++; //Next card } } } else { if (supplyCount(estate, state) > 0) { gainCard(estate, state, 0, currentPlayer); //Gain an estate state->supplyCount[estate]--; //Decrement Estates if (supplyCount(estate, state) == 0) { isGameOver(state); } } } return 0; case great_hall: return greatHallCardEffect(currentPlayer, handPos, state); case minion: //+1 action state->numActions++; //discard card from hand discardCard(handPos, currentPlayer, state, 0); if (choice1) //+2 coins { state->coins = state->coins + 2; } else if (choice2) //discard hand, redraw 4, other players with 5+ cards discard hand and draw 4 { //discard hand while (numHandCards(state) > 0) { discardCard(handPos, currentPlayer, state, 0); } //draw 4 for (i = 0; i < 4; i++) { drawCard(currentPlayer, state); } //other players discard hand and redraw if hand size > 4 for (i = 0; i < state->numPlayers; i++) { if (i != currentPlayer) { if (state->handCount[i] > 4) { //discard hand while (state->handCount[i] > 0) { discardCard(handPos, i, state, 0); } //draw 4 for (j = 0; j < 4; j++) { drawCard(i, state); } } } } } return 0; case steward: if (choice1 == 1) { //+2 cards drawCard(currentPlayer, state); drawCard(currentPlayer, state); } else if (choice1 == 2) { //+2 coins state->coins = state->coins + 2; } else { //trash 2 cards in hand discardCard(choice2, currentPlayer, state, 1); discardCard(choice3, currentPlayer, state, 1); } //discard card from hand discardCard(handPos, currentPlayer, state, 0); return 0; case tribute: if ((state->discardCount[nextPlayer] + state->deckCount[nextPlayer]) <= 1) { if (state->deckCount[nextPlayer] > 0) { tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer] - 1]; state->deckCount[nextPlayer]--; } else if (state->discardCount[nextPlayer] > 0) { tributeRevealedCards[0] = state->discard[nextPlayer][state->discardCount[nextPlayer] - 1]; state->discardCount[nextPlayer]--; } else { //No Card to Reveal if (DEBUG) { printf("No cards to reveal\n"); } } } else { if (state->deckCount[nextPlayer] == 0) { for (i = 0; i < state->discardCount[nextPlayer]; i++) { state->deck[nextPlayer][i] = state->discard[nextPlayer][i]; //Move to deck state->deckCount[nextPlayer]++; state->discard[nextPlayer][i] = -1; state->discardCount[nextPlayer]--; } shuffle(nextPlayer, state); //Shuffle the deck } tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer] - 1]; state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; state->deckCount[nextPlayer]--; tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer] - 1]; state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; state->deckCount[nextPlayer]--; } if (tributeRevealedCards[0] == tributeRevealedCards[1]) { //If we have a duplicate card, just drop one state->playedCards[state->playedCardCount] = tributeRevealedCards[1]; state->playedCardCount++; tributeRevealedCards[1] = -1; } for (i = 0; i <= 2; i++) { if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold) { //Treasure cards state->coins += 2; } else if (tributeRevealedCards[i] == estate || tributeRevealedCards[i] == duchy || tributeRevealedCards[i] == province || tributeRevealedCards[i] == gardens || tributeRevealedCards[i] == great_hall) { //Victory Card Found drawCard(currentPlayer, state); drawCard(currentPlayer, state); } else { //Action Card state->numActions = state->numActions + 2; } } return 0; case ambassador: j = 0; //used to check if player has enough cards to discard if (choice2 > 2 || choice2 < 0) { return -1; } if (choice1 == handPos) { return -1; } for (i = 0; i < state->handCount[currentPlayer]; i++) { if (i != handPos && i == state->hand[currentPlayer][choice1] && i != choice1) { j++; } } if (j < choice2) { return -1; } if (DEBUG) { printf("Player %d reveals card number: %d\n", currentPlayer, state->hand[currentPlayer][choice1]); } //increase supply count for choosen card by amount being discarded state->supplyCount[state->hand[currentPlayer][choice1]] += choice2; //each other player gains a copy of revealed card for (i = 0; i < state->numPlayers; i++) { if (i != currentPlayer) { gainCard(state->hand[currentPlayer][choice1], state, 0, i); } } //discard played card from hand discardCard(handPos, currentPlayer, state, 0); //trash copies of cards returned to supply for (j = 0; j < choice2; j++) { for (i = 0; i < state->handCount[currentPlayer]; i++) { if (state->hand[currentPlayer][i] == state->hand[currentPlayer][choice1]) { discardCard(i, currentPlayer, state, 1); break; } } } return 0; case cutpurse: return cutpurseCardEffect(currentPlayer, handPos, state); case embargo: //+2 Coins state->coins = state->coins + 2; //see if selected pile is in play if (state->supplyCount[choice1] == -1) { return -1; } //add embargo token to selected supply pile state->embargoTokens[choice1]++; //trash card discardCard(handPos, currentPlayer, state, 1); return 0; case outpost: //set outpost flag state->outpostPlayed++; //discard card discardCard(handPos, currentPlayer, state, 0); return 0; case salvager: //+1 buy state->numBuys++; if (choice1) { //gain coins equal to trashed card state->coins = state->coins + getCost(handCard(choice1, state)); //trash card discardCard(choice1, currentPlayer, state, 1); } //discard card discardCard(handPos, currentPlayer, state, 0); return 0; case sea_hag: for (i = 0; i < state->numPlayers; i++) { if (i != currentPlayer) { state->discard[i][state->discardCount[i]] = state->deck[i][state->deckCount[i]--]; state->deckCount[i]--; state->discardCount[i]++; state->deck[i][state->deckCount[i]--] = curse; //Top card now a curse } } return 0; case treasure_map: return treasureMapCardEffect(currentPlayer, handPos, state); } return -1; }