Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

need some help. We are working on code that will simulate the card game Dominion

ID: 3877258 • Letter: N

Question

need some help. We are working on code that will simulate the card game Dominion. I have provided the relevant code I believe. Please let me know if you need clarification. The following paragraphs are the instructions that must be followed. The code below is pulled from existing code that currently runs properly. The switch runs in the dominion.c file. I have provided the dominion.c and dominion.h files. I am not sure what bugs they want but just some simple bugs that may make the code not work properly.

1) Read the rules and the source code of Dominion, and understand the game sufficiently to be comfortable with testing an implementation of it!. Your first job is to become a “subject expert” in Dominion, since you will be testing an implementation of it. Note that the primary source of information about the Dominion implementation itself is the dominion.c and dominion.h files provided in the class repository. The specification you use will have to combine this information with knowledge about how the game works, discovered by investigation. This is a typical testing experience, where you are not given a complete specification, but must discover one for yourself.

Pick 5 cards implemented in dominion.c. Choose 3 cards of your choice and smithy and adventurer cards are mandatory. Refactor the code so that these cards are implemented in their own functions, rather than as part of the switch statement in cardEffect. You should call the functions for these cards in the appropriate place in cardEffect. The 5 cards I am using is Adventurer, smithy, gardens, outpost, and council room card.


2) Introduce some bug(s) in 4 cards out of these 5 cards, preferably “subtle” ones that might easily escape a decent test suite. By bugs I mean something that does not behave correctly – it may crash, or it may cause incorrect Dominion behavior. Introducing bugs in smithy and adventurer is mandatory. ALL CODE SHOULD BE COMPILED and RUN. Again, the code for the cards is below.

3) Document your changes of the five cards in the, discussing the process of extracting the functions. In addtion, write information of your bugs.

CODE FOR THE CARDS AND cardEFFECT FUNCTION

#include "dominion.h"
#include "dominion_helpers.h"
#include "rngs.h"
#include
#include
#include

int compare(const void* a, const void* b) {
if (*(int*)a > *(int*)b)
    return 1;
if (*(int*)a < *(int*)b)
    return -1;
return 0;
}

struct gameState* newGame() {
struct gameState* g = malloc(sizeof(struct gameState));
return g;
}

int* kingdomCards(int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8, int k9, int k10) {
int* k = malloc(10 * sizeof(int));
k[0] = k1;
k[1] = k2;
k[2] = k3;
k[3] = k4;
k[4] = k5;
k[5] = k6;
k[6] = k7;
k[7] = k8;
k[8] = k9;
k[9] = k10;
return k;
}

int initializeGame(int numPlayers, int kingdomCards[10], int randomSeed,struct gameState *state) {

int i;
int j;
int it;   
//set up random number generator
SelectStream(1);
PutSeed((long)randomSeed);

//check number of players
if (numPlayers > MAX_PLAYERS || numPlayers < 2){
      return -1;
    }

//set number of players
state->numPlayers = numPlayers;

//check selected kingdom cards are different
for (i = 0; i < 10; i++){
      for (j = 0; j < 10; j++){
   if (j != i && kingdomCards[j] == kingdomCards[i]){
       return -1;
     }
        }
    }

//initialize supply
///////////////////////////////

//set number of Curse cards
if (numPlayers == 2){
      state->supplyCount[curse] = 10;
    }else if (numPlayers == 3){
      state->supplyCount[curse] = 20;
    }else{
      state->supplyCount[curse] = 30;
    }

//set number of Victory cards
if (numPlayers == 2){
      state->supplyCount[estate] = 8;
      state->supplyCount[duchy] = 8;
      state->supplyCount[province] = 8;
    }else{
      state->supplyCount[estate] = 12;
      state->supplyCount[duchy] = 12;
      state->supplyCount[province] = 12;
    }

//set number of Treasure cards
state->supplyCount[copper] = 60 - (7 * numPlayers);
state->supplyCount[silver] = 40;
state->supplyCount[gold] = 30;

//set number of Kingdom cards
for (i = adventurer; i <= treasure_map; i++){       //loop all cards
      for (j = 0; j < 10; j++){    //loop chosen cards
   if (kingdomCards[j] == i){
       //check if card is a 'Victory' Kingdom card
       if (kingdomCards[j] == great_hall || kingdomCards[j] == gardens){
    if (numPlayers == 2){
      state->supplyCount[i] = 8;
    }else{ state->supplyCount[i] = 12; }
  }else{
    state->supplyCount[i] = 10;
  }
       break;
     }else{    //card is not in the set choosen for the game
       state->supplyCount[i] = -1;
     }
}

    }

////////////////////////
//supply intilization complete

//set player decks
for (i = 0; i < numPlayers; i++){
      state->deckCount[i] = 0;
      for (j = 0; j < 3; j++){
   state->deck[i][j] = estate;
   state->deckCount[i]++;
}
      for (j = 3; j < 10; j++){
   state->deck[i][j] = copper;
   state->deckCount[i]++;  
}
    }

//shuffle player decks
for (i = 0; i < numPlayers; i++){
      if ( shuffle(i, state) < 0 ){
   return -1;
}
    }

//draw player hands
for (i = 0; i < numPlayers; i++){
      //initialize hand size to zero
      state->handCount[i] = 0;
      state->discardCount[i] = 0;
      //draw 5 cards
      // for (j = 0; j < 5; j++)
      // {
      //   drawCard(i, state);
      // }
    }
//set embargo tokens to 0 for all supply piles
for (i = 0; i <= treasure_map; i++){
      state->embargoTokens[i] = 0;
    }

//initialize first player's turn
state->outpostPlayed = 0;
state->phase = 0;
state->numActions = 1;
state->numBuys = 1;
state->playedCardCount = 0;
state->whoseTurn = 0;
state->handCount[state->whoseTurn] = 0;
//int it; move to top

//Moved draw cards to here, only drawing at the start of a turn
for (it = 0; it < 5; it++){
    drawCard(state->whoseTurn, state);
}

updateCoins(state->whoseTurn, state, 0);

return 0;
}

