int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus) { int i; int j; int k; int index; int currentPlayer = whoseTurn(state); int nextPlayer = currentPlayer + 1; int tributeRevealedCards[2] = {-1, -1}; int drawntreasure=0; if (nextPlayer > (state->numPlayers - 1)){ nextPlayer = 0; } //uses switch to select card and perform actions switch( card ) { case adventurer: return adventurerCard (drawntreasure, state, currentPlayer); case council_room: return councilRoomCard (currentPlayer, state, handPos); case feast: return feastCard (currentPlayer, state, choice1); case gardens: return -1; case mine: return mineCard (currentPlayer, state, choice1, choice2, handPos); case remodel: return remodelCard (currentPlayer, state, choice1, choice2, handPos); case smithy: //+3 Cards for (i = 0; i < 3; i++) { drawCard(currentPlayer, state); } //discard card from hand discardCard(handPos, currentPlayer, state, 0); return 0; 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: //+1 Card drawCard(currentPlayer, state); //+1 Actions state->numActions++; //discard card from hand discardCard(handPos, currentPlayer, state, 0); return 0; 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: updateCoins(currentPlayer, state, 2); for (i = 0; i < state->numPlayers; i++) { if (i != currentPlayer) { for (j = 0; j < state->handCount[i]; j++) { if (state->hand[i][j] == copper) { discardCard(j, i, state, 0); break; } if (j == state->handCount[i]) { for (k = 0; k < state->handCount[i]; k++) { if (DEBUG) printf("Player %d reveals card number %d\n", i, state->hand[i][k]); } break; } } } } //discard played card from hand discardCard(handPos, currentPlayer, state, 0); return 0; 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]-1]; state->discardCount[i]++; state->deck[i][state->deckCount[i]-1] = curse;//Top card now a curse } } return 0; case treasure_map: //search hand for another treasure_map index = -1; for (i = 0; i < state->handCount[currentPlayer]; i++) { if (state->hand[currentPlayer][i] == treasure_map && i != handPos) { index = i; break; } } if (index > -1) { //trash both treasure cards discardCard(handPos, currentPlayer, state, 1); discardCard(index, currentPlayer, state, 1); //gain 4 Gold cards for (i = 0; i < 4; i++) { gainCard(gold, state, 1, currentPlayer); } //return success return 1; } //no second treasure_map found in hand return -1; } return -1; }
int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus) { int i; int j; int index; int currentPlayer = whoseTurn(state); int nextPlayer = currentPlayer + 1; int tributeRevealedCards[2] = { -1, -1 }; int temphand[MAX_HAND];// moved above the if statement int drawntreasure = 0; int cardDrawn; int z = 0;// this is the counter for the temp hand if (nextPlayer > (state->numPlayers - 1)) { nextPlayer = 0; } //uses switch to select card and perform actions switch (card) { case adventurer: playedCard(handPos, NULL, NULL, state); while (drawntreasure < 2) { if (drawCard(currentPlayer, state) == -1) break; cardDrawn = state->hand[currentPlayer][state->handCount[currentPlayer] - 1];//top card of hand is most recently drawn card. if (cardDrawn == copper || cardDrawn == silver || cardDrawn == gold) drawntreasure++; else { temphand[z] = cardDrawn; state->hand[currentPlayer][state->handCount[currentPlayer] - 1] = -1; state->handCount[currentPlayer]--; //this should just remove the top card (the most recently drawn one). z++; } } while (z > 0) { state->discard[currentPlayer][state->discardCount[currentPlayer]++] = temphand[z - 1]; // discard all cards in play that have been drawn z--; } endPlayed(state, 0); return 0; case council_room: return councilRoomEffect(currentPlayer, handPos, state); case feast: if (choice1 < curse || choice1 > treasure_map) return -1; 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)); } return -1; } else if (5 < getCost(choice1)) { if (DEBUG) { printf("That card is too expensive!\n"); printf("Coins: %d < %d\n", state->coins, getCost(choice1)); } return -1; } playedCard(handPos, NULL, NULL, state); if (DEBUG) { printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]); } gainCard(choice1, state, 0, currentPlayer);//Gain the card if (DEBUG) { printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]); } //trash feast endPlayed(state, 1); return 0; case gardens: return -1; case mine: if (choice1 >= state->handCount[currentPlayer] || choice1 < 0 || choice1 == handPos) return -1; 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 > gold || choice2 < copper) { return -1; } if ((getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2)) { return -1; } playedCard(handPos, &choice1, NULL, state); //trash old treasure discardCard(choice1, currentPlayer, state, 1); //gain new treasure gainCard(choice2, state, 2, currentPlayer); endPlayed(state, 0); return 0; case remodel: if (choice1 >= state->handCount[currentPlayer] || choice1 < 0 || choice1 == handPos) return -1; if (choice2 < curse || choice2 > treasure_map) return -1; if ((getCost(state->hand[currentPlayer][choice1]) + 2) > getCost(choice2)) { return -1; } playedCard(handPos, &choice1, NULL, state); //trash choice discardCard(choice1, currentPlayer, state, 1); //gain new card gainCard(choice2, state, 0, currentPlayer); endPlayed(state, 0); return 0; case smithy: return smithyEffect(currentPlayer, handPos, state); case village: return villageEffect(currentPlayer, handPos, state); case baron: if (!(choice1 == 1 || choice1 == 2)) return -1; if (choice1 == 1) {//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 (p >= state->handCount[currentPlayer]) { if (DEBUG) { printf("No estate cards in your hand, invalid choice\n"); } return -1; } else if (state->hand[currentPlayer][p] == estate) {//Found an estate card! playedCard(handPos, &p, NULL, state); *bonus += 4;//Add 4 coins to the amount of coins discardCard(p, currentPlayer, state, 0); card_not_discarded = 0;//Exit the loop } else { p++;//Next card } } } else { playedCard(handPos, NULL, NULL, state); gainCard(estate, state, 0, currentPlayer);//Gain an estate } state->numBuys++;//Increase buys by 1! endPlayed(state, 0); return 0; case great_hall: return greatHallEffect(currentPlayer, handPos, state); case minion: if (!(choice1 == 1 || choice1 == 2)) return -1; playedCard(handPos, NULL, NULL, state); //+1 action state->numActions++; if (choice1 == 1) //+2 coins { *bonus += 2; } else if (choice1 == 2) //discard hand, redraw 4, other players with 5+ cards discard hand and draw 4 { //discard hand while (numHandCards(state) > 0) { discardCard(0, 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(0, i, state, 0); } //draw 4 for (j = 0; j < 4; j++) { drawCard(i, state); } } } } } endPlayed(state, 0); return 0; case steward: if (!(choice1 == 1 || choice1 == 2 || choice1 == 3)) return -1; if (choice1 == 3 && ((choice2 >= state->handCount[currentPlayer] || choice2 < 0) || (choice3 >= state->handCount[currentPlayer] || choice3 < 0) || choice2 == choice3 || (choice2 == handPos || choice3 == handPos))) return -1; if (choice1 == 1) { playedCard(handPos, NULL, NULL, state); //+2 cards drawCard(currentPlayer, state); drawCard(currentPlayer, state); } else if (choice1 == 2) { //+2 coins playedCard(handPos, NULL, NULL, state); *bonus += 2; } else { playedCard(handPos, &choice2, &choice3, state); //trash 2 cards in hand if (choice2 < choice3) { int tmp = choice2; choice2 = choice3; choice3 = tmp; } //discard order matters, must discard max to min for correct effect discardCard(choice2, currentPlayer, state, 1); discardCard(choice3, currentPlayer, state, 1); } endPlayed(state, 0); return 0; case tribute: playedCard(handPos, NULL, NULL, state); 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]--; state->discard[nextPlayer][state->discardCount[nextPlayer]] = tributeRevealedCards[0]; state->discardCount[nextPlayer]++; } else if (state->discardCount[nextPlayer] > 0) { tributeRevealedCards[0] = state->discard[nextPlayer][state->discardCount[nextPlayer] - 1]; } else { //No Card to Reveal if (DEBUG) { printf("No cards to reveal\n"); } endPlayed(state, 0); return 0; } } else { if (state->deckCount[nextPlayer] == 0) { j = state->discardCount[nextPlayer]; for (i = 0; i < j; 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] = -1; state->deckCount[nextPlayer]--; if (state->deckCount[nextPlayer] == 0) { j = state->discardCount[nextPlayer]; for (i = 0; i < j; 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 } state->discard[nextPlayer][state->discardCount[nextPlayer]] = tributeRevealedCards[0]; state->discardCount[nextPlayer]++; tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer] - 1]; state->deck[nextPlayer][state->deckCount[nextPlayer] - 1] = -1; state->deckCount[nextPlayer]--; state->discard[nextPlayer][state->discardCount[nextPlayer]] = tributeRevealedCards[1]; state->discardCount[nextPlayer]++; } if (tributeRevealedCards[0] == tributeRevealedCards[1]) {//If we have a duplicate card, just drop one tributeRevealedCards[1] = -1; } for (i = 0; i < 2; i++) { if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold) {//Treasure cards *bonus += 2; } 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); } if (tributeRevealedCards[i] >= adventurer && tributeRevealedCards[i] <= treasure_map){//Action Card state->numActions = state->numActions + 2; } } endPlayed(state, 0); 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 || choice1 >= numHandCards(state) || choice1 < 0) { return -1; } for (i = 0; i < state->handCount[currentPlayer]; i++) { if (i != handPos && i == state->hand[currentPlayer][choice1]) { j++; } } if (j < choice2) { return -1; } playedCard(handPos, &choice1, NULL, state); 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); } } //trash copies of cards returned to supply for (j = 0; j < choice2; j++) { for (i = state->handCount[currentPlayer] - 1; i >= 0; i--) { if (state->hand[currentPlayer][i] == state->hand[currentPlayer][choice1]) { discardCard(i, currentPlayer, state, 1); break; } } } endPlayed(state, 0); return 0; case cutpurse: return cutpurseEffect(currentPlayer, handPos, state, bonus); case embargo: if (choice1 < curse || choice1 > treasure_map) return -1; //see if selected pile is in play if (state->supplyCount[choice1] == -1) { return -1; } playedCard(handPos, NULL, NULL, state); //+2 Coins *bonus += 2; //add embargo token to selected supply pile state->embargoTokens[choice1]++; //trash card endPlayed(state, 1); return 0; case outpost: if (state->outpostTurn == 1) return -1; playedCard(handPos, NULL, NULL, state); //set outpost flag state->outpostPlayed = 1; //we actually don't call endPlayed() here on purpose return 0; case salvager: if (choice1 >= state->handCount[currentPlayer] || choice1 < 0 || choice1 == handPos) return -1; playedCard(handPos, &choice1, NULL, state); //+1 buy state->numBuys++; //gain coins equal to trashed card *bonus += getCost(handCard(choice1, state)); //trash card discardCard(choice1, currentPlayer, state, 1); endPlayed(state, 0); return 0; case sea_hag: playedCard(handPos, NULL, NULL, state); for (i = 0; i < state->numPlayers; i++) { if (i != currentPlayer) { if (state->deckCount[i] + state->discardCount[i] > 0) { if (state->deckCount[i] == 0) { j = state->discardCount[i]; for (index = 0; index < j; index++) { state->deck[i][index] = state->discard[i][index];//Move to deck state->deckCount[i]++; state->discard[i][index] = -1; state->discardCount[i]--; } shuffle(i, state);//Shuffle the deck } state->discard[i][state->discardCount[i]] = state->deck[i][state->deckCount[i] - 1]; state->discardCount[i]++; //conveniently, this happens to add it to the top of the deck gainCard(curse, state, 1, i); } else { //literally no cards in their deck or discard, so they just get a curse in their deck gainCard(curse, state, 1, i); } } } endPlayed(state, 0); return 0; case treasure_map: //search hand for another treasure_map index = -1; for (i = 0; i < state->handCount[currentPlayer]; i++) { if (state->hand[currentPlayer][i] == treasure_map && i != handPos) { index = i; break; } } if (index > -1){ playedCard(handPos, &index, NULL, state); //trash other treasure_map discardCard(index, currentPlayer, state, 1); //gain 4 Gold cards for (i = 0; i < 4; i++) { gainCard(gold, state, 1, currentPlayer); } } else { return -1; } endPlayed(state, 1); return 0; } return -1; }
// test discardCard int main(int argc, char** argv) { struct gameState game; int errorPresent = 0; int player; int handPos; player = 1; handPos = 1; game.playedCardCount = 0; // check discarding last card in hand and that played card count doesn't get incremented incorrectly game.hand[player][handPos] = 1; game.handCount[player] = 2; discardCard(handPos, player, &game, 0); if(game.hand[player][handPos] != -1) { printf("\nError in discardCard, the card that was discarded was not set to played.\n"); errorPresent = 1; } if(game.handCount[player] != 1) { printf("\nError in discardCard, the users hand count was not decremented when last card in hand is discarded. Note: not only card, last card position wise\n"); errorPresent = 1; } if(game.playedCardCount != 01) { printf("\nError in discardCard, the played card count was incremented when a card should not have been trashed.\n"); errorPresent = 1; } // check discarding only card in hand game.handCount[player] = 1; game.hand[player][handPos] = 1; discardCard(handPos, player, &game, 0); if(game.handCount[player] != 0) { printf("\nError in discardCard, the users hand count was not decremented when only card in hand is discarded.\n"); errorPresent = 1; } // check discarding middle card in hand with other cards surrounding it and trashing cards game.playedCardCount = 0; game.handCount[player] = 3; game.hand[player][handPos] = 1; game.hand[player][2] = 5; // set last card to unique value discardCard(handPos, player, &game, 0); if(game.handCount[player] != 2) { printf("\nError in discardCard, the users hand count was not decremented when a middle card in hand is discarded.\n"); errorPresent = 1; } if(game.hand[player][handPos] != 5) { printf("\nError in discardCard, the value of the card in the discarded card's position was not updated to the value of the last card in the user's hand when a middle card in hand is discarded.\n"); errorPresent = 1; } if(game.hand[player][2] != -1) { printf("\nError in discardCard, the value of the card in the last card's position was not set to played when a middle card in hand is discarded.\n"); errorPresent = 1; } if(game.playedCards[0] != 1) { printf("\nError in discardCard, the correct card value was not added to the played cards pile when trashed.\n"); errorPresent = 1; } if(game.playedCardCount != 1) { printf("\nError in discardCard, the played card count was not incremented after a card should have been trashed.\n"); errorPresent = 1; } if(errorPresent == 0) { printf("\nNo Errors found in discardCard\n"); } return 0; }
int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus) { int i; int j; int k; int x; int index; int currentPlayer = whoseTurn(state); int nextPlayer = currentPlayer + 1; int tributeRevealedCards[2] = {-1, -1}; int temphand[MAX_HAND];// moved above the if statement int drawntreasure=0; int cardDrawn; int z = 0;// this is the counter for the temp hand if (nextPlayer > (state->numPlayers - 1)){ nextPlayer = 0; } //uses switch to select card and perform actions switch( card ) { case adventurer: while(drawntreasure<2){ if (state->deckCount[currentPlayer] <1){//if the deck is empty we need to shuffle discard and add to deck shuffle(currentPlayer, state); } drawCard(currentPlayer, state); cardDrawn = state->hand[currentPlayer][state->handCount[currentPlayer]-1];//top card of hand is most recently drawn card. if (cardDrawn == copper || cardDrawn == silver || cardDrawn == gold) drawntreasure++; else{ temphand[z]=cardDrawn; state->handCount[currentPlayer]--; //this should just remove the top card (the most recently drawn one). z++; } } while(z-1>=0){ state->discard[currentPlayer][state->discardCount[currentPlayer]++]=temphand[z-1]; // discard all cards in play that have been drawn z=z-1; } return 0; 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: //+3 Cards for (i = 0; i < 3; i++) { drawCard(currentPlayer, state); } //discard card from hand discardCard(handPos, currentPlayer, state, 0); return 0; 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: //+1 Card drawCard(currentPlayer, state); //+1 Actions state->numActions++; //discard card from hand discardCard(handPos, currentPlayer, state, 0); return 0; 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: updateCoins(currentPlayer, state, 2); for (i = 0; i < state->numPlayers; i++) { if (i != currentPlayer) { for (j = 0; j < state->handCount[i]; j++) { if (state->hand[i][j] == copper) { discardCard(j, i, state, 0); break; } if (j == state->handCount[i]) { for (k = 0; k < state->handCount[i]; k++) { if (DEBUG) printf("Player %d reveals card number %d\n", i, state->hand[i][k]); } break; } } } } //discard played card from hand discardCard(handPos, currentPlayer, state, 0); return 0; 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: //search hand for another treasure_map index = -1; for (i = 0; i < state->handCount[currentPlayer]; i++) { if (state->hand[currentPlayer][i] == treasure_map && i != handPos) { index = i; break; } } if (index > -1) { //trash both treasure cards discardCard(handPos, currentPlayer, state, 1); discardCard(index, currentPlayer, state, 1); //gain 4 Gold cards for (i = 0; i < 4; i++) { gainCard(gold, state, 1, currentPlayer); } //return success return 1; } //no second treasure_map found in hand return -1; } return -1; }
int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus) { int i; int j; int k; int x; int index; int currentPlayer = whoseTurn(state); int nextPlayer = currentPlayer + 1; int tributeRevealedCards[2] = {-1, -1}; int temphand[MAX_HAND];// moved above the if statement int drawntreasure=0; // int cardDrawn; int z = 0;// this is the counter for the temp hand if (nextPlayer > (state->numPlayers - 1)) { nextPlayer = 0; } //uses switch to select card and perform actions switch( card ) { case adventurer: return adventurerEffect(state, drawntreasure, z, temphand); 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 smithyEffect(state, handPos); 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: return baronEffect(state, choice1); case great_hall: //+1 Card drawCard(currentPlayer, state); //+1 Actions state->numActions++; //discard card from hand discardCard(handPos, currentPlayer, state, 0); return 0; case minion: return minionEffect(state, handPos, choice1, choice2); case steward: return stewardEffect(state, handPos, choice1, choice2, choice3); 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: return ambassadorEffect(state, handPos, choice1, choice2); case cutpurse: updateCoins(currentPlayer, state, 2); for (i = 0; i < state->numPlayers; i++) { if (i != currentPlayer) { for (j = 0; j < state->handCount[i]; j++) { if (state->hand[i][j] == copper) { discardCard(j, i, state, 0); break; } if (j == state->handCount[i]) { for (k = 0; k < state->handCount[i]; k++) { if (DEBUG) printf("Player %d reveals card number %d\n", i, state->hand[i][k]); } break; } } } } //discard played card from hand discardCard(handPos, currentPlayer, state, 0); return 0; case embargo: return embargoEffect(state, handPos, choice1); case outpost: //set outpost flag state->outpostPlayed++; //discard card discardCard(handPos, state->whoseTurn, 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: //search hand for another treasure_map index = -1; for (i = 0; i < state->handCount[currentPlayer]; i++) { if (state->hand[currentPlayer][i] == treasure_map && i != handPos) { index = i; break; } } if (index > -1) { //trash both treasure cards discardCard(handPos, currentPlayer, state, 1); discardCard(index, currentPlayer, state, 1); //gain 4 Gold cards for (i = 0; i < 4; i++) { gainCard(gold, state, 1, currentPlayer); } //return success return 1; } //no second treasure_map found in hand return -1; } return -1; }
int main() { int seed = 1000; int numPlayers = 4; int handNum, handPos, player, trashFlag, result; int k[10] = {adventurer, council_room, feast, gardens, mine , remodel, smithy, village, baron, great_hall}; struct gameState G, testG; initializeGame(numPlayers, k, seed, &G); int hands[3][15] = {{copper, gold, village, estate, smithy}, {gold}, {silver, province, copper, copper, feast, baron, remodel, copper, smithy, province, duchy, estate, copper, mine, gardens}}; int handCounts[3] = {5, 1, 8}; printf("\n----------------- Testing Function: %s ----------------\n", TESTFUNCTION); memcpy(&testG, &G, sizeof(struct gameState)); for (player = 0; player < numPlayers; player++) //for each of the players { G.whoseTurn = player; for (handNum = 0; handNum < 3; handNum++) //for each of the 3 predefined hands { memcpy(&G.hand[player], &hands[handNum], sizeof(hands[handNum])); //load new hand G.handCount[player] = handCounts[handNum]; //load new handCount for (handPos = 0; handPos < handCounts[handNum]; handPos++) //for every card in the hand { for (trashFlag = 0; trashFlag < 2; trashFlag ++) { memcpy(&testG, &G, sizeof(struct gameState)); //restore game state discardCard(handPos, player, &testG, trashFlag); #if (NOISY_TEST == 1) printf("handCount = %d, expected = %d\n", testG.handCount[player], G.handCount[player] - 1); #endif assert(testG.handCount[player] == handCounts[handNum] - 1); #if (NOISY_TEST == 1) printf("playedCardCount = %d, expected = %d\n", testG.playedCardCount, G.playedCardCount + 1 - trashFlag); #endif assert(testG.playedCardCount == G.playedCardCount + 1 - trashFlag); if (trashFlag == 0) //if it wasn't trashed, it should be in the played cards pile { #if (NOISY_TEST == 1) printf("playedCard = %d, expected = %d\n", testG.playedCards[0], hands[handNum][handPos]); #endif assert(testG.playedCards[0] == hands[handNum][handPos]); } //restore values and check that the rest of the game was left intact testG.handCount[player] = G.handCount[player]; testG.playedCardCount = G.playedCardCount; memcpy(&testG.hand[player], &G.hand[player], sizeof(G.hand[player])); if (trashFlag == 0) { memcpy(&testG.playedCards, &G.playedCards, sizeof(G.playedCards)); } result = memcmp(&testG, &G, sizeof(struct gameState)); #if (NOISY_TEST == 1) printf("memcmp result = %d, expected = %d\n", result, 0); #endif assert(result == 0); } } } } printf("All tests passed!\n"); return 0; }