#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...\n"); } // 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\n"); return -1; } else if (supplyCount(supplyPos, state) <1) { if (DEBUG) printf("There are not any of that type of card left\n"); return -1; } else if (state->coins < getCost(supplyPos)) { if (DEBUG) printf("You do not have enough money to buy that. You have %d coins.\n", 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.\n", 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\n", 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\n", 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\n", 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; } //NOTE: THIS VERSION HAS ADDED BUGS IN THE 4 FUNCTIONS BELOW int playAdventurer(int drawntreasure, struct gameState *state, int currentPlayer, int temphand[MAX_HAND], int z) { //Reveal cards from your deck until you reveal 2 Treasure cards. //Put those Treasure cards into your hand and discard the other revealed cards. int cardDrawn; 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; } int playSmithy(struct gameState *state, int handPos, int currentPlayer) { //+3 Cards int i; for (i = 0; i < 5; i++) { drawCard(currentPlayer, state); } //discard card from hand discardCard(handPos, currentPlayer, state, 0); return 0; } int playVillage(int currentPlayer, struct gameState *state, int handPos) { //+1 Card and +2 Actions //+1 Card drawCard(currentPlayer, state); //+2 Actions state->numActions = state->numActions + 2; return 0; } int playMine(struct gameState *state, int currentPlayer, int choice1, int choice2, int handPos) { //You may trash a Treasure from your hand. Gain a Treasure to your hand costing //up to 3 coins more than it. //Usage: play 5 0 3 //Where 5 is the mine card in hand, 0 is copper card in had, and 3 is silver card //in the supply int j = state->hand[currentPlayer][choice1]; //store card we will trash int i; 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]) + 6) > 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; } int playEmbargo(struct gameState *state, int choice1, int handPos, int currentPlayer) { //+2 Coins. Trash this card. Put an Embargo token on top of a Supply pile. // When a player buys a card, he gains a Curse card per Embargo token on that pile. //NOTE: The program has a bug already where Player0 starts with a different number // of VP than Player1. Regardless, I didn't mess with the VP counter. //+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; } //NOT USED: DON'T CHECK THESE FOR BUGS int playGreat_hall(int currentPlayer, struct gameState *state, int handPos) { //+1 Card drawCard(currentPlayer, state); //+1 Actions state->numActions++; //discard card from hand discardCard(handPos, currentPlayer, state, 0); return 0; } //NOT USED: DON'T CHECK THESE FOR BUGS int playSteward(int choice1, int choice2, int choice3, int currentPlayer, struct gameState *state, int handPos) { 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; } 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 playAdventurer(drawntreasure, state, currentPlayer, temphand, z); 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: return playMine(state, currentPlayer, choice1, choice2, handPos); 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 return playSmithy(state, handPos, currentPlayer); case village: return playVillage(currentPlayer, state, handPos); case baron: state->numBuys++;//Increase buys by 1! if (choice1 > 0){//Boolean true or going to discard an estate int p = 0;//Iterator for hand! int card_not_discarded = 1;//Flag for discard set! while(card_not_discarded){ if (state->hand[currentPlayer][p] == estate){//Found an estate card! state->coins += 4;//Add 4 coins to the amount of coins state->discard[currentPlayer][state->discardCount[currentPlayer]] = state->hand[currentPlayer][p]; state->discardCount[currentPlayer]++; for (;p < state->handCount[currentPlayer]; p++){ state->hand[currentPlayer][p] = state->hand[currentPlayer][p+1]; } state->hand[currentPlayer][state->handCount[currentPlayer]] = -1; state->handCount[currentPlayer]--; card_not_discarded = 0;//Exit the loop } else if (p > state->handCount[currentPlayer]){ if(DEBUG) { printf("No estate cards in your hand, invalid choice\n"); printf("Must gain an estate if there are any\n"); } if (supplyCount(estate, state) > 0){ gainCard(estate, state, 0, currentPlayer); state->supplyCount[estate]--;//Decrement estates if (supplyCount(estate, state) == 0){ isGameOver(state); } } card_not_discarded = 0;//Exit the loop } else{ p++;//Next card } } } else{ if (supplyCount(estate, state) > 0){ gainCard(estate, state, 0, currentPlayer);//Gain an estate state->supplyCount[estate]--;//Decrement Estates if (supplyCount(estate, state) == 0){ isGameOver(state); } } } return 0; case great_hall: return playGreat_hall(currentPlayer, state, handPos); 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: return playSteward(choice1, choice2, choice3, currentPlayer, state, handPos); 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: return playEmbargo(state, choice1, handPos, currentPlayer); 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