int shuffle(int player, struct gameState *state) {

int newDeck[MAX_DECK];
int newDeckPos = 0;
int card;
int i;

if (state->deckCount[player] < 1)
    return -1;
qsort ((void*)(state->deck[player]), state->deckCount[player], sizeof(int), compare);
/* SORT CARDS IN DECK TO ENSURE DETERMINISM! */

while (state->deckCount[player] > 0) {
    card = floor(Random() * state->deckCount[player]);
    newDeck[newDeckPos] = state->deck[player][card];
    newDeckPos++;
    for (i = card; i < state->deckCount[player]-1; i++) {
      state->deck[player][i] = state->deck[player][i+1];
    }
    state->deckCount[player]--;
}
for (i = 0; i < newDeckPos; i++) {
    state->deck[player][i] = newDeck[i];
    state->deckCount[player]++;
}

return 0;
}

int playCard(int handPos, int choice1, int choice2, int choice3, struct gameState *state)
{
int card;
int coin_bonus = 0;   //tracks coins gain from actions

//check if it is the right phase
if (state->phase != 0){
      return -1;
    }
//check if player has enough actions
if ( state->numActions < 1 ){
      return -1;
    }
//get card played
card = handCard(handPos, state);
//check if selected card is an action
if ( card < adventurer || card > treasure_map ){
      return -1;
    }
//play card
if ( cardEffect(card, choice1, choice2, choice3, state, handPos,& coin_bonus) < 0 ){
      return -1;
    }
//reduce number of actions
state->numActions--;

//update coins (Treasure cards may be added with card draws)
updateCoins(state->whoseTurn, state, coin_bonus);
return 0;
}

int buyCard(int supplyPos, struct gameState *state) {
int who;
if (DEBUG){
    printf("Entering buyCard... ");
}

// I don't know what to do about the phase thing.

who = state->whoseTurn;

if (state->numBuys< 1){
    if (DEBUG)
      printf("You do not have any buys left ");
    return -1;
} else if (supplyCount(supplyPos, state) <1){
    if (DEBUG)
      printf("There are not any of that type of card left ");
    return -1;
} else if (state->coins < getCost(supplyPos)){
    if (DEBUG)
      printf("You do not have enough money to buy that. You have %d coins. ", state->coins);
    return -1;
} else {
    state->phase=1;
    //state->supplyCount[supplyPos]--;
    gainCard(supplyPos, state, 0, who); //card goes in discard, this might be wrong.. (2 means goes into hand, 0 goes into discard)
state->coins = (state->coins) - (getCost(supplyPos));
    state->numBuys--;
    if (DEBUG)
      printf("You bought card number %d for %d coins. You now have %d buys and %d coins. ", supplyPos, getCost(supplyPos), state->numBuys, state->coins);
}

//state->discard[who][state->discardCount[who]] = supplyPos;
//state->discardCount[who]++;
return 0;
}

int numHandCards(struct gameState *state) {
return state->handCount[ whoseTurn(state) ];
}

int handCard(int handPos, struct gameState *state) {
int currentPlayer = whoseTurn(state);
return state->hand[currentPlayer][handPos];
}

int supplyCount(int card, struct gameState *state) {
return state->supplyCount[card];
}

int fullDeckCount(int player, int card, struct gameState *state) {
int i;
int count = 0;

for (i = 0; i < state->deckCount[player]; i++){
      if (state->deck[player][i] == card) count++;
    }

for (i = 0; i < state->handCount[player]; i++){
      if (state->hand[player][i] == card) count++;
    }

for (i = 0; i < state->discardCount[player]; i++){
      if (state->discard[player][i] == card) count++;
    }

return count;
}

int whoseTurn(struct gameState *state) {
return state->whoseTurn;
}

int endTurn(struct gameState *state) {
int k;
int i;
int currentPlayer = whoseTurn(state);
//Discard hand
for (i = 0; i < state->handCount[currentPlayer]; i++){
    state->discard[currentPlayer][state->discardCount[currentPlayer]++] = state->hand[currentPlayer][i];//Discard
    state->hand[currentPlayer][i] = -1;//Set card to -1
}
state->handCount[currentPlayer] = 0;//Reset hand count
   
//Code for determining the player
if (currentPlayer < (state->numPlayers - 1)){
    state->whoseTurn = currentPlayer + 1;//Still safe to increment
}else{
    state->whoseTurn = 0;//Max player has been reached, loop back around to player 1
}

state->outpostPlayed = 0;
state->phase = 0;
state->numActions = 1;
state->coins = 0;
state->numBuys = 1;
state->playedCardCount = 0;
state->handCount[state->whoseTurn] = 0;

//int k; move to top
//Next player draws hand
for (k = 0; k < 5; k++){
    drawCard(state->whoseTurn, state);//Draw a card
}

//Update money
updateCoins(state->whoseTurn, state , 0);

return 0;
}

int isGameOver(struct gameState *state) {
int i;
int j;
//if stack of Province cards is empty, the game ends
if (state->supplyCount[province] == 0){
      return 1;
    }

//if three supply pile are at 0, the game ends
j = 0;
for (i = 0; i < 25; i++){
      if (state->supplyCount[i] == 0){
   j++;
}
    }
if ( j >= 3){
      return 1;
    }

return 0;
}

int scoreFor (int player, struct gameState *state) {

int i;
int score = 0;
//score from hand
for (i = 0; i < state->handCount[player]; i++){
      if (state->hand[player][i] == curse) { score = score - 1; };
      if (state->hand[player][i] == estate) { score = score + 1; };
      if (state->hand[player][i] == duchy) { score = score + 3; };
      if (state->hand[player][i] == province) { score = score + 6; };
      if (state->hand[player][i] == great_hall) { score = score + 1; };
      if (state->hand[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); };
    }

//score from discard
for (i = 0; i < state->discardCount[player]; i++){
      if (state->discard[player][i] == curse) { score = score - 1; };
      if (state->discard[player][i] == estate) { score = score + 1; };
      if (state->discard[player][i] == duchy) { score = score + 3; };
      if (state->discard[player][i] == province) { score = score + 6; };
      if (state->discard[player][i] == great_hall) { score = score + 1; };
      if (state->discard[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); };
    }

//score from deck
for (i = 0; i < state->discardCount[player]; i++){
      if (state->deck[player][i] == curse) { score = score - 1; };
      if (state->deck[player][i] == estate) { score = score + 1; };
      if (state->deck[player][i] == duchy) { score = score + 3; };
      if (state->deck[player][i] == province) { score = score + 6; };
      if (state->deck[player][i] == great_hall) { score = score + 1; };
      if (state->deck[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); };
    }

return score;
}

int getWinners(int players[MAX_PLAYERS], struct gameState *state) {
int i;
int j;
int highScore;
int currentPlayer;

//get score for each player
for (i = 0; i < MAX_PLAYERS; i++){
      //set unused player scores to -9999
      if (i >= state->numPlayers){
   players[i] = -9999;
}else{
   players[i] = scoreFor (i, state);
}
    }

//find highest score
j = 0;
for (i = 0; i < MAX_PLAYERS; i++){
      if (players[i] > players[j]){
   j = i;
}
    }
highScore = players[j];

//add 1 to players who had less turns
currentPlayer = whoseTurn(state);
for (i = 0; i < MAX_PLAYERS; i++){
      if ( players[i] == highScore&& i > currentPlayer ){
   players[i]++;
}
    }

//find new highest score
j = 0;
for (i = 0; i < MAX_PLAYERS; i++){
      if ( players[i] > players[j] ){
   j = i;
}
    }
highScore = players[j];

//set winners in array to 1 and rest to 0
for (i = 0; i < MAX_PLAYERS; i++){
      if ( players[i] == highScore ){
   players[i] = 1;
}else{
   players[i] = 0;
}
    }

return 0;
}

int drawCard(int player, struct gameState *state)
{ int count;
int deckCounter;
if (state->deckCount[player] <= 0){//Deck is empty
//Step 1 Shuffle the discard pile back into a deck
    int i;
    //Move discard to deck
    for (i = 0; i < state->discardCount[player];i++){
      state->deck[player][i] = state->discard[player][i];
      state->discard[player][i] = -1;
    }

    state->deckCount[player] = state->discardCount[player];
    state->discardCount[player] = 0;//Reset discard

    //Shufffle the deck
    shuffle(player, state);//Shuffle the deck up and make it so that we can draw
   if (DEBUG){//Debug statements
      printf("Deck count now: %d ", state->deckCount[player]);
    }
   state->discardCount[player] = 0;

    //Step 2 Draw Card
    count = state->handCount[player];//Get current player's hand count
   if (DEBUG){//Debug statements
      printf("Current hand count: %d ", count);
    }
   deckCounter = state->deckCount[player];//Create a holder for the deck count

    if (deckCounter == 0)
      return -1;

    state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to hand
    state->deckCount[player]--;
    state->handCount[player]++;//Increment hand count
}else{

    int count = state->handCount[player];//Get current hand count for player
    int deckCounter;
    if (DEBUG){//Debug statements
      printf("Current hand count: %d ", count);
    }

    deckCounter = state->deckCount[player];//Create holder for the deck count
    state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to the hand
    state->deckCount[player]--;
    state->handCount[player]++;//Increment hand count
}

return 0;
}

int getCost(int cardNumber)
{
switch( cardNumber )
    {
    case curse:
      return 0;
    case estate:
      return 2;
    case duchy:
      return 5;
    case province:
      return 8;
    case copper:
      return 0;
    case silver:
      return 3;
    case gold:
      return 6;
    case adventurer:
      return 6;
    case council_room:
      return 5;
    case feast:
      return 4;
    case gardens:
      return 4;
    case mine:
      return 5;
    case remodel:
      return 4;
    case smithy:
      return 4;
    case village:
      return 3;
    case baron:
      return 4;
    case great_hall:
      return 3;
    case minion:
      return 5;
    case steward:
      return 3;
    case tribute:
      return 5;
    case ambassador:
      return 3;
    case cutpurse:
      return 4;
    case embargo:
      return 2;
    case outpost:
      return 5;
    case salvager:
      return 4;
    case sea_hag:
      return 4;
    case treasure_map:
      return 4;
    }
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:
      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! ");

   if (DEBUG){
     printf("Cards Left: %d ", supplyCount(choice1, state));
   }
}else if (state->coins < getCost(choice1)){
   printf("That card is too expensive! ");

   if (DEBUG){
     printf("Coins: %d < %d ", state->coins, getCost(choice1));
   }
}else{

   if (DEBUG){
     printf("Deck Count: %d ", 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 ", 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 ");
       printf("Must gain an estate if there are any ");
     }
     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 ");
   }
}
      }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 ", 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 ", 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 discardCard(int handPos, int currentPlayer, struct gameState *state, int trashFlag)
{
//if card is not trashed, added to Played pile
if (trashFlag < 1){
      //add card to played pile
      state->playedCards[state->playedCardCount] = state->hand[currentPlayer][handPos];
      state->playedCardCount++;
    }
//set played card to -1
state->hand[currentPlayer][handPos] = -1;
//remove card from player's hand
if ( handPos == (state->handCount[currentPlayer] - 1) ){//last card in hand array is played
      //reduce number of cards in hand
      state->handCount[currentPlayer]--;
    }else if ( state->handCount[currentPlayer] == 1 ){//only one card in hand
      //reduce number of cards in hand
      state->handCount[currentPlayer]--;
    }else{
      //replace discarded card with last card in hand
      state->hand[currentPlayer][handPos] = state->hand[currentPlayer][ (state->handCount[currentPlayer] - 1)];
      //set last card to -1
      state->hand[currentPlayer][state->handCount[currentPlayer] - 1] = -1;
      //reduce number of cards in hand
      state->handCount[currentPlayer]--;
    }
return 0;
}

int gainCard(int supplyPos, struct gameState *state, int toFlag, int player)
{
//Note: supplyPos is enum of choosen card
//check if supply pile is empty (0) or card is not used in game (-1)
if ( supplyCount(supplyPos, state) < 1 ){
      return -1;
    }
//added card for [whoseTurn] current player:
// toFlag = 0 : add to discard
// toFlag = 1 : add to deck
// toFlag = 2 : add to hand

if (toFlag == 1){
      state->deck[ player ][ state->deckCount[player] ] = supplyPos;
      state->deckCount[player]++;
    }
else if (toFlag == 2){
      state->hand[ player ][ state->handCount[player] ] = supplyPos;
      state->handCount[player]++;
    }
else{
      state->discard[player][ state->discardCount[player] ] = supplyPos;
      state->discardCount[player]++;
    }

//decrease number in supply pile
state->supplyCount[supplyPos]--;
return 0;
}

int updateCoins(int player, struct gameState *state, int bonus)
{
int i;
//reset coin count
state->coins = 0;

//add coins for each Treasure card in player's hand
for (i = 0; i < state->handCount[player]; i++)    {
      if (state->hand[player][i] == copper){
   state->coins += 1;
}
      else if (state->hand[player][i] == silver){
   state->coins += 2;
}
      else if (state->hand[player][i] == gold){
   state->coins += 3;
}
    }

//add bonus
state->coins += bonus;

return 0;
}//end of dominion.c

#ifndef _DOMINION_H
#define _DOMINION_H

// Code from various sources, baseline from Kristen Bartosz

#define MAX_HAND 500
#define MAX_DECK 500

#define MAX_PLAYERS 4

#define DEBUG 0

/* http://dominion.diehrstraits.com has card texts */
/* http://dominion.isotropic.org has other stuff */

/* hand# means index of a card in current active player's hand */

enum CARD
{curse = 0,
   estate,
   duchy,
   province,

   copper,
   silver,
   gold,

   adventurer,
   /* If no/only 1 treasure found, stop when full deck seen */
   council_room,
   feast, /* choice1 is supply # of card gained) */
   gardens,
   mine, /* choice1 is hand# of money to trash, choice2 is supply# of
     money to put in hand */
   remodel, /* choice1 is hand# of card to remodel, choice2 is supply# */
   smithy,
   village,

   baron, /* choice1: boolean for discard of estate */
   /* Discard is always of first (lowest index) estate */
   great_hall,
   minion, /* choice1: 1 = +2 coin, 2 = redraw */
   steward, /* choice1: 1 = +2 card, 2 = +2 coin, 3 = trash 2 (choice2,3) */
   tribute,

   ambassador, /* choice1 = hand#, choice2 = number to return to supply */
   cutpurse,
   embargo, /* choice1 = supply# */
   outpost,
   salvager, /* choice1 = hand# to trash */
   sea_hag,
   treasure_map
};

struct gameState {
int numPlayers; //number of players
int supplyCount[treasure_map+1]; //this is the amount of a specific type of card given a specific number.
int embargoTokens[treasure_map+1];
int outpostPlayed;
int outpostTurn;
int whoseTurn;
int phase;
int numActions; /* Starts at 1 each turn */
int coins; /* Use as you see fit! */
int numBuys; /* Starts at 1 each turn */
int hand[MAX_PLAYERS][MAX_HAND];
int handCount[MAX_PLAYERS];
int deck[MAX_PLAYERS][MAX_DECK];
int deckCount[MAX_PLAYERS];
int discard[MAX_PLAYERS][MAX_DECK];
int discardCount[MAX_PLAYERS];
int playedCards[MAX_DECK];
int playedCardCount;
};

/* All functions return -1 on failure, and DO NOT CHANGE GAME STATE;
   unless specified for other return, return 0 on success */

struct gameState* newGame();

int* kingdomCards(int k1, int k2, int k3, int k4, int k5, int k6, int k7,
    int k8, int k9, int k10);

int initializeGame(int numPlayers, int kingdomCards[10], int randomSeed,
     struct gameState *state);
/* Responsible for initializing all supplies, and shuffling deck and
   drawing starting hands for all players. Check that 10 cards selected
   are in fact (different) kingdom cards, and that numPlayers is valid.

Cards not in game should initialize supply position to -1 */

int shuffle(int player, struct gameState *state);
/* Assumes all cards are now in deck array (or hand/played): discard is
empty */

int playCard(int handPos, int choice1, int choice2, int choice3,
      struct gameState *state);
/* Play card with index handPos from current player's hand */

int buyCard(int supplyPos, struct gameState *state);
/* Buy card with supply index supplyPos */

int numHandCards(struct gameState *state);
/* How many cards current player has in hand */

int handCard(int handNum, struct gameState *state);
/* enum value of indexed card in player's hand */

int supplyCount(int card, struct gameState *state);
/* How many of given card are left in supply */

int fullDeckCount(int player, int card, struct gameState *state);
/* Here deck = hand + discard + deck */

int whoseTurn(struct gameState *state);

int endTurn(struct gameState *state);
/* Must do phase C and advance to next player; do not advance whose turn
   if game is over */

int isGameOver(struct gameState *state);

int scoreFor(int player, struct gameState *state);
/* Negative here does not mean invalid; scores may be negative,
   -9999 means invalid input */

int getWinners(int players[MAX_PLAYERS], struct gameState *state);
/* Set array position of each player who won (remember ties!) to
   1, others to 0 */

#endif

Explanation / Answer

#include "dominion.h"

#include "dominion_helpers.h"

#include "rngs.h"

#include <stdio.h>

#include <math.h>

#include <stdlib.h>

int compare(const void* a, const void* b) {

if (*(int*)a > *(int*)b)

return 1;

if (*(int*)a < *(int*)b)

return -1;

return 0;

}

struct gameState* newGame() {

struct gameState* g = malloc(sizeof(struct gameState));

return g;

}

int* kingdomCards(int k1, int k2, int k3, int k4, int k5, int k6, int k7,

int k8, int k9, int k10) {

int* k = malloc(10 * sizeof(int));

k[0] = k1;

k[1] = k2;

k[2] = k3;

k[3] = k4;

k[4] = k5;

k[5] = k6;

k[6] = k7;

k[7] = k8;

k[8] = k9;

k[9] = k10;

return k;

}

int initializeGame(int numPlayers, int kingdomCards[10], int randomSeed,

struct gameState *state) {

int i;

int j;

int it;

//set up random number generator

SelectStream(1);

PutSeed((long)randomSeed);

  

//check number of players

if (numPlayers > MAX_PLAYERS || numPlayers < 2)

{

return -1;

}

//set number of players

state->numPlayers = numPlayers;

//check selected kingdom cards are different

for (i = 0; i < 10; i++)

{

for (j = 0; j < 10; j++)

{

if (j != i && kingdomCards[j] == kingdomCards[i])

{

return -1;

}

}

}

//initialize supply

///////////////////////////////

//set number of Curse cards

if (numPlayers == 2)

{

state->supplyCount[curse] = 10;

}

else if (numPlayers == 3)

{

state->supplyCount[curse] = 20;

}

else

{

state->supplyCount[curse] = 30;

}

//set number of Victory cards

if (numPlayers == 2)

{

state->supplyCount[estate] = 8;

state->supplyCount[duchy] = 8;

state->supplyCount[province] = 8;

}

else

{

state->supplyCount[estate] = 12;

state->supplyCount[duchy] = 12;

state->supplyCount[province] = 12;

}

//set number of Treasure cards

state->supplyCount[copper] = 60 - (7 * numPlayers);

state->supplyCount[silver] = 40;

state->supplyCount[gold] = 30;

//set number of Kingdom cards

for (i = adventurer; i <= treasure_map; i++) //loop all cards

{

for (j = 0; j < 10; j++) //loop chosen cards

{

if (kingdomCards[j] == i)

{

//check if card is a 'Victory' Kingdom card

if (kingdomCards[j] == great_hall || kingdomCards[j] == gardens)

{

if (numPlayers == 2){

state->supplyCount[i] = 8;

}

else{ state->supplyCount[i] = 12; }

}

else

{

state->supplyCount[i] = 10;

}

break;

}

else //card is not in the set choosen for the game

{

state->supplyCount[i] = -1;

}

}

}

////////////////////////

//supply intilization complete

//set player decks

for (i = 0; i < numPlayers; i++)

{

state->deckCount[i] = 0;

for (j = 0; j < 3; j++)

{

state->deck[i][j] = estate;

state->deckCount[i]++;

}

for (j = 3; j < 10; j++)

{

state->deck[i][j] = copper;

state->deckCount[i]++;

}

}

//shuffle player decks

for (i = 0; i < numPlayers; i++)

{

if ( shuffle(i, state) < 0 )

{

return -1;

}

}

//draw player hands

for (i = 0; i < numPlayers; i++)

{  

//initialize hand size to zero

state->handCount[i] = 0;

state->discardCount[i] = 0;

//draw 5 cards

// for (j = 0; j < 5; j++)

// {

// drawCard(i, state);

// }

}

  

//set embargo tokens to 0 for all supply piles

for (i = 0; i <= treasure_map; i++)

{

state->embargoTokens[i] = 0;

}

//initialize first player's turn

state->outpostPlayed = 0;

state->phase = 0;

state->numActions = 1;

state->numBuys = 1;

state->playedCardCount = 0;

state->whoseTurn = 0;

state->handCount[state->whoseTurn] = 0;

//int it; move to top

//Moved draw cards to here, only drawing at the start of a turn

for (it = 0; it < 5; it++){

drawCard(state->whoseTurn, state);

}

updateCoins(state->whoseTurn, state, 0);

return 0;

}

int shuffle(int player, struct gameState *state) {

int newDeck[MAX_DECK];

int newDeckPos = 0;

int card;

int i;

if (state->deckCount[player] < 1)

return -1;

qsort ((void*)(state->deck[player]), state->deckCount[player], sizeof(int), compare);

/* SORT CARDS IN DECK TO ENSURE DETERMINISM! */

while (state->deckCount[player] > 0) {

card = floor(Random() * state->deckCount[player]);

newDeck[newDeckPos] = state->deck[player][card];

newDeckPos++;

for (i = card; i < state->deckCount[player]-1; i++) {

state->deck[player][i] = state->deck[player][i+1];

}

state->deckCount[player]--;

}

for (i = 0; i < newDeckPos; i++) {

state->deck[player][i] = newDeck[i];

state->deckCount[player]++;

}

return 0;

}

int playCard(int handPos, int choice1, int choice2, int choice3, struct gameState *state)

{

int card;

int coin_bonus = 0; //tracks coins gain from actions

//check if it is the right phase

if (state->phase != 0)

{

return -1;

}

//check if player has enough actions

if ( state->numActions < 1 )

{

return -1;

}

//get card played

card = handCard(handPos, state);

//check if selected card is an action

if ( card < adventurer || card > treasure_map )

{

return -1;

}

//play card

if ( cardEffect(card, choice1, choice2, choice3, state, handPos, &coin_bonus) < 0 )

{

return -1;

}

//reduce number of actions

state->numActions--;

//update coins (Treasure cards may be added with card draws)

updateCoins(state->whoseTurn, state, coin_bonus);

return 0;

}

int buyCard(int supplyPos, struct gameState *state) {

int who;

if (DEBUG){

printf("Entering buyCard... ");

}

// I don't know what to do about the phase thing.

who = state->whoseTurn;

if (state->numBuys < 1){

if (DEBUG)

printf("You do not have any buys left ");

return -1;

} else if (supplyCount(supplyPos, state) <1){

if (DEBUG)

printf("There are not any of that type of card left ");

return -1;

} else if (state->coins < getCost(supplyPos)){

if (DEBUG)

printf("You do not have enough money to buy that. You have %d coins. ", state->coins);

return -1;

} else {

state->phase=1;

//state->supplyCount[supplyPos]--;

gainCard(supplyPos, state, 0, who); //card goes in discard, this might be wrong.. (2 means goes into hand, 0 goes into discard)

  

state->coins = (state->coins) - (getCost(supplyPos));

state->numBuys--;

if (DEBUG)

printf("You bought card number %d for %d coins. You now have %d buys and %d coins. ", supplyPos, getCost(supplyPos), state->numBuys, state->coins);

}

//state->discard[who][state->discardCount[who]] = supplyPos;

//state->discardCount[who]++;

  

return 0;

}

int numHandCards(struct gameState *state) {

return state->handCount[ whoseTurn(state) ];

}

int handCard(int handPos, struct gameState *state) {

int currentPlayer = whoseTurn(state);

return state->hand[currentPlayer][handPos];

}

int supplyCount(int card, struct gameState *state) {

return state->supplyCount[card];

}

int fullDeckCount(int player, int card, struct gameState *state) {

int i;

int count = 0;

for (i = 0; i < state->deckCount[player]; i++)

{

if (state->deck[player][i] == card) count++;

}

for (i = 0; i < state->handCount[player]; i++)

{

if (state->hand[player][i] == card) count++;

}

for (i = 0; i < state->discardCount[player]; i++)

{

if (state->discard[player][i] == card) count++;

}

return count;

}

int whoseTurn(struct gameState *state) {

return state->whoseTurn;

}

int endTurn(struct gameState *state) {

int k;

int i;

int currentPlayer = whoseTurn(state);

  

//Discard hand

for (i = 0; i < state->handCount[currentPlayer]; i++){

state->discard[currentPlayer][state->discardCount[currentPlayer]++] = state->hand[currentPlayer][i];//Discard

state->hand[currentPlayer][i] = -1;//Set card to -1

}

state->handCount[currentPlayer] = 0;//Reset hand count

  

//Code for determining the player

if (currentPlayer < (state->numPlayers - 1)){

state->whoseTurn = currentPlayer + 1;//Still safe to increment

}

else{

state->whoseTurn = 0;//Max player has been reached, loop back around to player 1

}

state->outpostPlayed = 0;

state->phase = 0;

state->numActions = 1;

state->coins = 0;

state->numBuys = 1;

state->playedCardCount = 0;

state->handCount[state->whoseTurn] = 0;

//int k; move to top

//Next player draws hand

for (k = 0; k < 5; k++){

drawCard(state->whoseTurn, state);//Draw a card

}

//Update money

updateCoins(state->whoseTurn, state , 0);

return 0;

}

int isGameOver(struct gameState *state) {

int i;

int j;

//if stack of Province cards is empty, the game ends

if (state->supplyCount[province] == 0)

{

return 1;

}

//if three supply pile are at 0, the game ends

j = 0;

for (i = 0; i < 25; i++)

{

if (state->supplyCount[i] == 0)

{

j++;

}

}

if ( j >= 3)

{

return 1;

}

return 0;

}

int scoreFor (int player, struct gameState *state) {

int i;

int score = 0;

//score from hand

for (i = 0; i < state->handCount[player]; i++)

{

if (state->hand[player][i] == curse) { score = score - 1; };

if (state->hand[player][i] == estate) { score = score + 1; };

if (state->hand[player][i] == duchy) { score = score + 3; };

if (state->hand[player][i] == province) { score = score + 6; };

if (state->hand[player][i] == great_hall) { score = score + 1; };

if (state->hand[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); };

}

//score from discard

for (i = 0; i < state->discardCount[player]; i++)

{

if (state->discard[player][i] == curse) { score = score - 1; };

if (state->discard[player][i] == estate) { score = score + 1; };

if (state->discard[player][i] == duchy) { score = score + 3; };

if (state->discard[player][i] == province) { score = score + 6; };

if (state->discard[player][i] == great_hall) { score = score + 1; };

if (state->discard[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); };

}

//score from deck

for (i = 0; i < state->discardCount[player]; i++)

{

if (state->deck[player][i] == curse) { score = score - 1; };

if (state->deck[player][i] == estate) { score = score + 1; };

if (state->deck[player][i] == duchy) { score = score + 3; };

if (state->deck[player][i] == province) { score = score + 6; };

if (state->deck[player][i] == great_hall) { score = score + 1; };

if (state->deck[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); };

}

return score;

}

int getWinners(int players[MAX_PLAYERS], struct gameState *state) {

int i;

int j;

int highScore;

int currentPlayer;

//get score for each player

for (i = 0; i < MAX_PLAYERS; i++)

{

//set unused player scores to -9999

if (i >= state->numPlayers)

{

players[i] = -9999;

}

else

{

players[i] = scoreFor (i, state);

}

}

//find highest score

j = 0;

for (i = 0; i < MAX_PLAYERS; i++)

{

if (players[i] > players[j])

{

j = i;

}

}

highScore = players[j];

//add 1 to players who had less turns

currentPlayer = whoseTurn(state);

for (i = 0; i < MAX_PLAYERS; i++)

{

if ( players[i] == highScore && i > currentPlayer )

{

players[i]++;

}

}

//find new highest score

j = 0;

for (i = 0; i < MAX_PLAYERS; i++)

{

if ( players[i] > players[j] )

{

j = i;

}

}

highScore = players[j];

//set winners in array to 1 and rest to 0

for (i = 0; i < MAX_PLAYERS; i++)

{

if ( players[i] == highScore )

{

players[i] = 1;

}

else

{

players[i] = 0;

}

}

return 0;

}

int drawCard(int player, struct gameState *state)

{ int count;

int deckCounter;

if (state->deckCount[player] <= 0){//Deck is empty

  

//Step 1 Shuffle the discard pile back into a deck

int i;

//Move discard to deck

for (i = 0; i < state->discardCount[player];i++){

state->deck[player][i] = state->discard[player][i];

state->discard[player][i] = -1;

}

state->deckCount[player] = state->discardCount[player];

state->discardCount[player] = 0;//Reset discard

//Shufffle the deck

shuffle(player, state);//Shuffle the deck up and make it so that we can draw

if (DEBUG){//Debug statements

printf("Deck count now: %d ", state->deckCount[player]);

}

  

state->discardCount[player] = 0;

//Step 2 Draw Card

count = state->handCount[player];//Get current player's hand count

  

if (DEBUG){//Debug statements

printf("Current hand count: %d ", count);

}

  

deckCounter = state->deckCount[player];//Create a holder for the deck count

if (deckCounter == 0)

return -1;

state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to hand

state->deckCount[player]--;

state->handCount[player]++;//Increment hand count

}

else{

int count = state->handCount[player];//Get current hand count for player

int deckCounter;

if (DEBUG){//Debug statements

printf("Current hand count: %d ", count);

}

deckCounter = state->deckCount[player];//Create holder for the deck count

state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to the hand

state->deckCount[player]--;

state->handCount[player]++;//Increment hand count

}

return 0;

}

int getCost(int cardNumber)

{

switch( cardNumber )

{

case curse:

return 0;

case estate:

return 2;

case duchy:

return 5;

case province:

return 8;

case copper:

return 0;

case silver:

return 3;

case gold:

return 6;

case adventurer:

return 6;

case council_room:

return 5;

case feast:

return 4;

case gardens:

return 4;

case mine:

return 5;

case remodel:

return 4;

case smithy:

return 4;

case village:

return 3;

case baron:

return 4;

case great_hall:

return 3;

case minion:

return 5;

case steward:

return 3;

case tribute:

return 5;

case ambassador:

return 3;

case cutpurse:

return 4;

case embargo:

return 2;

case outpost:

return 5;

case salvager:

return 4;

case sea_hag:

return 4;

case treasure_map:

return 4;

}

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:

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! ");

if (DEBUG){

printf("Cards Left: %d ", supplyCount(choice1, state));

}

}

else if (state->coins < getCost(choice1)){

printf("That card is too expensive! ");

if (DEBUG){

printf("Coins: %d < %d ", state->coins, getCost(choice1));

}

}

else{

if (DEBUG){

printf("Deck Count: %d ", 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 ", 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 ");

printf("Must gain an estate if there are any ");

}

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 ");

}

}

}

  

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 ", 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 ", 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 discardCard(int handPos, int currentPlayer, struct gameState *state, int trashFlag)

{

//if card is not trashed, added to Played pile

if (trashFlag < 1)

{

//add card to played pile

state->playedCards[state->playedCardCount] = state->hand[currentPlayer][handPos];

state->playedCardCount++;

}

//set played card to -1

state->hand[currentPlayer][handPos] = -1;

//remove card from player's hand

if ( handPos == (state->handCount[currentPlayer] - 1) ) //last card in hand array is played

{

//reduce number of cards in hand

state->handCount[currentPlayer]--;

}

else if ( state->handCount[currentPlayer] == 1 ) //only one card in hand

{

//reduce number of cards in hand

state->handCount[currentPlayer]--;

}

else

{

//replace discarded card with last card in hand

state->hand[currentPlayer][handPos] = state->hand[currentPlayer][ (state->handCount[currentPlayer] - 1)];

//set last card to -1

state->hand[currentPlayer][state->handCount[currentPlayer] - 1] = -1;

//reduce number of cards in hand

state->handCount[currentPlayer]--;

}

return 0;

}

int gainCard(int supplyPos, struct gameState *state, int toFlag, int player)

{

//Note: supplyPos is enum of choosen card

//check if supply pile is empty (0) or card is not used in game (-1)

if ( supplyCount(supplyPos, state) < 1 )

{

return -1;

}

//added card for [whoseTurn] current player:

// toFlag = 0 : add to discard

// toFlag = 1 : add to deck

// toFlag = 2 : add to hand

if (toFlag == 1)

{

state->deck[ player ][ state->deckCount[player] ] = supplyPos;

state->deckCount[player]++;

}

else if (toFlag == 2)

{

state->hand[ player ][ state->handCount[player] ] = supplyPos;

state->handCount[player]++;

}

else

{

state->discard[player][ state->discardCount[player] ] = supplyPos;

state->discardCount[player]++;

}

//decrease number in supply pile

state->supplyCount[supplyPos]--;

return 0;

}

int updateCoins(int player, struct gameState *state, int bonus)

{

int i;

//reset coin count

state->coins = 0;

//add coins for each Treasure card in player's hand

for (i = 0; i < state->handCount[player]; i++)

{

if (state->hand[player][i] == copper)

{

state->coins += 1;

}

else if (state->hand[player][i] == silver)

{

state->coins += 2;

}

else if (state->hand[player][i] == gold)

{

state->coins += 3;

}

}

//add bonus

state->coins += bonus;

return 0;

}

//end of dominion.c