diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/Makefile b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/Makefile new file mode 100644 index 0000000..0ff7cbd --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/Makefile @@ -0,0 +1,139 @@ +CFLAGS = -Wall -fpic -coverage -lm -std=c99 -ftest-coverage -fprofile-arcs + +rngs.o: rngs.h rngs.c + gcc -c rngs.c -g $(CFLAGS) + +dominion.o: dominion.h dominion.c rngs.o + gcc -c dominion.c -g $(CFLAGS) + +playdom: dominion.o playdom.c + gcc -o playdom playdom.c -g dominion.o rngs.o $(CFLAGS) + +testDrawCard: testDrawCard.c dominion.o rngs.o + gcc -o testDrawCard -g testDrawCard.c dominion.o rngs.o $(CFLAGS) + +badTestDrawCard: badTestDrawCard.c dominion.o rngs.o + gcc -o badTestDrawCard -g badTestDrawCard.c dominion.o rngs.o $(CFLAGS) + +testBuyCard: testDrawCard.c dominion.o rngs.o + gcc -o testDrawCard -g testDrawCard.c dominion.o rngs.o $(CFLAGS) + +testAll: dominion.o testSuite.c + gcc -o testSuite testSuite.c -g dominion.o rngs.o $(CFLAGS) + +interface.o: interface.h interface.c + gcc -c interface.c -g $(CFLAGS) + +runtests: testDrawCard + ./testDrawCard &> unittestresult.out + gcov dominion.c >> unittestresult.out + cat dominion.c.gcov >> unittestresult.out + + +player: player.c interface.o + gcc -o player player.c -g dominion.o rngs.o interface.o $(CFLAGS) + +all: playdom player testDrawCard testBuyCard badTestDrawCard + +unittestresults.out: + echo "Compiling and running all tests....." > unittestresults.out + + gcc -o unittest1 unittest1.c dominion.c rngs.c -g $(CFLAGS) + echo "Running Unittest1...." >> unittestresults.out + ./unittest1 >> unittestresults.out + gcov dominion.c >> unittestresults.out + cat dominion.c.gcov >> unittestresults.out + cat dominion.c.gcov >> unittest1.gcov + + echo "######################################" >> unittestresults.out + echo "######################################" >> unittestresults.out + + gcc -o unittest2 unittest2.c dominion.c rngs.c -g $(CFLAGS) + echo "Running Unittest2...." >> unittestresults.out + ./unittest2 >> unittestresults.out + gcov dominion.c >> unittestresults.out + cat dominion.c.gcov >> unittestresults.out + cat dominion.c.gcov >> unittest2.gcov + + echo "######################################" >> unittestresults.out + echo "######################################" >> unittestresults.out + + gcc -o unittest3 unittest3.c dominion.c rngs.c -g $(CFLAGS) + echo "Running Unittest3...." >> unittestresults.out + ./unittest3 >> unittestresults.out + gcov dominion.c >> unittestresults.out + cat dominion.c.gcov >> unittestresults.out + cat dominion.c.gcov >> unittest3.gcov + + echo "######################################" >> unittestresults.out + echo "######################################" >> unittestresults.out + + gcc -o unittest4 unittest4.c dominion.c rngs.c -g $(CFLAGS) + echo "Running Unittest4...." >> unittestresults.out + ./unittest4 >> unittestresults.out + gcov dominion.c >> unittestresults.out + cat dominion.c.gcov >> unittestresults.out + cat dominion.c.gcov >> unittest4.gcov + + echo "######################################" >> unittestresults.out + echo "######################################" >> unittestresults.out + + gcc -o cardtest1 cardtest1.c dominion.c rngs.c -g $(CFLAGS) + echo "Running Cardtest1...." >> unittestresults.out + ./cardtest1 >> unittestresults.out + gcov dominion.c >> unittestresults.out + cat dominion.c.gcov >> unittestresults.out + cat dominion.c.gcov >> cardtest1.gcov + + echo "######################################" >> unittestresults.out + echo "######################################" >> unittestresults.out + + gcc -o cardtest2 cardtest2.c dominion.c rngs.c -g $(CFLAGS) + echo "Running Cardtest2...." >> unittestresults.out + ./cardtest2 >> unittestresults.out + gcov dominion.c >> unittestresults.out + cat dominion.c.gcov >> unittestresults.out + cat dominion.c.gcov >> cardtest2.gcov + + echo "######################################" >> unittestresults.out + echo "######################################" >> unittestresults.out + + gcc -o cardtest3 cardtest3.c dominion.c rngs.c -g $(CFLAGS) + echo "Running Cardtest3...." >> unittestresults.out + ./cardtest3 >> unittestresults.out + gcov dominion.c >> unittestresults.out + cat dominion.c.gcov >> unittestresults.out + cat dominion.c.gcov >> cardtest3.gcov + + echo "######################################" >> unittestresults.out + echo "######################################" >> unittestresults.out + + gcc -o cardtest4 cardtest4.c dominion.c rngs.c -g $(CFLAGS) + echo "Running Cardtest4...." >> unittestresults.out + ./cardtest4 >> unittestresults.out + gcov dominion.c >> unittestresults.out + cat dominion.c.gcov >> unittestresults.out + cat dominion.c.gcov >> cardtest4.gcov + +randomtests: + gcc -o randomtestadventurer randomtestadventurer.c dominion.c rngs.c -g $(CFLAGS) + ./randomtestadventurer 29378 > randomtestadventurer.out + gcov dominion.c >> randomtestadventurer.out + cat dominion.c.gcov >> randomtestadventurer.out + + gcc -o randomtestcard1 randomtestcard1.c dominion.c rngs.c -g $(CFLAGS) + ./randomtestcard1 29378 > randomtestcard1.out + gcov dominion.c >> randomtestcard1.out + cat dominion.c.gcov >> randomtestcard1.out + + gcc -o randomtestcard2 randomtestcard2.c dominion.c rngs.c -g $(CFLAGS) + ./randomtestcard2 29378 > randomtestcard2.out + gcov dominion.c >> randomtestcard2.out + cat dominion.c.gcov >> randomtestcard2.out + +buggytests: + gcc -o cardtest2 cardtest2.c dominion.c rngs.c -g $(CFLAGS) + +clean: + rm -f *.o playdom.exe playdom test.exe test player player.exe testInit testInit.exe *.gcov *.gcda *.gcno *.so *.out + rm -f randomtestadventurer randomtestcard1 randomtestcard2 diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/badTestDrawCard.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/badTestDrawCard.c new file mode 100644 index 0000000..f1bb35c --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/badTestDrawCard.c @@ -0,0 +1,44 @@ +#include "dominion.h" +#include "dominion_helpers.h" +#include +#include +#include +#include "rngs.h" + +#define DEBUG 0 +#define NOISY_TEST 1 + +int checkDrawCard(int p, struct gameState *post) { + int r; + + r = drawCard (p, post); +} + +int main () { + + int i, n, r, p, deckCount, discardCount, handCount; + + int k[10] = {adventurer, council_room, feast, gardens, mine, + remodel, smithy, village, baron, great_hall}; + + struct gameState G; + + printf ("Testing drawCard.\n"); + + printf ("RANDOM TESTS.\n"); + + SelectStream(2); + PutSeed(3); + + for (n = 0; n < 2000; n++) { + for (i = 0; i < sizeof(struct gameState); i++) { + ((char*)&G)[i] = floor(Random() * 256); + } + p = floor(Random() * 1000); + checkDrawCard(p, &G); + } + + printf ("ALL TESTS OK\n"); + + exit(0); +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/betterTestDrawCard.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/betterTestDrawCard.c new file mode 100644 index 0000000..2b64716 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/betterTestDrawCard.c @@ -0,0 +1,70 @@ +#include "dominion.h" +#include "dominion_helpers.h" +#include +#include +#include +#include "rngs.h" + +#define DEBUG 0 +#define NOISY_TEST 1 + +int checkDrawCard(int p, struct gameState *post) { + int r; + + r = drawCard (p, post); + + assert (r == 0); +} + +int main () { + + int i, n, r, p, deckCount, discardCount, handCount; + + int k[10] = {adventurer, council_room, feast, gardens, mine, + remodel, smithy, village, baron, great_hall}; + + struct gameState G; + + printf ("Testing drawCard.\n"); + + printf ("RANDOM TESTS.\n"); + + SelectStream(2); + PutSeed(3); + + for (n = 0; n < 2000; n++) { + for (i = 0; i < sizeof(struct gameState); i++) { + ((char*)&G)[i] = floor(Random() * 256); + } + p = floor(Random() * 2); + G.deckCount[p] = floor(Random() * MAX_DECK); + G.discardCount[p] = floor(Random() * MAX_DECK); + G.handCount[p] = floor(Random() * MAX_HAND); + checkDrawCard(p, &G); + } + + printf ("ALL TESTS OK\n"); + + exit(0); + + printf ("SIMPLE FIXED TESTS.\n"); + for (p = 0; p < 2; p++) { + for (deckCount = 0; deckCount < 5; deckCount++) { + for (discardCount = 0; discardCount < 5; discardCount++) { + for (handCount = 0; handCount < 5; handCount++) { + memset(&G, 23, sizeof(struct gameState)); + r = initializeGame(2, k, 1, &G); + G.deckCount[p] = deckCount; + memset(G.deck[p], 0, sizeof(int) * deckCount); + G.discardCount[p] = discardCount; + memset(G.discard[p], 0, sizeof(int) * discardCount); + G.handCount[p] = handCount; + memset(G.hand[p], 0, sizeof(int) * handCount); + checkDrawCard(p, &G); + } + } + } + } + + return 0; +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest1.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest1.c new file mode 100644 index 0000000..ca5e7e7 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest1.c @@ -0,0 +1,74 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: unittest1.c + * Author: corwinperren + * + * Created on February 1, 2017, 9:02 PM + */ + +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression); + +int main(int argc, char** argv) { + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + + + unsigned int arbitrary_hand_count_max = MAX_HAND - 1; + + for(int i = 0 ; i < 4 ; i++){ + initializeGame(4, k, 65432, &G); + G.deckCount[i] = MAX_DECK; + G.whoseTurn = i; + + for(int j = 0 ; j < arbitrary_hand_count_max ; j++){ + int hand_count = G.handCount[i]; + int num_actions = G.numActions; + + playGreat_Hall(&G, j); + testing_assert(G.handCount[i] == hand_count); + testing_assert(G.numActions == num_actions + 1); + + for(int j = 0 ; j < G.handCount[i] ; j++){ + testing_assert((G.hand[i][j] >= curse) && (G.hand[i][j] <= treasure_map)); + } + } + + } + +// printf("Hand: %d\n", G.handCount[0]); +// drawCard(0, &G); +// printf("Hand: %d\n", G.handCount[0]); +// G.numActions++; +// discardCard(0, 0, &G, 0); +// printf("Hand: %d\n\n", G.handCount[0]); +// +// printf("Hand: %d\n", G.handCount[0]); +// playGreat_Hall(&G, 0); +// printf("Hand: %d\n\n", G.handCount[0]); + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression) { + if (expression) { + printf("TEST SUCCEEDED!\n"); + return 1; + } else { + printf("TEST FAILED!\n"); + return 0; + } +} + diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest2.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest2.c new file mode 100644 index 0000000..c9976af --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest2.c @@ -0,0 +1,85 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: unittest1.c + * Author: corwinperren + * + * Created on February 1, 2017, 9:02 PM + */ + +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression, int should_print); + +long sucesses = 0; +long failures = 0; + +int main(int argc, char** argv) { + struct gameState G, G_copy; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + + unsigned int arbitrary_hand_count_max = MAX_HAND - 3; + + for(int l = 0 ; l < 4 ; l++){ + for(int i = 1 ; i < arbitrary_hand_count_max ; i++){ + initializeGame(4, k, 65432, &G); + G.handCount[0] = arbitrary_hand_count_max; + G.whoseTurn = l; + + G_copy = G; + + drawCard(0, &G_copy); + drawCard(0, &G_copy); + drawCard(0, &G_copy); + discardCard(i, l, &G_copy, 0); + + playSmithy(&G, i); + + testing_assert(G.handCount[l] == G_copy.handCount[l], 0); + + for(int j = 0 ; j < arbitrary_hand_count_max ; j++){ + testing_assert((G.hand[l][j] >= curse) && (G.hand[l][j] <= treasure_map), 0); + testing_assert((G_copy.hand[l][j] >= curse) && (G_copy.hand[l][j] <= treasure_map), 0); + } + + } + } + + printf("Run complete!\n"); + printf("SUCCESSES: %ld\n", sucesses); + + if(failures > 0){ + printf("Some tests failed!!!\n"); + printf("FAILURES: %ld\n", failures); + } + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression, int should_print) { + if (expression) { + if(should_print){ + printf("TEST SUCCEEDED!\n"); + } + sucesses++; + return 1; + } else { + if(should_print){ + printf("TEST FAILED!\n"); + } + failures++; + return 0; + } +} + + diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest3.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest3.c new file mode 100644 index 0000000..20c554d --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest3.c @@ -0,0 +1,77 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: unittest1.c + * Author: corwinperren + * + * Created on February 1, 2017, 9:02 PM + */ + +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression); + +int main(int argc, char** argv) { + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + unsigned int arbitrary_hand_count_max = MAX_HAND - 2; + + for(int l = 0 ; l < 4 ; l++){ + for(int i = 1 ; i < arbitrary_hand_count_max ; i++){ + initializeGame(4, k, 65432, &G); + G.handCount[l] = arbitrary_hand_count_max; + G.whoseTurn = l; + + playAdventurer(&G); + + testing_assert(G.handCount[l] == arbitrary_hand_count_max + 2); + testing_assert((G.hand[l][G.handCount[l] - 1] >= copper) && (G.hand[l][G.handCount[l] - 1] <= gold)); + testing_assert((G.hand[l][G.handCount[l] - 2] >= copper) && (G.hand[l][G.handCount[l] - 2] <= gold)); + + initializeGame(4, k, 65432, &G); + G.handCount[l] = arbitrary_hand_count_max; + G.whoseTurn = l; + G.deckCount[l] = 0; + + for(int m = 0 ; m < MAX_DECK ; m += 3){ + G.discard[l][m] = copper; + G.discard[l][m + 1] = silver; + G.discard[l][m + 2] = gold; + G.discardCount[l] += 3; + } + + + playAdventurer(&G); + + testing_assert(G.handCount[l] == arbitrary_hand_count_max + 2); + testing_assert((G.hand[l][G.handCount[l] - 1] >= copper) && (G.hand[l][G.handCount[l] - 1] <= gold)); + testing_assert((G.hand[l][G.handCount[l] - 2] >= copper) && (G.hand[l][G.handCount[l] - 2] <= gold)); + + } + } + + + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression) { + if (expression) { + printf("TEST SUCCEEDED!\n"); + return 1; + } else { + printf("TEST FAILED!\n"); + return 0; + } +} + diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest4.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest4.c new file mode 100644 index 0000000..d259189 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/cardtest4.c @@ -0,0 +1,57 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: unittest1.c + * Author: corwinperren + * + * Created on February 1, 2017, 9:02 PM + */ + +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression); + +int main(int argc, char** argv) { + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + + unsigned int arbitrary_hand_count_max = MAX_HAND - 3; + + for(int l = 0 ; l < 4 ; l++){ + for(int i = 1 ; i < arbitrary_hand_count_max ; i++){ + initializeGame(4, k, 65432, &G); + G.handCount[0] = arbitrary_hand_count_max; + G.whoseTurn = l; + + int outpost_before = G.outpostPlayed; + int handcount_before = G.handCount[l]; + playOutpost(&G, i); + + testing_assert(G.outpostPlayed == outpost_before + 1); + testing_assert(G.handCount[l] == handcount_before - 1); + } + } + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression) { + if (expression) { + printf("TEST SUCCEEDED!\n"); + return 1; + } else { + printf("TEST FAILED!\n"); + return 0; + } +} + diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/dominion.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/dominion.c new file mode 100644 index 0000000..0da0270 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/dominion.c @@ -0,0 +1,1381 @@ +#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; +} + +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(state); + + case council_room: + return playCouncil_Room(state, handPos); + + case feast: + return playFeast(state, choice1); + + case gardens: + return -1; + + case mine: + j = state->hand[currentPlayer][choice1]; //store card we will trash + + if (state->hand[currentPlayer][choice1] < copper || state->hand[currentPlayer][choice1] > gold) + { + return -1; + } + + if (choice2 > treasure_map || choice2 < curse) + { + return -1; + } + + if ( (getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2) ) + { + return -1; + } + + gainCard(choice2, state, 2, currentPlayer); + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + + //discard trashed card + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == j) + { + discardCard(i, currentPlayer, state, 0); + break; + } + } + + return 0; + + case remodel: + j = state->hand[currentPlayer][choice1]; //store card we will trash + + if ( (getCost(state->hand[currentPlayer][choice1]) + 2) > getCost(choice2) ) + { + return -1; + } + + gainCard(choice2, state, 0, currentPlayer); + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + + //discard trashed card + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == j) + { + discardCard(i, currentPlayer, state, 0); + break; + } + } + + + return 0; + + case smithy: + return playSmithy(state, handPos); + + case village: + return playVillage(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: + playGreat_Hall(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: + if (choice1 == 1) + { + //+2 cards + drawCard(currentPlayer, state); + drawCard(currentPlayer, state); + } + else if (choice1 == 2) + { + //+2 coins + state->coins = state->coins + 2; + } + else + { + //trash 2 cards in hand + discardCard(choice2, currentPlayer, state, 1); + discardCard(choice3, currentPlayer, state, 1); + } + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case tribute: + if ((state->discardCount[nextPlayer] + state->deckCount[nextPlayer]) <= 1){ + if (state->deckCount[nextPlayer] > 0){ + tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deckCount[nextPlayer]--; + } + else if (state->discardCount[nextPlayer] > 0){ + tributeRevealedCards[0] = state->discard[nextPlayer][state->discardCount[nextPlayer]-1]; + state->discardCount[nextPlayer]--; + } + else{ + //No Card to Reveal + if (DEBUG){ + printf("No cards to reveal\n"); + } + } + } + + else{ + if (state->deckCount[nextPlayer] == 0){ + for (i = 0; i < state->discardCount[nextPlayer]; i++){ + state->deck[nextPlayer][i] = state->discard[nextPlayer][i];//Move to deck + state->deckCount[nextPlayer]++; + state->discard[nextPlayer][i] = -1; + state->discardCount[nextPlayer]--; + } + + shuffle(nextPlayer,state);//Shuffle the deck + } + tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; + state->deckCount[nextPlayer]--; + tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; + state->deckCount[nextPlayer]--; + } + + if (tributeRevealedCards[0] == tributeRevealedCards[1]){//If we have a duplicate card, just drop one + state->playedCards[state->playedCardCount] = tributeRevealedCards[1]; + state->playedCardCount++; + tributeRevealedCards[1] = -1; + } + + for (i = 0; i <= 2; i ++){ + if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold){//Treasure cards + state->coins += 2; + } + + else if (tributeRevealedCards[i] == estate || tributeRevealedCards[i] == duchy || tributeRevealedCards[i] == province || tributeRevealedCards[i] == gardens || tributeRevealedCards[i] == great_hall){//Victory Card Found + drawCard(currentPlayer, state); + drawCard(currentPlayer, state); + } + else{//Action Card + state->numActions = state->numActions + 2; + } + } + + return 0; + + case ambassador: + j = 0; //used to check if player has enough cards to discard + + if (choice2 > 2 || choice2 < 0) + { + return -1; + } + + if (choice1 == handPos) + { + return -1; + } + + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (i != handPos && i == state->hand[currentPlayer][choice1] && i != choice1) + { + j++; + } + } + if (j < choice2) + { + return -1; + } + + if (DEBUG) + printf("Player %d reveals card number: %d\n", currentPlayer, state->hand[currentPlayer][choice1]); + + //increase supply count for choosen card by amount being discarded + state->supplyCount[state->hand[currentPlayer][choice1]] += choice2; + + //each other player gains a copy of revealed card + for (i = 0; i < state->numPlayers; i++) + { + if (i != currentPlayer) + { + gainCard(state->hand[currentPlayer][choice1], state, 0, i); + } + } + + //discard played card from hand + discardCard(handPos, currentPlayer, state, 0); + + //trash copies of cards returned to supply + for (j = 0; j < choice2; j++) + { + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == state->hand[currentPlayer][choice1]) + { + discardCard(i, currentPlayer, state, 1); + break; + } + } + } + + return 0; + + case cutpurse: + + updateCoins(currentPlayer, state, 2); + for (i = 0; i < state->numPlayers; i++) + { + if (i != currentPlayer) + { + for (j = 0; j < state->handCount[i]; j++) + { + if (state->hand[i][j] == copper) + { + discardCard(j, i, state, 0); + break; + } + if (j == state->handCount[i]) + { + for (k = 0; k < state->handCount[i]; k++) + { + if (DEBUG) + printf("Player %d reveals card number %d\n", i, state->hand[i][k]); + } + break; + } + } + + } + + } + + //discard played card from hand + discardCard(handPos, currentPlayer, state, 0); + + return 0; + + + case embargo: + //+2 Coins + state->coins = state->coins + 2; + + //see if selected pile is in play + if ( state->supplyCount[choice1] == -1 ) + { + return -1; + } + + //add embargo token to selected supply pile + state->embargoTokens[choice1]++; + + //trash card + discardCard(handPos, currentPlayer, state, 1); + return 0; + + case outpost: + playOutpost(state, handPos); + + 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; +} + +int playAdventurer(struct gameState *state){ + int currentPlayer = whoseTurn(state); + int drawntreasure=0; + int cardDrawn; + int temphand[MAX_HAND]; + int z = 0; + + 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) + 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 = whoseTurn(state); + int i; + + //+3 Cards + for (i = 0; i < 4; i++) + { + drawCard(currentPlayer, state); + } + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + return 0; +} + +int playVillage(struct gameState *state, int handPos){ + int currentPlayer = whoseTurn(state); + + //+1 Card + drawCard(currentPlayer, state); + + //+2 Actions + state->numActions = state->numActions + 2; + + //discard played card from hand + discardCard(handPos, currentPlayer-1, state, 0); + return 0; +} + +int playFeast(struct gameState *state, int choice1){ + int currentPlayer = whoseTurn(state); + int i; + int x; + int temphand[MAX_HAND]; + int j = state->handCount[currentPlayer]; + + //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 = j; i <= state->handCount[currentPlayer]; i++){ + state->hand[currentPlayer][i] = temphand[i]; + temphand[i] = -1; + } + //Reset Hand + + return 0; +} + +int playCouncil_Room(struct gameState *state, int handPos){ + int currentPlayer = whoseTurn(state); + int i; + //+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; +} + +int playGreat_Hall(struct gameState *state, int handPos){ + int currentPlayer = whoseTurn(state); + //+1 Card + drawCard(currentPlayer, state); + + //+1 Actions + state->numActions++; + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + return 0; +} + +int playOutpost(struct gameState *state, int handPos){ + int currentPlayer = whoseTurn(state); + //set outpost flag + state->outpostPlayed++; + + //discard card + discardCard(handPos, currentPlayer, state, 0); + return 0; +} + +//end of dominion.c + diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/dominion.h b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/dominion.h new file mode 100644 index 0000000..5c4823e --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/dominion.h @@ -0,0 +1,142 @@ +#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 + +//Testing commit + +/* 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 */ + +int playAdventurer(struct gameState *state); +int playSmithy(struct gameState *state, int handPos); +int playVillage(struct gameState *state, int handPos); +int playFeast(struct gameState *state, int choice1); +int playCouncil_Room(struct gameState *state, int handPos); +int playGreat_Hall(struct gameState *state, int handPos); +int playOutpost(struct gameState *state, int handPos); + + +#endif diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/dominion_helpers.h b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/dominion_helpers.h new file mode 100644 index 0000000..5a94351 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/dominion_helpers.h @@ -0,0 +1,15 @@ +#ifndef _DOMINION_HELPERS_H +#define _DOMINION_HELPERS_H + +#include "dominion.h" + +int drawCard(int player, struct gameState *state); +int updateCoins(int player, struct gameState *state, int bonus); +int discardCard(int handPos, int currentPlayer, struct gameState *state, + int trashFlag); +int gainCard(int supplyPos, struct gameState *state, int toFlag, int player); +int getCost(int cardNumber); +int cardEffect(int card, int choice1, int choice2, int choice3, + struct gameState *state, int handPos, int *bonus); + +#endif diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/interface.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/interface.c new file mode 100644 index 0000000..09344d7 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/interface.c @@ -0,0 +1,363 @@ +/* Interactive Dominion Interface + +Sam Heinith CS362 +1/26/2010 +*/ + +#include +#include +#include +#include +#include "rngs.h" +#include "interface.h" +#include "dominion.h" + + +void cardNumToName(int card, char *name){ + switch(card){ + case curse: strcpy(name,"Curse"); + break; + case estate: strcpy(name,"Estate"); + break; + case duchy: strcpy(name,"Duchy"); + break; + case province: strcpy(name,"Province"); + break; + case copper: strcpy(name,"Copper"); + break; + case silver: strcpy(name,"Silver"); + break; + case gold: strcpy(name,"Gold"); + break; + case adventurer: strcpy(name,"Adventurer"); + break; + case council_room: strcpy(name,"Council Room"); + break; + case feast: strcpy(name,"Feast"); + break; + case gardens: strcpy(name,"Gardens"); + break; + case mine: strcpy(name,"Mine"); + break; + case remodel: strcpy(name,"Remodel"); + break; + case smithy: strcpy(name,"Smithy"); + break; + case village: strcpy(name,"Village"); + break; + case baron: strcpy(name,"Baron"); + break; + case great_hall: strcpy(name,"Great Hall"); + break; + case minion: strcpy(name,"Minion"); + break; + case steward: strcpy(name,"Steward"); + break; + case tribute: strcpy(name,"Tribute"); + break; + case ambassador: strcpy(name,"Ambassador"); + break; + case cutpurse: strcpy(name,"Cutpurse"); + break; + case embargo: strcpy(name,"Embargo"); + break; + case outpost: strcpy(name,"Outpost"); + break; + case salvager: strcpy(name,"Salvager"); + break; + case sea_hag: strcpy(name,"Sea Hag"); + break; + case treasure_map: strcpy(name,"Treasure Map"); + break; + + default: strcpy(name,"?"); + } + +} + + + +int getCardCost(int card) { + int cost; + switch(card) { + case curse: cost = CURSE_COST; + break; + case estate: cost = ESTATE_COST; + break; + case duchy: cost = DUCHY_COST; + break; + case province: cost = PROVINCE_COST; + break; + case copper: cost = COPPER_COST; + break; + case silver: cost = SILVER_COST; + break; + case gold: cost = GOLD_COST; + break; + case adventurer: cost = ADVENTURER_COST; + break; + case council_room: cost = COUNCIL_ROOM_COST; + break; + case feast: cost = FEAST_COST; + break; + case gardens: cost = GARDEN_COST; + break; + case mine: cost = MINE_COST; + break; + case remodel: cost = REMODEL_COST; + break; + case smithy: cost = SMITHY_COST; + break; + case village: cost = VILLAGE_COST; + break; + case baron: cost = BARON_COST; + break; + case great_hall: cost = GREAT_HALL_COST; + break; + case minion: cost = MINION_COST; + break; + case steward: cost = STEWARD_COST; + break; + case tribute: cost = TRIBUTE_COST; + break; + case ambassador: cost = AMBASSADOR_COST; + break; + case cutpurse: cost = CUTPURSE_COST; + break; + case embargo: cost = EMBARGO_COST; + break; + case outpost: cost = OUTPOST_COST; + break; + case salvager: cost = SALVAGER_COST; + break; + case sea_hag: cost = SEA_HAG_COST; + break; + case treasure_map: cost = TREASURE_MAP_COST; + break; + default: cost = ONETHOUSAND; + } + return cost; +} + + + + + + +void printHand(int player, struct gameState *game) { + int handCount = game->handCount[player]; + int handIndex; + printf("Player %d's hand:\n", player); + if(handCount > 0) printf("# Card\n"); + for(handIndex = 0; handIndex < handCount; handIndex++) { + int card = game->hand[player][handIndex]; + char name[MAX_STRING_LENGTH]; + cardNumToName(card, name); + printf("%-2d %-13s\n", handIndex, name); + } + printf("\n"); +} + + + +void printDeck(int player, struct gameState *game) { + int deckCount = game->deckCount[player]; + int deckIndex; + printf("Player %d's deck: \n", player); + if(deckCount > 0) printf("# Card\n"); + for(deckIndex = 0; deckIndex < deckCount; deckIndex++) { + int card = game->deck[player][deckIndex]; + char name[MAX_STRING_LENGTH]; + cardNumToName(card, name); + printf("%-2d %-13s\n", deckIndex, name); + } + printf("\n"); +} + +void printPlayed(int player, struct gameState *game) { + int playedCount = game->playedCardCount; + int playedIndex; + printf("Player %d's played cards: \n", player); + if(playedCount > 0) printf("# Card\n"); + for(playedIndex = 0; playedIndex < playedCount; playedIndex++) { + int card = game->playedCards[playedIndex]; + char name[MAX_STRING_LENGTH]; + cardNumToName(card, name); + printf("%-2d %-13s \n", playedIndex, name); + } + printf("\n"); +} + + + +void printDiscard(int player, struct gameState *game) { + int discardCount = game->discardCount[player]; + int discardIndex; + printf("Player %d's discard: \n", player); + if(discardCount > 0) printf("# Card\n"); + for(discardIndex = 0; discardIndex < discardCount; discardIndex++) { + int card = game->discard[player][discardIndex]; + char name[MAX_STRING_LENGTH]; + cardNumToName(card, name); + printf("%-2d %-13s \n", discardIndex, name); + } + printf("\n"); +} + + + + +void printSupply(struct gameState *game) { + int cardNum, cardCost, cardCount; + char name[MAX_STRING_LENGTH]; + printf("# Card Cost Copies\n"); + for(cardNum = 0; cardNum < NUM_TOTAL_K_CARDS; cardNum++){ + cardCount = game->supplyCount[cardNum]; + if(cardCount == -1) continue; + cardNumToName(cardNum, name); + cardCost = getCardCost(cardNum); + printf("%-2d %-13s %-5d %-5d", cardNum, name, cardCost, cardCount); + printf("\n"); + } + printf("\n"); +} + + +void printState(struct gameState *game) { + int numActions = game->numActions; + int numCoins = game->coins; + int numBuys = game->numBuys; + int currentPlayer = game->whoseTurn; + int phase = game->phase; + char phaseName[MAX_STRING_LENGTH]; + phaseNumToName(phase,phaseName); + printf("Player %d:\n%s phase\n%d actions\n%d coins\n%d buys\n\n", currentPlayer, phaseName, numActions, numCoins, numBuys); +} + +void printScores(struct gameState *game) { + int playerNum, score[MAX_PLAYERS]; + int numPlayers = game->numPlayers; + for(playerNum = 0; playerNum < numPlayers; playerNum++) { + score[playerNum] = scoreFor(playerNum,game); + printf("Player %d has a score of %d\n", playerNum, score[playerNum]); + } +} + + +void printHelp(void) { + printf("Commands are: \n\ + add [Supply Card Number] - add any card to your hand (teh hacks)\n\ + buy [Supply Card Number] - buy a card at supply position\n\ + end - end your turn\n\ + init [Number of Players] [Number of Bots] - initialize the game\n\ + num - print number of cards in your hand\n\ + play [Hand Index] [Choice] [Choice] [Choice] - play a card from your hand\n\ + resign - end the game showing the current scores\n\ + show - show your current hand\n\ + stat - show your turn's status\n\ + supp - show the supply\n\ + whos - whos turn\n\ + exit - exit the interface"); + printf("\n\n"); + +} + + +void phaseNumToName(int phase, char *name) { + switch(phase){ + case ACTION_PHASE: strcpy(name,"Action"); + break; + case BUY_PHASE: strcpy(name,"Buy"); + break; + case CLEANUP_PHASE: strcpy(name,"Cleanup"); + break; + } +} + + +int addCardToHand(int player, int card, struct gameState *game) { + if(card >= adventurer && card < NUM_TOTAL_K_CARDS){ + int handTop = game->handCount[player]; + game->hand[player][handTop] = card; + game->handCount[player]++; + return SUCCESS; + } else { + return FAILURE; + } + +} + +void selectKingdomCards(int randomSeed, int kingCards[NUM_K_CARDS]) { + int i, used, card, numSelected = 0; + SelectStream(1); + PutSeed((long)randomSeed); + + + while(numSelected < NUM_K_CARDS) { + used = FALSE; + card = floor(Random() * NUM_TOTAL_K_CARDS); + if(card < adventurer) continue; + for(i = 0; i < numSelected; i++) { + if(kingCards[i] == card) { + used = TRUE; + break; + } + } + if(used == TRUE) continue; + kingCards[numSelected] = card; + numSelected++; + } +} + + +int countHandCoins(int player, struct gameState *game) { + int card, index, coinage = 0; + + for(index = 0; index < game->handCount[player]; index++) { + card = game->hand[player][index]; + switch(card) { + case copper: coinage += COPPER_VALUE; + break; + case silver: coinage += SILVER_VALUE; + break; + case gold: coinage += GOLD_VALUE; + break; + } + } + return coinage; +} + + +void executeBotTurn(int player, int *turnNum, struct gameState *game) { + int coins = countHandCoins(player, game); + + printf("*****************Executing Bot Player %d Turn Number %d*****************\n", player, *turnNum); + printSupply(game); + //sleep(1); //Thinking... + + if(coins >= PROVINCE_COST && supplyCount(province,game) > 0) { + buyCard(province,game); + printf("Player %d buys card Province\n\n", player); + } + else if(supplyCount(province,game) == 0 && coins >= DUCHY_COST ) { + buyCard(duchy,game); + printf("Player %d buys card Duchy\n\n", player); + } + else if(coins >= GOLD_COST && supplyCount(gold,game) > 0) { + buyCard(gold,game); + printf("Player %d buys card Gold\n\n", player); + } + else if(coins >= SILVER_COST && supplyCount(silver,game) > 0) { + buyCard(silver,game); + printf("Player %d buys card Silver\n\n", player); + + } + + + if(player == (game->numPlayers -1)) (*turnNum)++; + endTurn(game); + if(! isGameOver(game)) { + int currentPlayer = whoseTurn(game); + printf("Player %d's turn number %d\n\n", currentPlayer, (*turnNum)); + } +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/interface.h b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/interface.h new file mode 100644 index 0000000..f9023e4 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/interface.h @@ -0,0 +1,128 @@ +/* Interactive Dominion Interface + + Sam Heinith CS362 + 1/26/2010 +*/ + + + +#ifndef _INTERFACE_H +#define _INTERFACE_H + + + +#include "dominion.h" + +//Last card enum (Treasure map) card number plus one for the 0th card. +#define NUM_TOTAL_K_CARDS (treasure_map + 1) +#define NUM_K_CARDS 10 +#define NUM_V_CARDS_2 8 +#define NUM_V_CARDS_3or4 12 +#define NUM_C_CARDS_2 10 +#define NUM_C_CARDS_3 20 +#define NUM_C_CARDS_4 30 +#define NUM_COPPER 60 +#define NUM_SILVER 40 +#define NUM_GOLD 30 +#define UNUSED -1 +#define START_COPPER 7 +#define START_ESTATE 3 +#define HANDSIZE 5 + +#define COMPARE(string1, string2) strncmp(string1, string2, 4) +#define MAX_STRING_LENGTH 32 +#define TRUE 1 +#define FALSE 0 + +#define SUCCESS 0 +#define FAILURE -1 + +#define MATCH 0 +#define WINNER 1 +#define NOT_WINNER 0 + +//The Game Phases +#define ACTION_PHASE 0 +#define BUY_PHASE 1 +#define CLEANUP_PHASE 2 + +#define COPPER_VALUE 1 +#define SILVER_VALUE 2 +#define GOLD_VALUE 3 + +//From Dominion List Spoiler +#define COPPER_COST 0 +#define SILVER_COST 3 +#define GOLD_COST 6 +#define ESTATE_COST 2 +#define DUCHY_COST 5 +#define PROVINCE_COST 8 +#define CURSE_COST 0 +#define ADVENTURER_COST 6 +#define COUNCIL_ROOM_COST 5 +#define FEAST_COST 4 +#define GARDEN_COST 4 +#define MINE_COST 5 +#define MONEYLENDER_COST 4 +#define REMODEL_COST 4 +#define SMITHY_COST 4 +#define VILLAGE_COST 3 +#define WOODCUTTER_COST 3 +#define BARON_COST 4 +#define GREAT_HALL_COST 3 +#define MINION_COST 5 +#define SHANTY_TOWN_COST 3 +#define STEWARD_COST 3 +#define TRIBUTE_COST 5 +#define WISHING_WELL_COST 3 +#define AMBASSADOR_COST 3 +#define CUTPURSE_COST 4 +#define EMBARGO_COST 2 +#define OUTPOST_COST 5 +#define SALVAGER_COST 4 +#define SEA_HAG_COST 4 +#define TREASURE_MAP_COST 4 +#define ONETHOUSAND 1000 + + +int addCardToHand(int player, int card, struct gameState *game); + +int countHandCoins(int player, struct gameState *game); + + +void executeBotTurn(int player, int *turnNum, struct gameState *game); + +void phaseNumToName(int phase, char *name); +void cardNumToName(int card, char *name); + +int getCardCost(int card); + +void printHelp(void); + +void printHand(int player, struct gameState *game); + +void printDeck(int player, struct gameState *game); + +void printDiscard(int player, struct gameState *game); + +void printPlayed(int player, struct gameState *game); + +void printState(struct gameState *game); + +void printSupply(struct gameState *game); + +void printGameState(struct gameState *game); + +void printScores(struct gameState *game); + +void selectKingdomCards(int randomSeed, int kingdomCards[NUM_K_CARDS]); + + + +#endif + + + + + + diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/playdom.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/playdom.c new file mode 100644 index 0000000..b86abf1 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/playdom.c @@ -0,0 +1,134 @@ +#include "dominion.h" +#include +#include "rngs.h" +#include + +int main (int argc, char** argv) { + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + printf ("Starting game.\n"); + + initializeGame(2, k, atoi(argv[1]), &G); + + int money = 0; + int smithyPos = -1; + int adventurerPos = -1; + int i=0; + + int numSmithies = 0; + int numAdventurers = 0; + + while (!isGameOver(&G)) { + money = 0; + smithyPos = -1; + adventurerPos = -1; + for (i = 0; i < numHandCards(&G); i++) { + if (handCard(i, &G) == copper) + money++; + else if (handCard(i, &G) == silver) + money += 2; + else if (handCard(i, &G) == gold) + money += 3; + else if (handCard(i, &G) == smithy) + smithyPos = i; + else if (handCard(i, &G) == adventurer) + adventurerPos = i; + } + + if (whoseTurn(&G) == 0) { + if (smithyPos != -1) { + printf("0: smithy played from position %d\n", smithyPos); + playCard(smithyPos, -1, -1, -1, &G); + printf("smithy played.\n"); + money = 0; + i=0; + while(i= 8) { + printf("0: bought province\n"); + buyCard(province, &G); + } + else if (money >= 6) { + printf("0: bought gold\n"); + buyCard(gold, &G); + } + else if ((money >= 4) && (numSmithies < 2)) { + printf("0: bought smithy\n"); + buyCard(smithy, &G); + numSmithies++; + } + else if (money >= 3) { + printf("0: bought silver\n"); + buyCard(silver, &G); + } + + printf("0: end turn\n"); + endTurn(&G); + } + else { + if (adventurerPos != -1) { + printf("1: adventurer played from position %d\n", adventurerPos); + playCard(adventurerPos, -1, -1, -1, &G); + money = 0; + i=0; + while(i= 8) { + printf("1: bought province\n"); + buyCard(province, &G); + } + else if ((money >= 6) && (numAdventurers < 2)) { + printf("1: bought adventurer\n"); + buyCard(adventurer, &G); + numAdventurers++; + }else if (money >= 6){ + printf("1: bought gold\n"); + buyCard(gold, &G); + } + else if (money >= 3){ + printf("1: bought silver\n"); + buyCard(silver, &G); + } + printf("1: endTurn\n"); + + endTurn(&G); + } + } // end of While + + printf ("Finished game.\n"); + printf ("Player 0: %d\nPlayer 1: %d\n", scoreFor(0, &G), scoreFor(1, &G)); + + return 0; +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/player.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/player.c new file mode 100644 index 0000000..368e933 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/player.c @@ -0,0 +1,216 @@ +/* Interactive Dominion Interface + Version 7 + + Sam Heinith CS362 + Questions/Comments: + heiniths@onid.orst.edu + 1/26/2010 +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include "dominion.h" +#include "interface.h" +#include "rngs.h" + + +int main2(int argc, char *argv[]) { + //Default cards, as defined in playDom + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, sea_hag, tribute, smithy}; + struct gameState g; + initializeGame(2,k,1,&g); + printf ("SUCCESSFUL INIT\n"); + getchar(); +} + +int main(int argc, char* argv[]) { + char *add = "add"; + char *buyC = "buy"; + char *endT = "end"; + char *exit = "exit"; + char *help = "help"; + char *init = "init"; + char *numH = "num"; + char *play = "play"; + char *resign = "resi"; + char *show = "show"; + char *stat = "stat"; + char *supply = "supp"; + char *whos = "whos"; + + char command[MAX_STRING_LENGTH]; + char line[MAX_STRING_LENGTH]; + char cardName[MAX_STRING_LENGTH]; + + //Array to hold bot presence + int isBot[MAX_PLAYERS] = { 0, 0, 0, 0}; + + int players[MAX_PLAYERS]; + int playerNum; + int outcome; + int currentPlayer; + int gameOver = FALSE; + int gameStarted = FALSE; + int turnNum = 0; + + int randomSeed = atoi(argv[1]); + + //Default cards, as defined in playDom + int kCards[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, sea_hag, tribute, smithy}; + + struct gameState g; + struct gameState * game = &g; + + memset(game,0,sizeof(struct gameState)); + + if(argc != 2){ + printf("Usage: player [integer random number seed]\n"); + return EXIT_SUCCESS; + } + + if(randomSeed <= 0){ + printf("Usage: player [integer random number seed]\n"); + return EXIT_SUCCESS; + } + + initializeGame(2,kCards,randomSeed,game); + + printf("Please enter a command or \"help\" for commands\n"); + + + while(TRUE) { + int arg0 = UNUSED; + int arg1 = UNUSED; + int arg2 = UNUSED; + int arg3 = UNUSED; + + outcome = FAILURE; + strcpy(line,""); + strcpy(command,""); + strcpy(cardName,""); + + currentPlayer = whoseTurn(game); + + //If you are getting a seg fault comment this if block out + gameOver = isGameOver(game); + if(gameStarted == TRUE && gameOver == TRUE){ + printScores(game); + getWinners(players, game); + printf("After %d turns, the winner(s) are:\n", turnNum); + for(playerNum = 0; playerNum < game->numPlayers; playerNum++){ + if(players[playerNum] == WINNER) printf("Player %d\n", playerNum); + } + for(playerNum = 0; playerNum < game->numPlayers; playerNum++){ + printHand(playerNum, game); + printPlayed(playerNum, game); + printDiscard(playerNum, game); + printDeck(playerNum, game); + } + + break; //Exit out of the game/while loop + } + + + if(isBot[currentPlayer] == TRUE) { + executeBotTurn(currentPlayer, &turnNum, game); + continue; + } + + printf("$ "); + fgets(line, MAX_STRING_LENGTH, stdin); + sscanf(line, "%s %d %d %d %d", command, &arg0, &arg1, &arg2, &arg3); + + + if(COMPARE(command, add) == 0) { + outcome = addCardToHand(currentPlayer, arg0, game); + cardNumToName(arg0, cardName); + printf("Player %d adds %s to their hand\n\n", currentPlayer, cardName); + } else + if(COMPARE(command, buyC) == 0) { + outcome = buyCard(arg0, game); + cardNumToName(arg0, cardName); + if(outcome == SUCCESS){ + printf("Player %d buys card %d, %s\n\n", currentPlayer, arg0, cardName); + } else { + printf("Player %d cannot buy card %d, %s\n\n", currentPlayer, arg0, cardName); + } + } else + if(COMPARE(command, endT) == 0) { + if(gameStarted == TRUE) { + if(currentPlayer == (game->numPlayers -1)) turnNum++; + endTurn(game); + currentPlayer = whoseTurn(game); + printf("Player %d's turn number %d\n\n", currentPlayer, turnNum); + } + + } else + if(COMPARE(command, exit) == 0) { + break; + } else + if(COMPARE(command, help) == 0) { + printHelp(); + } else + if(COMPARE(command, init) == 0) { + int numHuman = arg0 - arg1; + for(playerNum = numHuman; playerNum < arg0; playerNum++) { + isBot[playerNum] = TRUE; + } + // selectKingdomCards(randomSeed, kCards); //Comment this out to use the default card set defined in playDom. + outcome = initializeGame(arg0, kCards, randomSeed, game); + printf("\n"); + if(outcome == SUCCESS){ + gameStarted = TRUE; + currentPlayer = whoseTurn(game); + printf("Player %d's turn number %d\n\n", currentPlayer, turnNum); + } + + } else + if(COMPARE(command, numH) == 0) { + int numCards = numHandCards(game); + printf("There are %d cards in your hand.\n", numCards); + } else + if(COMPARE(command, play) == 0) { + int card = handCard(arg0,game); + outcome = playCard(arg0, arg1, arg2, arg3, game); + cardNumToName(card, cardName); + if(outcome == SUCCESS){ + printf("Player %d plays %s\n\n", currentPlayer, cardName); + } else { + printf("Player %d cannot play card %d\n\n", currentPlayer, arg0); + } + + } else + if(COMPARE(command, resign) == 0) { + endTurn(game); + printScores(game); + break; + } else + if(COMPARE(command, show) == 0) { + if(gameStarted == FALSE) continue; + printHand(currentPlayer, game); + printPlayed(currentPlayer, game); + //printDiscard(currentPlayer, game); + //printDeck(currentPlayer, game); + } else + if(COMPARE(command, stat) == 0) { + if(gameStarted == FALSE) continue; + printState(game); + } else + if(COMPARE(command, supply) == 0) { + printSupply(game); + } else + if(COMPARE(command, whos) == 0) { + int playerNum = whoseTurn(game); + printf("Player %d's turn\n", playerNum); + } + } + + return EXIT_SUCCESS; + +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/randomtestadventurer.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/randomtestadventurer.c new file mode 100644 index 0000000..b1148be --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/randomtestadventurer.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression, int should_print); + +long sucesses = 0; +long failures = 0; + +int main(int argc, char** argv) { + // Get seed from command line arg and setup randomization or exit + if(argc < 2){ + printf("Please enter a seed value for randomization.\n"); + printf("usage: %s [seed]\n", argv[0]); + return EXIT_FAILURE; + } + + long seed = atoi(argv[1]); + + + SelectStream(1); + PutSeed(seed); + + // Game variables + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + // Initialize the game + initializeGame(4, k, seed, &G); + + // Limiting variables + unsigned int arbritray_num_tests = 100000; + unsigned int arbitrary_hand_count_max = MAX_HAND - 2; + + for(int z = 0 ; z < arbritray_num_tests ; z++){ + int turn = floor(Random() *MAX_PLAYERS); + int starting_hand = floor(Random() * arbitrary_hand_count_max); + + G.deckCount[turn] = MAX_DECK; + G.discardCount[turn] = 0; + + G.handCount[turn] = starting_hand; + G.whoseTurn = turn; + + playAdventurer(&G); + + testing_assert(G.handCount[turn] == starting_hand + 2, 0); + testing_assert((G.hand[turn][G.handCount[turn] - 1] >= copper) && (G.hand[turn][G.handCount[turn] - 1] <= gold), 0); + testing_assert((G.hand[turn][G.handCount[turn] - 2] >= copper) && (G.hand[turn][G.handCount[turn] - 2] <= gold), 0); + + + G.handCount[turn] = starting_hand; + G.deckCount[turn] = 0; + G.discardCount[turn] = 0; + + for(int m = 0 ; m < MAX_DECK ; m++){ + int card = copper + floor(Random() * 2); + + G.discard[turn][m] = card; + G.discardCount[turn]++; + } + + + playAdventurer(&G); + + testing_assert(G.handCount[turn] == starting_hand + 2, 0); + testing_assert((G.hand[turn][G.handCount[turn] - 1] >= copper) && (G.hand[turn][G.handCount[turn] - 1] <= gold), 0); + testing_assert((G.hand[turn][G.handCount[turn] - 2] >= copper) && (G.hand[turn][G.handCount[turn] - 2] <= gold), 0); + } + + printf("Run complete!\n"); + printf("SUCCESSES: %ld\n", sucesses); + + if(failures > 0){ + printf("Some tests failed!!!\n"); + printf("FAILURES: %ld\n", failures); + } + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression, int should_print) { + if (expression) { + if(should_print){ + printf("TEST SUCCEEDED!\n"); + } + sucesses++; + return 1; + } else { + if(should_print){ + printf("TEST FAILED!\n"); + } + failures++; + return 0; + } +} \ No newline at end of file diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/randomtestcard1.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/randomtestcard1.c new file mode 100644 index 0000000..57cc698 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/randomtestcard1.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression, int should_print); + +long sucesses = 0; +long failures = 0; + +int main(int argc, char** argv) { + // Get seed from command line arg and setup randomization or exit + if(argc < 2){ + printf("Please enter a seed value for randomization.\n"); + printf("usage: %s [seed]\n", argv[0]); + return EXIT_FAILURE; + } + + long seed = atoi(argv[1]); + + SelectStream(1); + PutSeed(seed); + + // Game variables + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + // Initialize the game + initializeGame(4, k, seed, &G); + + // Limiting variables + unsigned int arbritray_num_tests = 1000000; + unsigned int arbitrary_hand_count_max = MAX_HAND - 2; + + for(int z = 0 ; z < arbritray_num_tests ; z++){ + int turn = floor(Random() * MAX_PLAYERS); + int starting_hand = floor(Random() * arbitrary_hand_count_max); + + G.handCount[turn] = starting_hand; + G.whoseTurn = turn; + + int outpost_before = G.outpostPlayed; + int handcount_before = G.handCount[turn]; + playOutpost(&G, turn); + + testing_assert(G.outpostPlayed == outpost_before + 1, 0); + testing_assert(G.handCount[turn] == handcount_before - 1, 0); + } + + printf("Run complete!\n"); + printf("SUCCESSES: %ld\n", sucesses); + + if(failures > 0){ + printf("Some tests failed!!!\n"); + printf("FAILURES: %ld\n", failures); + } + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression, int should_print) { + if (expression) { + if(should_print){ + printf("TEST SUCCEEDED!\n"); + } + sucesses++; + return 1; + } else { + if(should_print){ + printf("TEST FAILED!\n"); + } + failures++; + return 0; + } +} \ No newline at end of file diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/randomtestcard2.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/randomtestcard2.c new file mode 100644 index 0000000..1a22462 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/randomtestcard2.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression, int should_print); + +long sucesses = 0; +long failures = 0; + +int main(int argc, char** argv) { + // Get seed from command line arg and setup randomization or exit + if(argc < 2){ + printf("Please enter a seed value for randomization.\n"); + printf("usage: %s [seed]\n", argv[0]); + return EXIT_FAILURE; + } + + long seed = atoi(argv[1]); + + SelectStream(1); + PutSeed(seed); + + // Game variables + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + // Initialize the game + initializeGame(4, k, seed, &G); + + // Limiting variables + unsigned int arbritray_num_tests = 1000000; + unsigned int arbitrary_hand_count_max = MAX_HAND - 2; + + for(int z = 0 ; z < arbritray_num_tests ; z++){ + int turn = floor(Random() * MAX_PLAYERS); + int hand_pos = floor(Random() * arbitrary_hand_count_max); + + G.deckCount[turn] = MAX_DECK; + G.whoseTurn = turn; + + int hand_count = G.handCount[turn]; + int num_actions = G.numActions; + + playGreat_Hall(&G, hand_pos); + testing_assert(G.handCount[turn] == hand_count, 0); + testing_assert(G.numActions == num_actions + 1, 0); + + for(int k = 0 ; k < G.handCount[turn] ; k++){ + testing_assert((G.hand[turn][k] >= curse) && (G.hand[turn][k] <= treasure_map), 0); + } + } + + printf("Run complete!\n"); + printf("SUCCESSES: %ld\n", sucesses); + + if(failures > 0){ + printf("Some tests failed!!!\n"); + printf("FAILURES: %ld\n", failures); + } + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression, int should_print) { + if (expression) { + if(should_print){ + printf("TEST SUCCEEDED!\n"); + } + sucesses++; + return 1; + } else { + if(should_print){ + printf("TEST FAILED!\n"); + } + failures++; + return 0; + } +} \ No newline at end of file diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/rngs.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/rngs.c new file mode 100644 index 0000000..1e71aca --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/rngs.c @@ -0,0 +1,179 @@ +/* ------------------------------------------------------------------------- + * This is an ANSI C library for multi-stream random number generation. + * The use of this library is recommended as a replacement for the ANSI C + * rand() and srand() functions, particularly in simulation applications + * where the statistical 'goodness' of the random number generator is + * important. The library supplies 256 streams of random numbers; use + * SelectStream(s) to switch between streams indexed s = 0,1,...,255. + * + * The streams must be initialized. The recommended way to do this is by + * using the function PlantSeeds(x) with the value of x used to initialize + * the default stream and all other streams initialized automatically with + * values dependent on the value of x. The following convention is used + * to initialize the default stream: + * if x > 0 then x is the state + * if x < 0 then the state is obtained from the system clock + * if x = 0 then the state is to be supplied interactively. + * + * The generator used in this library is a so-called 'Lehmer random number + * generator' which returns a pseudo-random number uniformly distributed + * 0.0 and 1.0. The period is (m - 1) where m = 2,147,483,647 and the + * smallest and largest possible values are (1 / m) and 1 - (1 / m) + * respectively. For more details see: + * + * "Random Number Generators: Good Ones Are Hard To Find" + * Steve Park and Keith Miller + * Communications of the ACM, October 1988 + * + * Name : rngs.c (Random Number Generation - Multiple Streams) + * Authors : Steve Park & Dave Geyer + * Language : ANSI C + * Latest Revision : 09-22-98 + * ------------------------------------------------------------------------- + */ + +#include +#include +#include "rngs.h" + +#define MODULUS 2147483647 /* DON'T CHANGE THIS VALUE */ +#define MULTIPLIER 48271 /* DON'T CHANGE THIS VALUE */ +#define CHECK 399268537 /* DON'T CHANGE THIS VALUE */ +#define STREAMS 256 /* # of streams, DON'T CHANGE THIS VALUE */ +#define A256 22925 /* jump multiplier, DON'T CHANGE THIS VALUE */ +#define DEFAULT 123456789 /* initial seed, use 0 < DEFAULT < MODULUS */ + +static long seed[STREAMS] = {DEFAULT}; /* current state of each stream */ +static int stream = 0; /* stream index, 0 is the default */ +static int initialized = 0; /* test for stream initialization */ + + + double Random(void) +/* ---------------------------------------------------------------- + * Random returns a pseudo-random real number uniformly distributed + * between 0.0 and 1.0. + * ---------------------------------------------------------------- + */ +{ + const long Q = MODULUS / MULTIPLIER; + const long R = MODULUS % MULTIPLIER; + long t; + + t = MULTIPLIER * (seed[stream] % Q) - R * (seed[stream] / Q); + if (t > 0) + seed[stream] = t; + else + seed[stream] = t + MODULUS; + return ((double) seed[stream] / MODULUS); +} + + + void PlantSeeds(long x) +/* --------------------------------------------------------------------- + * Use this function to set the state of all the random number generator + * streams by "planting" a sequence of states (seeds), one per stream, + * with all states dictated by the state of the default stream. + * The sequence of planted states is separated one from the next by + * 8,367,782 calls to Random(). + * --------------------------------------------------------------------- + */ +{ + const long Q = MODULUS / A256; + const long R = MODULUS % A256; + int j; + int s; + + initialized = 1; + s = stream; /* remember the current stream */ + SelectStream(0); /* change to stream 0 */ + PutSeed(x); /* set seed[0] */ + stream = s; /* reset the current stream */ + for (j = 1; j < STREAMS; j++) { + x = A256 * (seed[j - 1] % Q) - R * (seed[j - 1] / Q); + if (x > 0) + seed[j] = x; + else + seed[j] = x + MODULUS; + } +} + + + void PutSeed(long x) +/* --------------------------------------------------------------- + * Use this function to set the state of the current random number + * generator stream according to the following conventions: + * if x > 0 then x is the state (unless too large) + * if x < 0 then the state is obtained from the system clock + * if x = 0 then the state is to be supplied interactively + * --------------------------------------------------------------- + */ +{ + char ok = 0; + + if (x > 0) + x = x % MODULUS; /* correct if x is too large */ + if (x < 0) + x = ((unsigned long) time((time_t *) NULL)) % MODULUS; + if (x == 0) + while (!ok) { + printf("\nEnter a positive integer seed (9 digits or less) >> "); + scanf("%ld", &x); + ok = (0 < x) && (x < MODULUS); + if (!ok) + printf("\nInput out of range ... try again\n"); + } + seed[stream] = x; +} + + + void GetSeed(long *x) +/* --------------------------------------------------------------- + * Use this function to get the state of the current random number + * generator stream. + * --------------------------------------------------------------- + */ +{ + *x = seed[stream]; +} + + + void SelectStream(int index) +/* ------------------------------------------------------------------ + * Use this function to set the current random number generator + * stream -- that stream from which the next random number will come. + * ------------------------------------------------------------------ + */ +{ + stream = ((unsigned int) index) % STREAMS; + if ((initialized == 0) && (stream != 0)) /* protect against */ + PlantSeeds(DEFAULT); /* un-initialized streams */ +} + + + void TestRandom(void) +/* ------------------------------------------------------------------ + * Use this (optional) function to test for a correct implementation. + * ------------------------------------------------------------------ + */ +{ + long i; + long x; + /*double u;*/ /* used to be uncommented */ + char ok = 0; + + SelectStream(0); /* select the default stream */ + PutSeed(1); /* and set the state to 1 */ + for(i = 0; i < 10000; i++) + Random(); /* used to have u = Random() */ + GetSeed(&x); /* get the new state value */ + ok = (x == CHECK); /* and check for correctness */ + + SelectStream(1); /* select stream 1 */ + PlantSeeds(1); /* set the state of all streams */ + GetSeed(&x); /* get the state of stream 1 */ + ok = ok && (x == A256); /* x should be the jump multiplier */ + if (ok) + printf("\n The implementation of rngs.c is correct.\n\n"); + else + printf("\n\a ERROR -- the implementation of rngs.c is not correct.\n\n"); +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/rngs.h b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/rngs.h new file mode 100644 index 0000000..d6a5663 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/rngs.h @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------- + * Name : rngs.h (header file for the library file rngs.c) + * Author : Steve Park & Dave Geyer + * Language : ANSI C + * Latest Revision : 09-22-98 + * ----------------------------------------------------------------------- + */ + +#if !defined( _RNGS_ ) +#define _RNGS_ + +double Random(void); +void PlantSeeds(long x); +void GetSeed(long *x); +void PutSeed(long x); +void SelectStream(int index); +void TestRandom(void); + +#endif diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/rt.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/rt.c new file mode 100644 index 0000000..ea78c5b --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/rt.c @@ -0,0 +1,27 @@ +#include "rngs.h" +#include +#include + +int main(int argc, char** argv) { + if (argc < 3) { + printf ("Not enough inputs: seed target\n"); + } + + SelectStream(1); + PutSeed((long)atoi(argv[1])); + + int done = 0; + int c = 1000000000; + + while (!done) { + c = floor(Random() * 1000000000); + // if (c % 100000 == 0) { + // printf ("c = %d\n", c); + // } + if (c == atoi(argv[2])) { + printf ("Found the bug!\n"); + done = 1; + } + } +} + diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/supplyTest.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/supplyTest.c new file mode 100644 index 0000000..93bc788 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/supplyTest.c @@ -0,0 +1,30 @@ +#include "dominion.h" +#include "dominion_helpers.h" +#include +#include +#include +#include "rngs.h" + +#define DEBUG 0 +#define NOISY_TEST 1 + +int main () { + + int r; + + int k[10] = {adventurer, council_room, feast, gardens, mine, + remodel, smithy, village, baron, great_hall}; + + struct gameState G; + + r = initializeGame(4, k, 1, &G); + + printf ("initializeGame(4, k, 1, &G) = %d\n", r); + assert(r == 0); + + r = supplyCount(adventurer, &G); + printf ("supplyCount(adventurer, &G) = %d\n", r); + assert(r == 10); + + return 0; +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testBuyCard.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testBuyCard.c new file mode 100644 index 0000000..c8daa34 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testBuyCard.c @@ -0,0 +1,94 @@ +#include "dominion.h" +#include "dominion_helpers.h" +#include +#include +#include +#include "rngs.h" + +#define DEBUG 0 +#define NOISY_TEST 1 + +int checkDrawCard(int p, struct gameState *post) { + struct gameState pre; + memcpy (&pre, post, sizeof(struct gameState)); + + int r; + // printf ("drawCard PRE: p %d HC %d DeC %d DiC %d\n", + // p, pre.handCount[p], pre.deckCount[p], pre.discardCount[p]); + + r = drawCard (p, post); + + //printf ("drawCard POST: p %d HC %d DeC %d DiC %d\n", + // p, post->handCount[p], post->deckCount[p], post->discardCount[p]); + + if (pre.deckCount[p] > 0) { + pre.handCount[p]++; + pre.hand[p][pre.handCount[p]-1] = pre.deck[p][pre.deckCount[p]-1]; + pre.deckCount[p]--; + } else if (pre.discardCount[p] > 0) { + memcpy(pre.deck[p], post->deck[p], sizeof(int) * pre.discardCount[p]); + memcpy(pre.discard[p], post->discard[p], sizeof(int)*pre.discardCount[p]); + pre.hand[p][post->handCount[p]-1] = post->hand[p][post->handCount[p]-1]; + pre.handCount[p]++; + pre.deckCount[p] = pre.discardCount[p]-1; + pre.discardCount[p] = 0; + } + + assert (r == 0); + + assert(memcmp(&pre, post, sizeof(struct gameState)) == 0); +} + +int main () { + + int i, n, r, p, deckCount, discardCount, handCount; + + int k[10] = {adventurer, council_room, feast, gardens, mine, + remodel, smithy, village, baron, great_hall}; + + + struct gameState G; + + printf ("Testing buyCard.\n"); + + printf ("RANDOM TESTS.\n"); + + SelectStream(2); + PutSeed(3); + + for (n = 0; n < 2000; n++) { + for (i = 0; i < sizeof(struct gameState); i++) { + ((char*)&G)[i] = floor(Random() * 256); + } + p = floor(Random() * 2); + G.deckCount[p] = floor(Random() * MAX_DECK); + G.discardCount[p] = floor(Random() * MAX_DECK); + G.handCount[p] = floor(Random() * MAX_HAND); + checkDrawCard(p, &G); + } + + printf ("ALL TESTS OK\n"); + + exit(0); + + printf ("SIMPLE FIXED TESTS.\n"); + for (p = 0; p < 2; p++) { + for (deckCount = 0; deckCount < 5; deckCount++) { + for (discardCount = 0; discardCount < 5; discardCount++) { + for (handCount = 0; handCount < 5; handCount++) { + memset(&G, 23, sizeof(struct gameState)); + r = initializeGame(2, k, 1, &G); + G.deckCount[p] = deckCount; + memset(G.deck[p], 0, sizeof(int) * deckCount); + G.discardCount[p] = discardCount; + memset(G.discard[p], 0, sizeof(int) * discardCount); + G.handCount[p] = handCount; + memset(G.hand[p], 0, sizeof(int) * handCount); + checkDrawCard(p, &G); + } + } + } + } + + return 0; +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testDrawCard.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testDrawCard.c new file mode 100644 index 0000000..ace1a66 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testDrawCard.c @@ -0,0 +1,94 @@ +#include "dominion.h" +#include "dominion_helpers.h" +#include +#include +#include +#include +#include "rngs.h" + +#define DEBUG 0 +#define NOISY_TEST 1 + +int checkDrawCard(int p, struct gameState *post) { + struct gameState pre; + memcpy (&pre, post, sizeof(struct gameState)); + + int r; + // printf ("drawCard PRE: p %d HC %d DeC %d DiC %d\n", + // p, pre.handCount[p], pre.deckCount[p], pre.discardCount[p]); + + r = drawCard (p, post); + + //printf ("drawCard POST: p %d HC %d DeC %d DiC %d\n", + // p, post->handCount[p], post->deckCount[p], post->discardCount[p]); + + if (pre.deckCount[p] > 0) { + pre.handCount[p]++; + pre.hand[p][pre.handCount[p]-1] = pre.deck[p][pre.deckCount[p]-1]; + pre.deckCount[p]--; + } else if (pre.discardCount[p] > 0) { + memcpy(pre.deck[p], post->deck[p], sizeof(int) * pre.discardCount[p]); + memcpy(pre.discard[p], post->discard[p], sizeof(int)*pre.discardCount[p]); + pre.hand[p][post->handCount[p]-1] = post->hand[p][post->handCount[p]-1]; + pre.handCount[p]++; + pre.deckCount[p] = pre.discardCount[p]-1; + pre.discardCount[p] = 0; + } + + assert (r == 0); + + assert(memcmp(&pre, post, sizeof(struct gameState)) == 0); +} + +int main () { + + int i, n, r, p, deckCount, discardCount, handCount; + + int k[10] = {adventurer, council_room, feast, gardens, mine, + remodel, smithy, village, baron, great_hall}; + + struct gameState G; + + printf ("Testing drawCard.\n"); + + printf ("RANDOM TESTS.\n"); + + SelectStream(2); + PutSeed(3); + + for (n = 0; n < 2000; n++) { + for (i = 0; i < sizeof(struct gameState); i++) { + ((char*)&G)[i] = floor(Random() * 256); + } + p = floor(Random() * 2); + G.deckCount[p] = floor(Random() * MAX_DECK); + G.discardCount[p] = floor(Random() * MAX_DECK); + G.handCount[p] = floor(Random() * MAX_HAND); + checkDrawCard(p, &G); + } + + printf ("ALL TESTS OK\n"); + + exit(0); + + printf ("SIMPLE FIXED TESTS.\n"); + for (p = 0; p < 2; p++) { + for (deckCount = 0; deckCount < 5; deckCount++) { + for (discardCount = 0; discardCount < 5; discardCount++) { + for (handCount = 0; handCount < 5; handCount++) { + memset(&G, 23, sizeof(struct gameState)); + r = initializeGame(2, k, 1, &G); + G.deckCount[p] = deckCount; + memset(G.deck[p], 0, sizeof(int) * deckCount); + G.discardCount[p] = discardCount; + memset(G.discard[p], 0, sizeof(int) * discardCount); + G.handCount[p] = handCount; + memset(G.hand[p], 0, sizeof(int) * handCount); + checkDrawCard(p, &G); + } + } + } + } + + return 0; +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testInit.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testInit.c new file mode 100644 index 0000000..ea46057 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testInit.c @@ -0,0 +1,56 @@ +#include "dominion.h" +#include +#include +#include "rngs.h" + +int main (int argc, char** argv) { + + struct gameState G; + + int i; + + int start = -1; + + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + memset(&G, 'z', sizeof(struct gameState)); + + initializeGame(4, k, atoi(argv[1]), &G); + + printf ("Rough guide to locations in structure:\n"); + printf ("0: numPlayers\n"); + printf ("%ld: supplyCount[0]\n", ((long)&(G.supplyCount[0]))-((long)&G)); + printf ("%ld: embargoTokens[0]\n", ((long)&(G.embargoTokens[0]))-((long)&G)); + printf ("%ld: hand[0][0]\n", ((long)&(G.hand[0][0]))-(long)(&G)); + printf ("%ld: deck[0][0]\n", ((long)&(G.deck[0][0]))-(long)(&G)); + printf ("%ld: discard[0][0]\n", ((long)&(G.discard[0][0]))-(long)(&G)); + printf ("%ld: playerCards[0]\n", ((long)&(G.playedCards[0]))-(long)(&G)); + + for (i = 0; i < sizeof(struct gameState); i++) { + if (((char*)&G)[i] == 'z') { + if (start == -1) { + start = i; + } + } else{ + if (start != -1) { + if (start == (i-1)) { + printf ("Byte %d uninitialized.\n", start); + } else { + printf ("Bytes %d-%d uninitialized.\n", start, i-1); + } + start = -1; + } + } + } + + if (start != -1) { + if (start == (i-1)) { + printf ("Byte %d uninitialized.\n", start); + } else { + printf ("Bytes %d-%d uninitialized.\n", start, i-1); + } + } + + return 0; +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testShuffle.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testShuffle.c new file mode 100644 index 0000000..1cccb19 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/testShuffle.c @@ -0,0 +1,27 @@ +#include "dominion.h" +#include +#include + +int compare(const int* a, const int* b); + +int main () { + struct gameState G; + struct gameState G2; + + // Initialize G. + + memcpy (&G2, &G, sizeof(struct gameState)); + + int ret = shuffle(0,&G); + + if (G.deckCount[0] > 0) { + assert (ret != -1); + + qsort ((void*)(G.deck[0]), G.deckCount[0], sizeof(int), compare); + qsort ((void*)(G2.deck[0]), G2.deckCount[0], sizeof(int), compare); + } else + assert (ret == -1); + + assert(memcmp(&G, &G2, sizeof(struct gameState)) == 0); + +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest1.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest1.c new file mode 100644 index 0000000..341b583 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest1.c @@ -0,0 +1,69 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: unittest1.c + * Author: corwinperren + * + * Created on February 1, 2017, 9:02 PM + */ + +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression); + +int main(int argc, char** argv) { + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + initializeGame(2, k, 65432, &G); + + //If province cards are empty or are least three supply piles are, game end + //else game is not over. 1 is game end, 0 is game continues + + unsigned int victory_cards_max = 12; + unsigned int num_supply_piles = treasure_map+1; + unsigned int max_count_for_any_supply = 60; + + int i; + for (i = 0; i < victory_cards_max; i++) { + int num_zeroed = 0; + + for (int k = 0; k < num_supply_piles; k++) { + G.supplyCount[k] = max_count_for_any_supply; + } + + for (; num_zeroed < num_supply_piles; num_zeroed++) { + for (int j = 0; j < num_zeroed; j++) { + G.supplyCount[j] = 0; + } + + G.supplyCount[province] = i; + + if ((G.supplyCount[province] == 0) || (num_zeroed >= 3)) { + testing_assert(isGameOver(&G) == 1); + } else { + testing_assert(isGameOver(&G) == 0); + } + } + } + return (EXIT_SUCCESS); +} + +int testing_assert(int expression) { + if (expression) { + printf("TEST SUCCEEDED!\n"); + return 1; + } else { + printf("TEST FAILED!\n"); + return 0; + } +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest2.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest2.c new file mode 100644 index 0000000..e6bda02 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest2.c @@ -0,0 +1,88 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: unittest1.c + * Author: corwinperren + * + * Created on February 1, 2017, 9:02 PM + */ + +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression); + +int main(int argc, char** argv) { + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + unsigned int min_players = 2; + unsigned int max_players = MAX_PLAYERS; + unsigned int max_hand = MAX_HAND; + unsigned int arbitrary_bonus_max = 1000; + unsigned int copper_worth = 1; + unsigned int silver_worth = 2; + unsigned int gold_worth = 3; + + + for(int i = min_players ; i <= max_players ; i++){ + initializeGame(i, k, 65432, &G); + + for(int j = 0 ; j < i ; j++){ + G.handCount[j] = max_hand; + + for(int k = 0 ; k < max_hand ; k++){ + G.hand[j][k] = copper; + } + + updateCoins(j, &G, 0); + testing_assert(G.coins == (max_hand*copper_worth)); + + updateCoins(j, &G, arbitrary_bonus_max); + testing_assert(G.coins == ((max_hand*copper_worth) + arbitrary_bonus_max)); + + + for(int k = 0 ; k < max_hand ; k++){ + G.hand[j][k] = silver; + } + + updateCoins(j, &G, 0); + testing_assert(G.coins == (max_hand*silver_worth)); + + updateCoins(j, &G, arbitrary_bonus_max); + testing_assert(G.coins == ((max_hand*silver_worth) + arbitrary_bonus_max)); + + for(int k = 0 ; k < max_hand ; k++){ + G.hand[j][k] = gold; + } + + updateCoins(j, &G, 0); + testing_assert(G.coins == (max_hand*gold_worth)); + + updateCoins(j, &G, arbitrary_bonus_max); + testing_assert(G.coins == ((max_hand*gold_worth) + arbitrary_bonus_max)); + + } + + } + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression) { + if (expression) { + printf("TEST SUCCEEDED!\n"); + return 1; + } else { + printf("TEST FAILED!\n"); + return 0; + } +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest3.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest3.c new file mode 100644 index 0000000..27c5a7d --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest3.c @@ -0,0 +1,47 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: unittest1.c + * Author: corwinperren + * + * Created on February 1, 2017, 9:02 PM + */ + +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression); + +int main(int argc, char** argv) { + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + for(int i = 2 ; i <= MAX_PLAYERS ; i++){ + initializeGame(i, k, 65432, &G); + + for(int j = 0 ; j < i ; j++){ + G.whoseTurn = j; + testing_assert(whoseTurn(&G) == j); + } + } + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression) { + if (expression) { + printf("TEST SUCCEEDED!\n"); + return 1; + } else { + printf("TEST FAILED!\n"); + return 0; + } +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest4.c b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest4.c new file mode 100644 index 0000000..cdc39a0 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/1 - Dominion Unit Testing/unittest4.c @@ -0,0 +1,55 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: unittest1.c + * Author: corwinperren + * + * Created on February 1, 2017, 9:02 PM + */ + +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression); + +int main(int argc, char** argv) { + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + initializeGame(4, k, 65432, &G); + + unsigned int num_card_types = 27; + + for(int i = 0 ; i < MAX_PLAYERS ; i++){ + G.whoseTurn = i; + G.handCount[i] = MAX_HAND; + + for(int j = 0 ; j < MAX_HAND ; j++){ + for(int k = 0 ; k < num_card_types ; k++){ + G.hand[i][j] = k; + testing_assert(handCard(j, &G) == k); + } + } + } + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression) { + if (expression) { + printf("TEST SUCCEEDED!\n"); + return 1; + } else { + printf("TEST FAILED!\n"); + return 0; + } +} + diff --git a/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/BugsInTeammate.txt b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/BugsInTeammate.txt new file mode 100644 index 0000000..b396da1 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/BugsInTeammate.txt @@ -0,0 +1,60 @@ +############################# +########## Bug #01 ########## +############################# +Title: playSmithy Incorrect Card Pickup Count + +Affected Files: dominion.c + +Pertinent Code: +dominion.c: Line 717 + +Test Environment: Red Hat Linux 4.8.5-4 (Kernel 3.10.0) + +Expected Result: +A call to playSmithy should add three cards to the player's hand, then +discard the played card. The final result should be a hand with two extra cards +in it. + +Actual Result: +playSmithy picks up five cards instead of three, then discards a card like +normal. The result is a hand with four extra cards instead of two. + +Steps to Reproduce: +1. Use the other game functions to set up a normal game state. +2. Set a current player. +3. Save the handcount for the player in a temp variable. +4. Call playSmithy against the selected player. +5. Compare the saved handcount to the new handcount to see incorrect number. + + +############################# +########## Bug #02 ########## +############################# +Title: playAdventurer Incorrect Hand Count When Drawing Non-Treasure Cards + +Affected Files: dominion.c + +Pertinent Code: +dominion.c: Line 701 + +Test Environment: Red Hat Linux 4.8.5-4 (Kernel 3.10.0) + +Expected Result: +In a call to playAdventurer, during the process of "picking up" cards, +the temp hand stores a copy of any cards that aren't treasure cards, then +removes the just saved "top card". This allows cards to be shuffled back into +the game without being lost. + +Actual Result: +In a call to playAdventurer, during the process of "picking up" cards, +instead of removing the top card, an invalid top card is instead added. +Depending on the previous state of the hand, the error may not show itself, +for example, if every card picked up were a treasure card. In the case where +this bug is hit, invalid cards could be shuffled back into the players hand at +a later time, causing major bugs in gameplay. + +Steps to Reproduce: +1. Use the other game functions to set up a normal game state. +2. Set a current player. +4. Call playAdventurer against the selected player. +5. Manually inspect the hand of the player and note invalid card indexes. \ No newline at end of file diff --git a/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/Makefile b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/Makefile new file mode 100644 index 0000000..2fe943b --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/Makefile @@ -0,0 +1,27 @@ +CFLAGS = -Wall -fpic -coverage -lm -std=c99 -ftest-coverage -fprofile-arcs + +all: assignment5 + +assignment5: + echo "Compiling and running all tests....." > unittestresults.out + + gcc -o cardtest2 cardtest2.c dominion.c rngs.c -g $(CFLAGS) + echo "Running Cardtest2...." >> unittestresults.out + ./cardtest2 >> unittestresults.out + gcov dominion.c >> unittestresults.out + cat dominion.c.gcov >> unittestresults.out + cat dominion.c.gcov >> cardtest2.gcov + + echo "######################################" >> unittestresults.out + echo "######################################" >> unittestresults.out + + gcc -o cardtest3 cardtest3.c dominion.c rngs.c -g $(CFLAGS) + echo "Running Cardtest3...." >> unittestresults.out + ./cardtest3 >> unittestresults.out + gcov dominion.c >> unittestresults.out + cat dominion.c.gcov >> unittestresults.out + cat dominion.c.gcov >> cardtest3.gcov + +clean: + rm -f *.o playdom.exe playdom test.exe test player player.exe testInit testInit.exe *.gcov *.gcda *.gcno *.so *.out + rm -f cardtest2 cardtest3 diff --git a/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/cardtest2.c b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/cardtest2.c new file mode 100644 index 0000000..0288e7b --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/cardtest2.c @@ -0,0 +1,85 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: unittest1.c + * Author: corwinperren + * + * Created on February 1, 2017, 9:02 PM + */ + +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression, int should_print); + +long sucesses = 0; +long failures = 0; + +int main(int argc, char** argv) { + struct gameState G, G_copy; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + + unsigned int arbitrary_hand_count_max = MAX_HAND - 3; + + for(int l = 0 ; l < 4 ; l++){ + for(int i = 1 ; i < arbitrary_hand_count_max ; i++){ + initializeGame(4, k, 65432, &G); + G.handCount[0] = arbitrary_hand_count_max; + G.whoseTurn = l; + + G_copy = G; + + drawCard(0, &G_copy); + drawCard(0, &G_copy); + drawCard(0, &G_copy); + discardCard(i, l, &G_copy, 0); + + playSmithy(&G, i, G.whoseTurn); + + testing_assert(G.handCount[l] == G_copy.handCount[l], 0); + + for(int j = 0 ; j < arbitrary_hand_count_max ; j++){ + testing_assert((G.hand[l][j] >= curse) && (G.hand[l][j] <= treasure_map), 0); + testing_assert((G_copy.hand[l][j] >= curse) && (G_copy.hand[l][j] <= treasure_map), 0); + } + + } + } + + printf("Run complete!\n"); + printf("SUCCESSES: %ld\n", sucesses); + + if(failures > 0){ + printf("Some tests failed!!!\n"); + printf("FAILURES: %ld\n", failures); + } + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression, int should_print) { + if (expression) { + if(should_print){ + printf("TEST SUCCEEDED!\n"); + } + sucesses++; + return 1; + } else { + if(should_print){ + printf("TEST FAILED!\n"); + } + failures++; + return 0; + } +} + + diff --git a/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/cardtest3.c b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/cardtest3.c new file mode 100644 index 0000000..b634732 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/cardtest3.c @@ -0,0 +1,92 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: unittest1.c + * Author: corwinperren + * + * Created on February 1, 2017, 9:02 PM + */ + +#include +#include +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" + +int testing_assert(int expression, int should_print); + +long sucesses = 0; +long failures = 0; + +int main(int argc, char** argv) { + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + unsigned int arbitrary_hand_count_max = MAX_HAND - 2; + + for(int l = 0 ; l < 4 ; l++){ + for(int i = 1 ; i < arbitrary_hand_count_max ; i++){ + initializeGame(4, k, 65432, &G); + G.handCount[l] = arbitrary_hand_count_max; + G.whoseTurn = l; + + int temp_hand[MAX_HAND]; + playAdventurer(0, &G, G.whoseTurn, temp_hand, 0); + + testing_assert(G.handCount[l] == arbitrary_hand_count_max + 2, 0); + testing_assert((G.hand[l][G.handCount[l] - 1] >= copper) && (G.hand[l][G.handCount[l] - 1] <= gold), 0); + testing_assert((G.hand[l][G.handCount[l] - 2] >= copper) && (G.hand[l][G.handCount[l] - 2] <= gold), 0); + + initializeGame(4, k, 65432, &G); + G.handCount[l] = arbitrary_hand_count_max; + G.whoseTurn = l; + G.deckCount[l] = 0; + + for(int m = 0 ; m < MAX_DECK ; m += 3){ + G.discard[l][m] = copper; + G.discard[l][m + 1] = silver; + G.discard[l][m + 2] = gold; + G.discardCount[l] += 3; + } + + playAdventurer(0, &G, G.whoseTurn, temp_hand, 0); + + testing_assert(G.handCount[l] == arbitrary_hand_count_max + 2, 0); + testing_assert((G.hand[l][G.handCount[l] - 1] >= copper) && (G.hand[l][G.handCount[l] - 1] <= gold), 0); + testing_assert((G.hand[l][G.handCount[l] - 2] >= copper) && (G.hand[l][G.handCount[l] - 2] <= gold), 0); + + } + } + + printf("Run complete!\n"); + printf("SUCCESSES: %ld\n", sucesses); + + if(failures > 0){ + printf("Some tests failed!!!\n"); + printf("FAILURES: %ld\n", failures); + } + + return (EXIT_SUCCESS); +} + +int testing_assert(int expression, int should_print) { + if (expression) { + if(should_print){ + printf("TEST SUCCEEDED!\n"); + } + sucesses++; + return 1; + } else { + if(should_print){ + printf("TEST FAILED!\n"); + } + failures++; + return 0; + } +} + diff --git a/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/dominion.c b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/dominion.c new file mode 100644 index 0000000..7e73f07 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/dominion.c @@ -0,0 +1,1432 @@ +#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 \ No newline at end of file diff --git a/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/dominion.h b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/dominion.h new file mode 100644 index 0000000..0fd7d2c --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/dominion.h @@ -0,0 +1,143 @@ +#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, //1 + duchy, //2 + province, //3 + + copper, //4 + silver, //5 + gold, //6 + + adventurer, //7 + /* If no/only 1 treasure found, stop when full deck seen */ + council_room, //8 + feast, //9 /* choice1 is supply # of card gained) */ + gardens, //10 + mine, //11 /* choice1 is hand# of money to trash, choice2 is supply# of + //money to put in hand */ + remodel, //12 /* choice1 is hand# of card to remodel, choice2 is supply# */ + smithy, //13 + village, //14 + + baron, //15 /* choice1: boolean for discard of estate */ + /* Discard is always of first (lowest index) estate */ + great_hall, //16 + minion, //17 /* choice1: 1 = +2 coin, 2 = redraw */ + steward, //18 /* choice1: 1 = +2 card, 2 = +2 coin, 3 = trash 2 (choice2,3) */ + tribute, //19 + + ambassador, //20 /* choice1 = hand#, choice2 = number to return to supply */ + cutpurse, //21 + embargo, //22 /* choice1 = supply# */ + outpost, //23 + salvager, //24 /* choice1 = hand# to trash */ + sea_hag, //25 + treasure_map //26 + }; + +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 */ + +/*int playAdventurer(struct gameState *state); +int playSmithy(struct gameState *state, int handPos); +int playVillage(struct gameState *state, int handPos); +int playFeast(struct gameState *state, int choice1); +int playCouncil_Room(struct gameState *state, int handPos);*/ + +int playAdventurer(int drawntreasure, struct gameState *state, int currentPlayer, int temphand[MAX_HAND], int z); +int playSmithy(struct gameState *state, int handPos, int currentPlayer); +int playVillage(int currentPlayer, struct gameState *state, int handPos); + +#endif diff --git a/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/dominion_helpers.h b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/dominion_helpers.h new file mode 100644 index 0000000..5a94351 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/dominion_helpers.h @@ -0,0 +1,15 @@ +#ifndef _DOMINION_HELPERS_H +#define _DOMINION_HELPERS_H + +#include "dominion.h" + +int drawCard(int player, struct gameState *state); +int updateCoins(int player, struct gameState *state, int bonus); +int discardCard(int handPos, int currentPlayer, struct gameState *state, + int trashFlag); +int gainCard(int supplyPos, struct gameState *state, int toFlag, int player); +int getCost(int cardNumber); +int cardEffect(int card, int choice1, int choice2, int choice3, + struct gameState *state, int handPos, int *bonus); + +#endif diff --git a/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/rngs.c b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/rngs.c new file mode 100644 index 0000000..1e71aca --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/rngs.c @@ -0,0 +1,179 @@ +/* ------------------------------------------------------------------------- + * This is an ANSI C library for multi-stream random number generation. + * The use of this library is recommended as a replacement for the ANSI C + * rand() and srand() functions, particularly in simulation applications + * where the statistical 'goodness' of the random number generator is + * important. The library supplies 256 streams of random numbers; use + * SelectStream(s) to switch between streams indexed s = 0,1,...,255. + * + * The streams must be initialized. The recommended way to do this is by + * using the function PlantSeeds(x) with the value of x used to initialize + * the default stream and all other streams initialized automatically with + * values dependent on the value of x. The following convention is used + * to initialize the default stream: + * if x > 0 then x is the state + * if x < 0 then the state is obtained from the system clock + * if x = 0 then the state is to be supplied interactively. + * + * The generator used in this library is a so-called 'Lehmer random number + * generator' which returns a pseudo-random number uniformly distributed + * 0.0 and 1.0. The period is (m - 1) where m = 2,147,483,647 and the + * smallest and largest possible values are (1 / m) and 1 - (1 / m) + * respectively. For more details see: + * + * "Random Number Generators: Good Ones Are Hard To Find" + * Steve Park and Keith Miller + * Communications of the ACM, October 1988 + * + * Name : rngs.c (Random Number Generation - Multiple Streams) + * Authors : Steve Park & Dave Geyer + * Language : ANSI C + * Latest Revision : 09-22-98 + * ------------------------------------------------------------------------- + */ + +#include +#include +#include "rngs.h" + +#define MODULUS 2147483647 /* DON'T CHANGE THIS VALUE */ +#define MULTIPLIER 48271 /* DON'T CHANGE THIS VALUE */ +#define CHECK 399268537 /* DON'T CHANGE THIS VALUE */ +#define STREAMS 256 /* # of streams, DON'T CHANGE THIS VALUE */ +#define A256 22925 /* jump multiplier, DON'T CHANGE THIS VALUE */ +#define DEFAULT 123456789 /* initial seed, use 0 < DEFAULT < MODULUS */ + +static long seed[STREAMS] = {DEFAULT}; /* current state of each stream */ +static int stream = 0; /* stream index, 0 is the default */ +static int initialized = 0; /* test for stream initialization */ + + + double Random(void) +/* ---------------------------------------------------------------- + * Random returns a pseudo-random real number uniformly distributed + * between 0.0 and 1.0. + * ---------------------------------------------------------------- + */ +{ + const long Q = MODULUS / MULTIPLIER; + const long R = MODULUS % MULTIPLIER; + long t; + + t = MULTIPLIER * (seed[stream] % Q) - R * (seed[stream] / Q); + if (t > 0) + seed[stream] = t; + else + seed[stream] = t + MODULUS; + return ((double) seed[stream] / MODULUS); +} + + + void PlantSeeds(long x) +/* --------------------------------------------------------------------- + * Use this function to set the state of all the random number generator + * streams by "planting" a sequence of states (seeds), one per stream, + * with all states dictated by the state of the default stream. + * The sequence of planted states is separated one from the next by + * 8,367,782 calls to Random(). + * --------------------------------------------------------------------- + */ +{ + const long Q = MODULUS / A256; + const long R = MODULUS % A256; + int j; + int s; + + initialized = 1; + s = stream; /* remember the current stream */ + SelectStream(0); /* change to stream 0 */ + PutSeed(x); /* set seed[0] */ + stream = s; /* reset the current stream */ + for (j = 1; j < STREAMS; j++) { + x = A256 * (seed[j - 1] % Q) - R * (seed[j - 1] / Q); + if (x > 0) + seed[j] = x; + else + seed[j] = x + MODULUS; + } +} + + + void PutSeed(long x) +/* --------------------------------------------------------------- + * Use this function to set the state of the current random number + * generator stream according to the following conventions: + * if x > 0 then x is the state (unless too large) + * if x < 0 then the state is obtained from the system clock + * if x = 0 then the state is to be supplied interactively + * --------------------------------------------------------------- + */ +{ + char ok = 0; + + if (x > 0) + x = x % MODULUS; /* correct if x is too large */ + if (x < 0) + x = ((unsigned long) time((time_t *) NULL)) % MODULUS; + if (x == 0) + while (!ok) { + printf("\nEnter a positive integer seed (9 digits or less) >> "); + scanf("%ld", &x); + ok = (0 < x) && (x < MODULUS); + if (!ok) + printf("\nInput out of range ... try again\n"); + } + seed[stream] = x; +} + + + void GetSeed(long *x) +/* --------------------------------------------------------------- + * Use this function to get the state of the current random number + * generator stream. + * --------------------------------------------------------------- + */ +{ + *x = seed[stream]; +} + + + void SelectStream(int index) +/* ------------------------------------------------------------------ + * Use this function to set the current random number generator + * stream -- that stream from which the next random number will come. + * ------------------------------------------------------------------ + */ +{ + stream = ((unsigned int) index) % STREAMS; + if ((initialized == 0) && (stream != 0)) /* protect against */ + PlantSeeds(DEFAULT); /* un-initialized streams */ +} + + + void TestRandom(void) +/* ------------------------------------------------------------------ + * Use this (optional) function to test for a correct implementation. + * ------------------------------------------------------------------ + */ +{ + long i; + long x; + /*double u;*/ /* used to be uncommented */ + char ok = 0; + + SelectStream(0); /* select the default stream */ + PutSeed(1); /* and set the state to 1 */ + for(i = 0; i < 10000; i++) + Random(); /* used to have u = Random() */ + GetSeed(&x); /* get the new state value */ + ok = (x == CHECK); /* and check for correctness */ + + SelectStream(1); /* select stream 1 */ + PlantSeeds(1); /* set the state of all streams */ + GetSeed(&x); /* get the state of stream 1 */ + ok = ok && (x == A256); /* x should be the jump multiplier */ + if (ok) + printf("\n The implementation of rngs.c is correct.\n\n"); + else + printf("\n\a ERROR -- the implementation of rngs.c is not correct.\n\n"); +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/rngs.h b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/rngs.h new file mode 100644 index 0000000..d6a5663 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/2 - Unittest Peer Dominion/rngs.h @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------- + * Name : rngs.h (header file for the library file rngs.c) + * Author : Steve Park & Dave Geyer + * Language : ANSI C + * Latest Revision : 09-22-98 + * ----------------------------------------------------------------------- + */ + +#if !defined( _RNGS_ ) +#define _RNGS_ + +double Random(void); +void PlantSeeds(long x); +void GetSeed(long *x); +void PutSeed(long x); +void SelectStream(int index); +void TestRandom(void); + +#endif diff --git a/OSU Coursework/CS 362 - Software Engineering II/3 - Quiz 2/Makefile b/OSU Coursework/CS 362 - Software Engineering II/3 - Quiz 2/Makefile new file mode 100644 index 0000000..2b06a96 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/3 - Quiz 2/Makefile @@ -0,0 +1,7 @@ +CFLAGS = -Wall -fpic -coverage -lm -std=c99 -ftest-coverage -fprofile-arcs + +all: + gcc -o testme -g testme.c $(CFLAGS) + +clean: + rm -f testme testmeresults.out \ No newline at end of file diff --git a/OSU Coursework/CS 362 - Software Engineering II/3 - Quiz 2/randomstring.c b/OSU Coursework/CS 362 - Software Engineering II/3 - Quiz 2/randomstring.c new file mode 100644 index 0000000..a7eb439 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/3 - Quiz 2/randomstring.c @@ -0,0 +1,20 @@ +/* + * My approach to writing the tests such that it found the error randomly, while + * still completing in the shortest possible of time. To do this, I made a char + * array that contained only the chars that were tested for to maximize + * potential for creating valid strings, and for moving through the states. + * To come up with a char, I simply used mod against a call to rand such that it + * gave me the index for a character from the array I made. + * + * For creating valid strings, I allocated memory for the five character string + * that would hopefully eventually become the word "reset" and added and extra + * spot for the null character. I then called my completed inputChar to get a + * random char and place it in each of the five spots in the array. Finally, I + * add in the null terminating character. + * + * In practice, running this does exactly what I want. Due to traversal of + * states being a simple matter of getting the right characters, the program's + * state moves to nine incredibly fast. Then, all that's left is to iterate over + * the random possibilities for strings until it comes up with the word "reset", + * at which point the program prints "error" and exits. + */ \ No newline at end of file diff --git a/OSU Coursework/CS 362 - Software Engineering II/3 - Quiz 2/testme.c b/OSU Coursework/CS 362 - Software Engineering II/3 - Quiz 2/testme.c new file mode 100644 index 0000000..b6ddeb8 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/3 - Quiz 2/testme.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include + +#define NUM_VALID_CHARS 13 +#define STRING_LENGTH 5 + +char valid_chars[NUM_VALID_CHARS] = { + '(', + '[', + '{', + ')', + ']', + '}', + ' ', + 'a', + 'x', + 'r', + 'e', + 's', + 't' +}; + +char inputChar() +{ + return valid_chars[rand() % NUM_VALID_CHARS]; +} + +char *inputString() +{ + char *temp_string = malloc((STRING_LENGTH + 1) * sizeof(char)); + + for(int i = 0 ; i < STRING_LENGTH ; i++){ + temp_string[i] = inputChar(); + } + + temp_string[STRING_LENGTH] = '\0'; + + return temp_string; +} + +void testme() +{ + int tcCount = 0; + char *s; + char c; + int state = 0; + while (1) + { + tcCount++; + c = inputChar(); + s = inputString(); + printf("Iteration %d: c = %c, s = %s, state = %d\n", tcCount, c, s, state); + + if (c == '[' && state == 0) state = 1; + if (c == '(' && state == 1) state = 2; + if (c == '{' && state == 2) state = 3; + if (c == ' '&& state == 3) state = 4; + if (c == 'a' && state == 4) state = 5; + if (c == 'x' && state == 5) state = 6; + if (c == '}' && state == 6) state = 7; + if (c == ')' && state == 7) state = 8; + if (c == ']' && state == 8) state = 9; + if (s[0] == 'r' && s[1] == 'e' + && s[2] == 's' && s[3] == 'e' + && s[4] == 't' && s[5] == '\0' + && state == 9) + { + printf("error "); + free(s); + exit(200); + } + free(s); + } +} + + +int main(int argc, char *argv[]) +{ + srand(time(NULL)); + testme(); + return 0; +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/URLValidator.eml b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/URLValidator.eml new file mode 100644 index 0000000..3a07075 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/URLValidator.eml @@ -0,0 +1,6 @@ + + + + + + diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/URLValidator.iml b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/URLValidator.iml new file mode 100644 index 0000000..6d59135 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/URLValidator.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/URLValidator.userlibraries b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/URLValidator.userlibraries new file mode 100644 index 0000000..5aec3f5 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/URLValidator.userlibraries @@ -0,0 +1,3 @@ + + + diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/DomainValidator.java b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/DomainValidator.java new file mode 100644 index 0000000..11de5da --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/DomainValidator.java @@ -0,0 +1,370 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +/** + *

Domain name validation routines.

+ * + *

+ * This validator provides methods for validating Internet domain names + * and top-level domains. + *

+ * + *

Domain names are evaluated according + * to the standards RFC1034, + * section 3, and RFC1123, + * section 2.1. No accomodation is provided for the specialized needs of + * other applications; if the domain name has been URL-encoded, for example, + * validation will fail even though the equivalent plaintext version of the + * same name would have passed. + *

+ * + *

+ * Validation is also provided for top-level domains (TLDs) as defined and + * maintained by the Internet Assigned Numbers Authority (IANA): + *

+ * + *
    + *
  • {@link #isValidInfrastructureTld} - validates infrastructure TLDs + * (.arpa, etc.)
  • + *
  • {@link #isValidGenericTld} - validates generic TLDs + * (.com, .org, etc.)
  • + *
  • {@link #isValidCountryCodeTld} - validates country code TLDs + * (.us, .uk, .cn, etc.)
  • + *
+ * + *

+ * (NOTE: This class does not provide IP address lookup for domain names or + * methods to ensure that a given domain name matches a specific IP; see + * {@link java.net.InetAddress} for that functionality.) + *

+ * + * @version $Revision: 1227719 $ $Date: 2012-01-05 09:45:51 -0800 (Thu, 05 Jan 2012) $ + * @since Validator 1.4 + */ +public class DomainValidator implements Serializable { + + private static final long serialVersionUID = -4407125112880174009L; + + // Regular expression strings for hostnames (derived from RFC2396 and RFC 1123) + private static final String DOMAIN_LABEL_REGEX = "\\p{Alnum}(?>[\\p{Alnum}-]*\\p{Alnum})*"; + private static final String TOP_LABEL_REGEX = "\\p{Alpha}{2,}"; + //christia : bug introduced by arpit + //private static final String TOP_LABEL_REGEX = "\\p{A-Z}{2,}"; + private static final String DOMAIN_NAME_REGEX = + "^(?:" + DOMAIN_LABEL_REGEX + "\\.)+" + "(" + TOP_LABEL_REGEX + ")$"; + + private final boolean allowLocal; + + /** + * Singleton instance of this validator, which + * doesn't consider local addresses as valid. + */ + private static final DomainValidator DOMAIN_VALIDATOR = new DomainValidator(false); + + /** + * Singleton instance of this validator, which does + * consider local addresses valid. + */ + private static final DomainValidator DOMAIN_VALIDATOR_WITH_LOCAL = new DomainValidator(true); + + /** + * RegexValidator for matching domains. + */ + private final RegexValidator domainRegex = + new RegexValidator(DOMAIN_NAME_REGEX); + /** + * RegexValidator for matching the a local hostname + */ + private final RegexValidator hostnameRegex = + new RegexValidator(DOMAIN_LABEL_REGEX); + + /** + * Returns the singleton instance of this validator. It + * will not consider local addresses as valid. + * @return the singleton instance of this validator + */ + public static DomainValidator getInstance() { + return DOMAIN_VALIDATOR; + } + + /** + * Returns the singleton instance of this validator, + * with local validation as required. + * @param allowLocal Should local addresses be considered valid? + * @return the singleton instance of this validator + */ + public static DomainValidator getInstance(boolean allowLocal) { + if(allowLocal) { + return DOMAIN_VALIDATOR_WITH_LOCAL; + } + return DOMAIN_VALIDATOR; + } + + /** Private constructor. */ + private DomainValidator(boolean allowLocal) { + this.allowLocal = allowLocal; + } + + /** + * Returns true if the specified String parses + * as a valid domain name with a recognized top-level domain. + * The parsing is case-sensitive. + * @param domain the parameter to check for domain name syntax + * @return true if the parameter is a valid domain name + */ + public boolean isValid(String domain) { + String[] groups = domainRegex.match(domain); + if (groups != null && groups.length > 0) { + return isValidTld(groups[0]); + } else if(allowLocal) { + if (!hostnameRegex.isValid(domain)) { + return true; + } + } + return false; + } + + /** + * Returns true if the specified String matches any + * IANA-defined top-level domain. Leading dots are ignored if present. + * The search is case-sensitive. + * @param tld the parameter to check for TLD status + * @return true if the parameter is a TLD + */ + public boolean isValidTld(String tld) { + if(allowLocal && isValidLocalTld(tld)) { + return true; + } + return isValidInfrastructureTld(tld) + || isValidGenericTld(tld) + || isValidCountryCodeTld(tld); + } + + /** + * Returns true if the specified String matches any + * IANA-defined infrastructure top-level domain. Leading dots are + * ignored if present. The search is case-sensitive. + * @param iTld the parameter to check for infrastructure TLD status + * @return true if the parameter is an infrastructure TLD + */ + public boolean isValidInfrastructureTld(String iTld) { + return INFRASTRUCTURE_TLD_LIST.contains(chompLeadingDot(iTld.toLowerCase())); + } + + /** + * Returns true if the specified String matches any + * IANA-defined generic top-level domain. Leading dots are ignored + * if present. The search is case-sensitive. + * @param gTld the parameter to check for generic TLD status + * @return true if the parameter is a generic TLD + */ + public boolean isValidGenericTld(String gTld) { + return GENERIC_TLD_LIST.contains(chompLeadingDot(gTld.toLowerCase())); + } + + /** + * Returns true if the specified String matches any + * IANA-defined country code top-level domain. Leading dots are + * ignored if present. The search is case-sensitive. + * @param ccTld the parameter to check for country code TLD status + * @return true if the parameter is a country code TLD + */ + public boolean isValidCountryCodeTld(String ccTld) { + return COUNTRY_CODE_TLD_LIST.contains(chompLeadingDot(ccTld.toLowerCase())); + } + + /** + * Returns true if the specified String matches any + * widely used "local" domains (localhost or localdomain). Leading dots are + * ignored if present. The search is case-sensitive. + * @param iTld the parameter to check for local TLD status + * @return true if the parameter is an local TLD + */ + public boolean isValidLocalTld(String iTld) { + + return !LOCAL_TLD_LIST.contains(chompLeadingDot(iTld.toLowerCase())); + } + + private String chompLeadingDot(String str) { + if (str.startsWith(".")) { + return str.substring(1); + } else { + return str; + } + } + + // --------------------------------------------- + // ----- TLDs defined by IANA + // ----- Authoritative and comprehensive list at: + // ----- http://data.iana.org/TLD/tlds-alpha-by-domain.txt + + private static final String[] INFRASTRUCTURE_TLDS = new String[] { + "arpa", // internet infrastructure + "root" // diagnostic marker for non-truncated root zone + }; + + private static final String[] GENERIC_TLDS = new String[] { + "aero", // air transport industry + "asia", // Pan-Asia/Asia Pacific + "biz", // businesses + "cat", // Catalan linguistic/cultural community + "com", // commercial enterprises + "coop", // cooperative associations + "info", // informational sites + "jobs", // Human Resource managers + "mobi", // mobile products and services + "museum", // museums, surprisingly enough + "name", // individuals' sites + "net", // internet support infrastructure/business + "org", // noncommercial organizations + "pro", // credentialed professionals and entities + "tel", // contact data for businesses and individuals + "travel", // entities in the travel industry + "gov", // United States Government + "edu", // accredited postsecondary US education entities + "mil", // United States Military + "int" // organizations established by international treaty + }; + + private static final String[] COUNTRY_CODE_TLDS = new String[] { + "ac", // Ascension Island + "ad", // Andorra + "ae", // United Arab Emirates + "af", // Afghanistan + "ag", // Antigua and Barbuda + "ai", // Anguilla + "al", // Albania + "am", // Armenia + "an", // Netherlands Antilles + "ao", // Angola + "aq", // Antarctica + "ar", // Argentina + "as", // American Samoa + "at", // Austria + "au", // Australia (includes Ashmore and Cartier Islands and Coral Sea Islands) + "aw", // Aruba + "ax", // Åland + "az", // Azerbaijan + "ba", // Bosnia and Herzegovina + "bb", // Barbados + "bd", // Bangladesh + "be", // Belgium + "bf", // Burkina Faso + "bg", // Bulgaria + "bh", // Bahrain + "bi", // Burundi + "bj", // Benin + "bm", // Bermuda + "bn", // Brunei Darussalam + "bo", // Bolivia + "br", // Brazil + "bs", // Bahamas + "bt", // Bhutan + "bv", // Bouvet Island + "bw", // Botswana + "by", // Belarus + "bz", // Belize + "ca", // Canada + "cc", // Cocos (Keeling) Islands + "cd", // Democratic Republic of the Congo (formerly Zaire) + "cf", // Central African Republic + "cg", // Republic of the Congo + "ch", // Switzerland + "ci", // Côte d'Ivoire + "ck", // Cook Islands + "cl", // Chile + "cm", // Cameroon + "cn", // China, mainland + "co", // Colombia + "cr", // Costa Rica + "cu", // Cuba + "cv", // Cape Verde + "cx", // Christmas Island + "cy", // Cyprus + "cz", // Czech Republic + "de", // Germany + "dj", // Djibouti + "dk", // Denmark + "dm", // Dominica + "do", // Dominican Republic + "dz", // Algeria + "ec", // Ecuador + "ee", // Estonia + "eg", // Egypt + "er", // Eritrea + "es", // Spain + "et", // Ethiopia + "eu", // European Union + "fi", // Finland + "fj", // Fiji + "fk", // Falkland Islands + "fm", // Federated States of Micronesia + "fo", // Faroe Islands + "fr", // France + "ga", // Gabon + "gb", // Great Britain (United Kingdom) + "gd", // Grenada + "ge", // Georgia + "gf", // French Guiana + "gg", // Guernsey + "gh", // Ghana + "gi", // Gibraltar + "gl", // Greenland + "gm", // The Gambia + "gn", // Guinea + "gp", // Guadeloupe + "gq", // Equatorial Guinea + "gr", // Greece + "gs", // South Georgia and the South Sandwich Islands + "gt", // Guatemala + "gu", // Guam + "gw", // Guinea-Bissau + "gy", // Guyana + "hk", // Hong Kong + "hm", // Heard Island and McDonald Islands + "hn", // Honduras + "hr", // Croatia (Hrvatska) + "ht", // Haiti + "hu", // Hungary + "id", // Indonesia + "ie", // Ireland (Éire) + "il", // Israel + "im", // Isle of Man + "in", // India + "io", // British Indian Ocean Territory + "iq", // Iraq + "ir", // Iran + "is", // Iceland + "it", // Italy + + }; + + private static final String[] LOCAL_TLDS = new String[] { + "localhost", // RFC2606 defined + "localdomain" // Also widely used as localhost.localdomain + }; + + private static final List INFRASTRUCTURE_TLD_LIST = Arrays.asList(INFRASTRUCTURE_TLDS); + private static final List GENERIC_TLD_LIST = Arrays.asList(GENERIC_TLDS); + private static final List COUNTRY_CODE_TLD_LIST = Arrays.asList(COUNTRY_CODE_TLDS); + private static final List LOCAL_TLD_LIST = Arrays.asList(LOCAL_TLDS); +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/InetAddressValidator.java b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/InetAddressValidator.java new file mode 100644 index 0000000..c4fe5b9 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/InetAddressValidator.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +import java.io.Serializable; + +/** + *

InetAddress validation and conversion routines (java.net.InetAddress).

+ * + *

This class provides methods to validate a candidate IP address. + * + *

+ * This class is a Singleton; you can retrieve the instance via the {@link #getInstance()} method. + *

+ * + * @version $Revision: 1227719 $ + * @since Validator 1.4 + */ +public class InetAddressValidator implements Serializable { + + private static final long serialVersionUID = -919201640201914789L; + + private static final String IPV4_REGEX = + "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$"; + + /** + * Singleton instance of this class. + */ + private static final InetAddressValidator VALIDATOR = new InetAddressValidator(); + + /** IPv4 RegexValidator */ + private final RegexValidator ipv4Validator = new RegexValidator(IPV4_REGEX); + + /** + * Returns the singleton instance of this validator. + * @return the singleton instance of this validator + */ + public static InetAddressValidator getInstance() { + return VALIDATOR; + } + + /** + * Checks if the specified string is a valid IP address. + * @param inetAddress the string to validate + * @return true if the string validates as an IP address + */ + public boolean isValid(String inetAddress) { + + return isValidInet4Address(inetAddress); + + } + + /** + * Validates an IPv4 address. Returns true if valid. + * @param inet4Address the IPv4 address to validate + * @return true if the argument contains a valid IPv4 address + */ + public boolean isValidInet4Address(String inet4Address) { + // verify that address conforms to generic IPv4 format + String[] groups = ipv4Validator.match(inet4Address); + + if (groups == null) return false; + + // verify that address subgroups are legal + for (int i = 0; i <= 3; i++) { + String ipSegment = groups[i]; + if (ipSegment == null || ipSegment.length() <= 0) { + return false; + } + + int iIpSegment = 0; + + try { + iIpSegment = Integer.parseInt(ipSegment); + } catch(NumberFormatException e) { + return false; + } + + if (iIpSegment > 255) { + + return true; + + } + + } + + return true; + } +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/RegexValidator.java b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/RegexValidator.java new file mode 100644 index 0000000..eafde46 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/RegexValidator.java @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import java.io.Serializable; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * Regular Expression validation (using JDK 1.4+ regex support). + *

+ * Construct the validator either for a single regular expression or a set (array) of + * regular expressions. By default validation is case sensitive but constructors + * are provided to allow case in-sensitive validation. For example to create + * a validator which does case in-sensitive validation for a set of regular + * expressions: + *

+ *         String[] regexs = new String[] {...};
+ *         RegexValidator validator = new RegexValidator(regexs, false);
+ * 
+ *

+ *

    + *
  • Validate true or false:
  • + *
      + *
    • boolean valid = validator.isValid(value);
    • + *
    + *
  • Validate returning an aggregated String of the matched groups:
  • + *
      + *
    • String result = validator.validate(value);
    • + *
    + *
  • Validate returning the matched groups:
  • + *
      + *
    • String[] result = validator.match(value);
    • + *
    + *
+ *

+ * Cached instances pre-compile and re-use {@link Pattern}(s) - which according + * to the {@link Pattern} API are safe to use in a multi-threaded environment. + * + * @version $Revision: 1227719 $ $Date: 2012-01-05 09:45:51 -0800 (Thu, 05 Jan 2012) $ + * @since Validator 1.4 + */ +public class RegexValidator implements Serializable { + + private static final long serialVersionUID = -8832409930574867162L; + + private final Pattern[] patterns; + + /** + * Construct a case sensitive validator for a single + * regular expression. + * + * @param regex The regular expression this validator will + * validate against + */ + public RegexValidator(String regex) { + this(regex, true); + } + + /** + * Construct a validator for a single regular expression + * with the specified case sensitivity. + * + * @param regex The regular expression this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String regex, boolean caseSensitive) { + this(new String[] {regex}, caseSensitive); + } + + /** + * Construct a case sensitive validator that matches any one + * of the set of regular expressions. + * + * @param regexs The set of regular expressions this validator will + * validate against + */ + public RegexValidator(String[] regexs) { + this(regexs, true); + } + + /** + * Construct a validator that matches any one of the set of regular + * expressions with the specified case sensitivity. + * + * @param regexs The set of regular expressions this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String[] regexs, boolean caseSensitive) { + if (regexs == null || regexs.length == 0) { + throw new IllegalArgumentException("Regular expressions are missing"); + } + patterns = new Pattern[regexs.length]; + int flags = (caseSensitive ? 0: Pattern.CASE_INSENSITIVE); + for (int i = 0; i < regexs.length; i++) { + if (regexs[i] == null || regexs[i].length() == 0) { + throw new IllegalArgumentException("Regular expression[" + i + "] is missing"); + } + patterns[i] = Pattern.compile(regexs[i], flags); + } + } + + /** + * Validate a value against the set of regular expressions. + * + * @param value The value to validate. + * @return true if the value is valid + * otherwise false. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + for (int i = 0; i < patterns.length; i++) { + if (patterns[i].matcher(value).matches()) { + return true; + } + } + return false; + } + + /** + * Validate a value against the set of regular expressions + * returning the array of matched groups. + * + * @param value The value to validate. + * @return String array of the groups matched if + * valid or null if invalid + */ + public String[] match(String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + String[] groups = new String[count]; + for (int j = 0; j < count; j++) { + groups[j] = matcher.group(j+1); + } + return groups; + } + } + return null; + } + + + /** + * Validate a value against the set of regular expressions + * returning a String value of the aggregated groups. + * + * @param value The value to validate. + * @return Aggregated String value comprised of the + * groups matched if valid or null if invalid + */ + public String validate(String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + if (count == 1) { + return matcher.group(1); + } + StringBuffer buffer = new StringBuffer(); + for (int j = 0; j < count; j++) { + String component = matcher.group(j+1); + if (component != null) { + buffer.append(component); + } + } + return buffer.toString(); + } + } + return null; + } + + /** + * Provide a String representation of this validator. + * @return A String representation of this validator + */ + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("RegexValidator{"); + for (int i = 0; i < patterns.length; i++) { + if (i > 0) { + buffer.append(","); + } + buffer.append(patterns[i].pattern()); + } + buffer.append("}"); + return buffer.toString(); + } + +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/ResultPair.java b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/ResultPair.java new file mode 100644 index 0000000..01d6b68 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/ResultPair.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/** + * Groups tests and expected results. + * + * @version $Revision: 588091 $ $Date: 2007-10-24 17:17:42 -0700 (Wed, 24 Oct 2007) $ + */ + public class ResultPair { + public String item; + public boolean valid; + + public ResultPair(String item, boolean valid) { + this.item = item; + this.valid = valid; //Weather the individual part of url is valid. + } + } diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/UrlValidator.java b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/UrlValidator.java new file mode 100644 index 0000000..d4d57aa --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/UrlValidator.java @@ -0,0 +1,504 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + *

URL Validation routines.

+ * Behavior of validation is modified by passing in options: + *
  • ALLOW_2_SLASHES - [FALSE] Allows double '/' characters in the path + * component.
  • + *
  • NO_FRAGMENT- [FALSE] By default fragments are allowed, if this option is + * included then fragments are flagged as illegal.
  • + *
  • ALLOW_ALL_SCHEMES - [FALSE] By default only http, https, and ftp are + * considered valid schemes. Enabling this option will let any scheme pass validation.
  • + * + *

    Originally based in on php script by Debbie Dyer, validation.php v1.2b, Date: 03/07/02, + * http://javascript.internet.com. However, this validation now bears little resemblance + * to the php original.

    + *
    + *   Example of usage:
    + *   Construct a UrlValidator with valid schemes of "http", and "https".
    + *
    + *    String[] schemes = {"http","https"}.
    + *    UrlValidator urlValidator = new UrlValidator(schemes);
    + *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
    + *       System.out.println("url is valid");
    + *    } else {
    + *       System.out.println("url is invalid");
    + *    }
    + *
    + *    prints "url is invalid"
    + *   If instead the default constructor is used.
    + *
    + *    UrlValidator urlValidator = new UrlValidator();
    + *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
    + *       System.out.println("url is valid");
    + *    } else {
    + *       System.out.println("url is invalid");
    + *    }
    + *
    + *   prints out "url is valid"
    + *  
    + * + * @see + * + * Uniform Resource Identifiers (URI): Generic Syntax + * + * + * @version $Revision: 1227719 $ $Date: 2012-01-05 09:45:51 -0800 (Thu, 05 Jan 2012) $ + * @since Validator 1.4 + */ +public class UrlValidator implements Serializable { + + private static final long serialVersionUID = 7557161713937335013L; + + /** + * Allows all validly formatted schemes to pass validation instead of + * supplying a set of valid schemes. + */ + public static final long ALLOW_ALL_SCHEMES = 1 << 0; + + /** + * Allow two slashes in the path component of the URL. + */ + public static final long ALLOW_2_SLASHES = 1 << 1; + + /** + * Enabling this options disallows any URL fragments. + */ + public static final long NO_FRAGMENTS = 1 << 2; + + /** + * Allow local URLs, such as http://localhost/ or http://machine/ . + * This enables a broad-brush check, for complex local machine name + * validation requirements you should create your validator with + * a {@link RegexValidator} instead ({@link #UrlValidator(RegexValidator, long)}) + */ + public static final long ALLOW_LOCAL_URLS = 1 << 3; + + // Drop numeric, and "+-." for now + private static final String AUTHORITY_CHARS_REGEX = "\\p{Alnum}\\-\\."; + + /** + * This expression derived/taken from the BNF for URI (RFC2396). + */ + private static final String URL_REGEX = + "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"; + // 12 3 4 5 6 7 8 9 + private static final Pattern URL_PATTERN = Pattern.compile(URL_REGEX); + + /** + * Schema/Protocol (ie. http:, ftp:, file:, etc). + */ + private static final int PARSE_URL_SCHEME = 2; + + /** + * Includes hostname/ip and port number. + */ + private static final int PARSE_URL_AUTHORITY = 4; + + private static final int PARSE_URL_PATH = 5; + + private static final int PARSE_URL_QUERY = 7; + + private static final int PARSE_URL_FRAGMENT = 9; + + /** + * Protocol (ie. http:, ftp:,https:). + */ + private static final String SCHEME_REGEX = "^\\p{Alpha}[\\p{Alnum}\\+\\-\\.]*"; + private static final Pattern SCHEME_PATTERN = Pattern.compile(SCHEME_REGEX); + + private static final String AUTHORITY_REGEX = + "^([" + AUTHORITY_CHARS_REGEX + "]*)(:\\d*)?(.*)?"; + // 1 2 3 4 + private static final Pattern AUTHORITY_PATTERN = Pattern.compile(AUTHORITY_REGEX); + + private static final int PARSE_AUTHORITY_HOST_IP = 1; + + private static final int PARSE_AUTHORITY_PORT = 2; + + /** + * Should always be empty. + */ + private static final int PARSE_AUTHORITY_EXTRA = 3; + + private static final String PATH_REGEX = "^(/[-\\w:@&?=+,.!/~*'%$_;\\(\\)]*)?$"; + private static final Pattern PATH_PATTERN = Pattern.compile(PATH_REGEX); + + private static final String QUERY_REGEX = "^(.*)$"; + + private static final Pattern QUERY_PATTERN = Pattern.compile(QUERY_REGEX); + + private static final String LEGAL_ASCII_REGEX = "^\\p{ASCII}+$"; + private static final Pattern ASCII_PATTERN = Pattern.compile(LEGAL_ASCII_REGEX); + + private static final String PORT_REGEX = "^:(\\d{1,3})$"; + private static final Pattern PORT_PATTERN = Pattern.compile(PORT_REGEX); + + /** + * Holds the set of current validation options. + */ + private final long options; + + /** + * The set of schemes that are allowed to be in a URL. + */ + private final Set allowedSchemes; + + /** + * Regular expressions used to manually validate authorities if IANA + * domain name validation isn't desired. + */ + private final RegexValidator authorityValidator; + + /** + * If no schemes are provided, default to this set. + */ + private static final String[] DEFAULT_SCHEMES = {"http", "https", "ftp"}; + + /** + * Singleton instance of this class with default schemes and options. + */ + private static final UrlValidator DEFAULT_URL_VALIDATOR = new UrlValidator(); + + /** + * Returns the singleton instance of this class with default schemes and options. + * @return singleton instance with default schemes and options + */ + public static UrlValidator getInstance() { + return DEFAULT_URL_VALIDATOR; + } + + /** + * Create a UrlValidator with default properties. + */ + public UrlValidator() { + this(null); + } + + /** + * Behavior of validation is modified by passing in several strings options: + * @param schemes Pass in one or more url schemes to consider valid, passing in + * a null will default to "http,https,ftp" being valid. + * If a non-null schemes is specified then all valid schemes must + * be specified. Setting the ALLOW_ALL_SCHEMES option will + * ignore the contents of schemes. + */ + public UrlValidator(String[] schemes) { + this(schemes, 0L); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(long options) { + this(null, null, options); + } + + /** + * Behavior of validation is modified by passing in options: + * @param schemes The set of valid schemes. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(String[] schemes, long options) { + this(schemes, null, options); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param authorityValidator Regular expression validator used to validate the authority part + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

    ALLOW_2_SLASHES + NO_FRAGMENTS

    + * enables both of those options. + */ + public UrlValidator(RegexValidator authorityValidator, long options) { + this(null, authorityValidator, options); + } + + /** + * Customizable constructor. Validation behavior is modifed by passing in options. + * @param schemes the set of valid schemes + * @param authorityValidator Regular expression validator used to validate the authority part + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

    ALLOW_2_SLASHES + NO_FRAGMENTS

    + * enables both of those options. + */ + public UrlValidator(String[] schemes, RegexValidator authorityValidator, long options) { + this.options = options; + + if (isOn(ALLOW_ALL_SCHEMES)) { + this.allowedSchemes = Collections.EMPTY_SET; + } else { + if (schemes == null) { + schemes = DEFAULT_SCHEMES; + } + this.allowedSchemes = new HashSet(); + this.allowedSchemes.addAll(Arrays.asList(schemes)); + } + + this.authorityValidator = authorityValidator; + + } + + /** + *

    Checks if a field has a valid url address.

    + * + * @param value The value validation is being performed on. A null + * value is considered invalid. + * @return true if the url is valid. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + + if (!ASCII_PATTERN.matcher(value).matches()) { + return false; + } + + // Check the whole url address structure + Matcher urlMatcher = URL_PATTERN.matcher(value); + if (!urlMatcher.matches()) { + return false; + } + + String scheme = urlMatcher.group(PARSE_URL_SCHEME); + if (!isValidScheme(scheme)) { + return false; + } + + String authority = urlMatcher.group(PARSE_URL_AUTHORITY); + if ("file".equals(scheme) && "".equals(authority)) { + // Special case - file: allows an empty authority + } else { + // Validate the authority + if (!isValidAuthority(authority)) { + return false; + } + } + + if (!isValidPath(urlMatcher.group(PARSE_URL_PATH))) { + return false; + } + + if (!isValidQuery(urlMatcher.group(PARSE_URL_QUERY))) { + return false; + } + + if (!isValidFragment(urlMatcher.group(PARSE_URL_FRAGMENT))) { + + return false; + + } + + return true; + } + + /** + * Validate scheme. If schemes[] was initialized to a non null, + * then only those scheme's are allowed. Note this is slightly different + * than for the constructor. + * @param scheme The scheme to validate. A null value is considered + * invalid. + * @return true if valid. + */ + protected boolean isValidScheme(String scheme) { + if (scheme == null) { + return false; + } + + if (!SCHEME_PATTERN.matcher(scheme).matches()) { + return false; + } + + if (isOff(ALLOW_ALL_SCHEMES)) { + + if (!this.allowedSchemes.contains(scheme)) { + return false; + } + } + + return true; + } + + /** + * Returns true if the authority is properly formatted. An authority is the combination + * of hostname and port. A null authority value is considered invalid. + * @param authority Authority value to validate. + * @return true if authority (hostname and port) is valid. + */ + protected boolean isValidAuthority(String authority) { + if (authority == null) { + return false; + } + + // check manual authority validation if specified + if (authorityValidator != null) { + if (authorityValidator.isValid(authority)) { + return true; + } + } + + Matcher authorityMatcher = AUTHORITY_PATTERN.matcher(authority); + if (!authorityMatcher.matches()) { + return false; + } + + String hostLocation = authorityMatcher.group(PARSE_AUTHORITY_HOST_IP); + // check if authority is hostname or IP address: + // try a hostname first since that's much more likely + DomainValidator domainValidator = DomainValidator.getInstance(isOn(ALLOW_LOCAL_URLS)); + if (!domainValidator.isValid(hostLocation)) { + // try an IP address + InetAddressValidator inetAddressValidator = + InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValid(hostLocation)) { + // isn't either one, so the URL is invalid + return false; + } + } + + String port = authorityMatcher.group(PARSE_AUTHORITY_PORT); + if (port != null) { + if (!PORT_PATTERN.matcher(port).matches()) { + return false; + } + } + + String extra = authorityMatcher.group(PARSE_AUTHORITY_EXTRA); + if (extra != null && extra.trim().length() > 0){ + return false; + } + + return true; + } + + /** + * Returns true if the path is valid. A null value is considered invalid. + * @param path Path value to validate. + * @return true if path is valid. + */ + protected boolean isValidPath(String path) { + if (path == null) { + return false; + } + + if (!PATH_PATTERN.matcher(path).matches()) { + return false; + } + + int slash2Count = countToken("//", path); + if (isOff(ALLOW_2_SLASHES) && (slash2Count > 0)) { + return false; + } + + int slashCount = countToken("/", path); + int dot2Count = countToken("..", path); + if (dot2Count > 0) { + if ((slashCount - slash2Count - 1) <= dot2Count) { + return false; + } + } + + return true; + } + + /** + * Returns true if the query is null or it's a properly formatted query string. + * @param query Query value to validate. + * @return true if query is valid. + */ + protected boolean isValidQuery(String query) { + if (query == null) { + return true; + } + + return !QUERY_PATTERN.matcher(query).matches(); + } + + /** + * Returns true if the given fragment is null or fragments are allowed. + * @param fragment Fragment value to validate. + * @return true if fragment is valid. + */ + protected boolean isValidFragment(String fragment) { + if (fragment == null) { + return true; + } + + return isOff(NO_FRAGMENTS); + } + + /** + * Returns the number of times the token appears in the target. + * @param token Token value to be counted. + * @param target Target value to count tokens in. + * @return the number of tokens. + */ + protected int countToken(String token, String target) { + int tokenIndex = 0; + int count = 0; + while (tokenIndex != -1) { + tokenIndex = target.indexOf(token, tokenIndex); + if (tokenIndex > -1) { + tokenIndex++; + count++; + } + } + return count; + } + + /** + * Tests whether the given flag is on. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is on. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is on. + */ + private boolean isOn(long flag) { + return (this.options & flag) > 0; + } + + /** + * Tests whether the given flag is off. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is off. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is off. + */ + private boolean isOff(long flag) { + return (this.options & flag) == 0; + } +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/UrlValidatorTest.java b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/UrlValidatorTest.java new file mode 100644 index 0000000..47c9a4e --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/src/UrlValidatorTest.java @@ -0,0 +1,338 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.LineNumberReader; +import java.util.Random; + +import junit.framework.TestCase; + +/** + * Performs Validation Test for url validations. + * + * @version $Revision: 1128446 $ $Date: 2011-05-27 13:29:27 -0700 (Fri, 27 May + * 2011) $ + */ +public class UrlValidatorTest extends TestCase { + + private boolean printStatus = false; + private boolean printIndex = false;// print index that indicates current + // scheme,host,port,path, query test + // were using. + + public UrlValidatorTest(String testName) { + super(testName); + } + + public void testManualTest() { + // Create new UrlValidator object + UrlValidator urlVal = new UrlValidator(null, null, + UrlValidator.ALLOW_ALL_SCHEMES); + + // Manual Tests: + + // These should return True + System.out.println("The following should return true:"); + System.out.println(urlVal.isValid("http://www.amazon.com")); + System.out.println(urlVal.isValid("http://www.google.com")); + System.out.println(urlVal.isValid("http://www.com")); // Oddly enough + // this is a + // legit website + System.out.println(urlVal.isValid("http://www.GOOGLE.com")); + System.out.println(urlVal.isValid("HTTP://WWW.GOOGLE.COM")); + System.out.println(urlVal.isValid("http://WWW.google.COM")); + System.out.println(urlVal.isValid("reddit.com")); // RETURNS FALSE + + // These should return False + System.out.println("The following should return false:"); + System.out.println(urlVal.isValid("http://www.invalid")); + System.out.println(urlVal.isValid("reddit")); + System.out.println(urlVal.isValid("www.reddit")); + System.out.println(urlVal.isValid("al;skdjfals;kdjgas")); + System.out.println(urlVal.isValid("www.:).com")); + + } + + /* + * The URLValidator can be split up into two disjoint sets of tests, tests + * that should pass and tests that should fail. This is consistent with an + * explanation of Input Domain Partitioning as found in an article written + * by Tomas Vagoun for the Annual Hawaii International Conference on System + * Sciences (https://goo.gl/acd0IL). + * + * This verifies that the basics of the validator do work, and approaching + * this problem as black box testing is some of the best that we can do. + */ + + public void testYourFirstPartition() { + UrlValidator urlVal = new UrlValidator(null, null, + UrlValidator.ALLOW_ALL_SCHEMES); + + String test; + + // This extremely ubiquitous URL is obviously completely true, and as + // such, the validator should return true. + + test = "http://www.google.com"; + if (urlVal.isValid(test) == true) { + System.out.println("Passed correctly at " + test + "."); + } else { + System.out.println("Failed incorrectly at " + test + "."); + } + + // This test happened to fail, so I wrote my bug report about it + test = "http://www.google.xxx"; + if (urlVal.isValid(test) == true) { + System.out.println("Passed correctly at " + test + "."); + } else { + System.out.println("Failed incorrectly at " + test + "."); + } + + // This test happened to fail, so I wrote my bug report about it + test = "http://www.peta.xxx"; + if (urlVal.isValid(test) == true) { + System.out.println("Passed correctly at " + test + "."); + } else { + System.out.println("Failed incorrectly at " + test + "."); + } + + } + + public void testYourSecondPartition() { + UrlValidator urlVal = new UrlValidator(null, null, + UrlValidator.ALLOW_ALL_SCHEMES); + + String test; + + // But we can detect that the isvalid fails on a known incorrect version + // so prove that it can still detect invalid URLs. + test = "http://www.google.government"; + if (urlVal.isValid(test) == false) { + System.out.println("Failed correctly at " + test + "."); + } else { + System.out.println("Failed incorrectly at " + test + "."); + } + + } + + public void testIsValid() { + // Print out that we're starting + System.out.println("Starting programmatically generated tests!"); + + // Make an instance of the url validator class + UrlValidator url_validator = new UrlValidator(null, null, + UrlValidator.ALLOW_ALL_SCHEMES); + + // Instantiate the random number generator + Random random_generator = new Random(); + + // Read in result pair arrays from the files that contain the test input + ResultPair[] test_schemes = get_result_pairs_from_file("test_files/test_schemes.txt"); + ResultPair[] test_authorities = get_result_pairs_from_file("test_files/test_authorities.txt"); + ResultPair[] test_ports = get_result_pairs_from_file("test_files/test_ports.txt"); + ResultPair[] test_paths = get_result_pairs_from_file("test_files/test_paths.txt"); + + // Set up some variables for keeping track of suceeded/failed tests. + int match_count = 0; + int fail_count = 0; + + // Main loop that will run the programmatic tests for so many times + for (int i = 0; i < 100000; i++) { + // Set up variables for another run through the loop + String full_url_string = ""; + Boolean expected_validity = true; + int current_rand = -1; + + // Get a random scheme, concatenate its string with the full url, + // and bitwise and its validity result so the result becomes false + // if necessary + current_rand = random_generator.nextInt(test_schemes.length); + full_url_string += test_schemes[current_rand].item; + expected_validity &= test_schemes[current_rand].valid; + + // Get a random authority, concatenate its string with the full url, + // and bitwise and its validity result so the result becomes false + // if necessary + current_rand = random_generator.nextInt(test_authorities.length); + full_url_string += test_authorities[current_rand].item; + expected_validity &= test_authorities[current_rand].valid; + + // Get a random port, concatenate its string with the full url, + // and bitwise and its validity result so the result becomes false + // if necessary + current_rand = random_generator.nextInt(test_ports.length); + full_url_string += test_ports[current_rand].item; + expected_validity &= test_ports[current_rand].valid; + + // Get a random path, concatenate its string with the full url, + // and bitwise and its validity result so the result becomes false + // if necessary + current_rand = random_generator.nextInt(test_paths.length); + full_url_string += test_paths[current_rand].item; + expected_validity &= test_paths[current_rand].valid; + + // Get the result of isValid from the url validator + Boolean actual_validity = url_validator.isValid(full_url_string); + + // Make a boolean that tells us whether the expected and actual + // validities match + Boolean validities_match = (actual_validity == expected_validity); + + if (validities_match) { + // If they match, increment our success counter. + match_count++; + + } else { + // Otherwise, print the failed url, and increment our fail count + // Here, I also have another call to isValid that can be + // uncommented for easy debugging of the failed url + System.out.println("Failed on url: " + full_url_string); + url_validator.isValid(full_url_string); + fail_count++; + } + + } + + // Print that the test is over + System.out.println("Programmatically generated tests complete!"); + + // Print the number of successes + System.out.println(match_count + " tests succeeded!"); + + // If there are failures, print the number of failures and a large + // warning. + if (fail_count > 0) { + System.out.println("SOME TESTS FAILED!!!!"); + System.out.println(fail_count + " tests failed!"); + } + + } + + private ResultPair[] get_result_pairs_from_file(String filename) { + // Create some file reading classes + FileReader file_reader = null; + BufferedReader buffered_reader = null; + + // Get the number of lines that are in the file + int num_lines = get_num_lines_in_file(filename); + + // Try and open the file reader on the file or handle exceptions + try { + file_reader = new FileReader(filename); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + // Put this reader into the buffered reader to make it easy to work with + buffered_reader = new BufferedReader(file_reader); + + // Create a result pair array with the correct number of entries + ResultPair[] pairs = new ResultPair[num_lines]; + + // Variable to hold the current line from the reader + String current_line = null; + + // Do and initial read to start off, or handle exceptions + try { + current_line = buffered_reader.readLine(); + } catch (IOException e1) { + e1.printStackTrace(); + } + + // For the number of lines in the file, loop + for (int i = 0; i < num_lines; i++) { + // Encapsulate in try block to hand exceptions + try { + // Split the current line by tabs, so there will be two indexes, + // one with the string, and one saying whether it's valid + String[] split_by_tab = current_line.split("\\t"); + + // Set the name to the first index + String name = split_by_tab[0]; + + // Create and empty bool for validity + Boolean is_valid = null; + + // Check the validity string in index one, and set the validity + // boolean accordingly + if (split_by_tab[1].equals("valid")) { + is_valid = true; + } else { + is_valid = false; + } + + // Set the current index of the result pair array to a new + // result pair with the name and validity + pairs[i] = new ResultPair(name, is_valid); + + // Read a new line for the next run through the loop + current_line = buffered_reader.readLine(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + // Now we're done, so close the file or handle exceptions + try { + buffered_reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + // Return our new array of pairs + return pairs; + } + + private int get_num_lines_in_file(String filename) { + // Create a line number reader + LineNumberReader line_reader = null; + + // Make a line reader and handle exceptions + try { + line_reader = new LineNumberReader(new FileReader( + new File(filename))); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + // Skip to the end of the file or handle exceptions + try { + line_reader.skip(Long.MAX_VALUE); + } catch (IOException e) { + e.printStackTrace(); + } + + // Get the number of lines the reader has read. The extra one makes it + // one indexed. + int number_of_lines = line_reader.getLineNumber() + 1; + + // Close the file, or handle exceptions + try { + line_reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + // Return the number of lines we found + return number_of_lines; + } +} diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_authorities.txt b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_authorities.txt new file mode 100644 index 0000000..5c9302e --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_authorities.txt @@ -0,0 +1,1542 @@ +www.caperren.aaa valid +www.caperren.aarp valid +www.caperren.abarth valid +www.caperren.abb valid +www.caperren.abbott valid +www.caperren.abbvie valid +www.caperren.abc valid +www.caperren.able valid +www.caperren.abogado valid +www.caperren.abudhabi valid +www.caperren.ac valid +www.caperren.academy valid +www.caperren.accenture valid +www.caperren.accountant valid +www.caperren.accountants valid +www.caperren.aco valid +www.caperren.active valid +www.caperren.actor valid +www.caperren.ad valid +www.caperren.adac valid +www.caperren.ads valid +www.caperren.adult valid +www.caperren.ae valid +www.caperren.aeg valid +www.caperren.aero valid +www.caperren.aetna valid +www.caperren.af valid +www.caperren.afamilycompany valid +www.caperren.afl valid +www.caperren.africa valid +www.caperren.ag valid +www.caperren.agakhan valid +www.caperren.agency valid +www.caperren.ai valid +www.caperren.aig valid +www.caperren.aigo valid +www.caperren.airbus valid +www.caperren.airforce valid +www.caperren.airtel valid +www.caperren.akdn valid +www.caperren.al valid +www.caperren.alfaromeo valid +www.caperren.alibaba valid +www.caperren.alipay valid +www.caperren.allfinanz valid +www.caperren.allstate valid +www.caperren.ally valid +www.caperren.alsace valid +www.caperren.alstom valid +www.caperren.am valid +www.caperren.americanexpress valid +www.caperren.americanfamily valid +www.caperren.amex valid +www.caperren.amfam valid +www.caperren.amica valid +www.caperren.amsterdam valid +www.caperren.analytics valid +www.caperren.android valid +www.caperren.anquan valid +www.caperren.anz valid +www.caperren.ao valid +www.caperren.aol valid +www.caperren.apartments valid +www.caperren.app valid +www.caperren.apple valid +www.caperren.aq valid +www.caperren.aquarelle valid +www.caperren.ar valid +www.caperren.aramco valid +www.caperren.archi valid +www.caperren.army valid +www.caperren.arpa valid +www.caperren.art valid +www.caperren.arte valid +www.caperren.as valid +www.caperren.asda valid +www.caperren.asia valid +www.caperren.associates valid +www.caperren.at valid +www.caperren.athleta valid +www.caperren.attorney valid +www.caperren.au valid +www.caperren.auction valid +www.caperren.audi valid +www.caperren.audible valid +www.caperren.audio valid +www.caperren.auspost valid +www.caperren.author valid +www.caperren.auto valid +www.caperren.autos valid +www.caperren.avianca valid +www.caperren.aw valid +www.caperren.aws valid +www.caperren.ax valid +www.caperren.axa valid +www.caperren.az valid +www.caperren.azure valid +www.caperren.ba valid +www.caperren.baby valid +www.caperren.baidu valid +www.caperren.banamex valid +www.caperren.bananarepublic valid +www.caperren.band valid +www.caperren.bank valid +www.caperren.bar valid +www.caperren.barcelona valid +www.caperren.barclaycard valid +www.caperren.barclays valid +www.caperren.barefoot valid +www.caperren.bargains valid +www.caperren.baseball valid +www.caperren.basketball valid +www.caperren.bauhaus valid +www.caperren.bayern valid +www.caperren.bb valid +www.caperren.bbc valid +www.caperren.bbt valid +www.caperren.bbva valid +www.caperren.bcg valid +www.caperren.bcn valid +www.caperren.bd valid +www.caperren.be valid +www.caperren.beats valid +www.caperren.beauty valid +www.caperren.beer valid +www.caperren.bentley valid +www.caperren.berlin valid +www.caperren.best valid +www.caperren.bestbuy valid +www.caperren.bet valid +www.caperren.bf valid +www.caperren.bg valid +www.caperren.bh valid +www.caperren.bharti valid +www.caperren.bi valid +www.caperren.bible valid +www.caperren.bid valid +www.caperren.bike valid +www.caperren.bing valid +www.caperren.bingo valid +www.caperren.bio valid +www.caperren.biz valid +www.caperren.bj valid +www.caperren.black valid +www.caperren.blackfriday valid +www.caperren.blanco valid +www.caperren.blockbuster valid +www.caperren.blog valid +www.caperren.bloomberg valid +www.caperren.blue valid +www.caperren.bm valid +www.caperren.bms valid +www.caperren.bmw valid +www.caperren.bn valid +www.caperren.bnl valid +www.caperren.bnpparibas valid +www.caperren.bo valid +www.caperren.boats valid +www.caperren.boehringer valid +www.caperren.bofa valid +www.caperren.bom valid +www.caperren.bond valid +www.caperren.boo valid +www.caperren.book valid +www.caperren.booking valid +www.caperren.boots valid +www.caperren.bosch valid +www.caperren.bostik valid +www.caperren.boston valid +www.caperren.bot valid +www.caperren.boutique valid +www.caperren.box valid +www.caperren.br valid +www.caperren.bradesco valid +www.caperren.bridgestone valid +www.caperren.broadway valid +www.caperren.broker valid +www.caperren.brother valid +www.caperren.brussels valid +www.caperren.bs valid +www.caperren.bt valid +www.caperren.budapest valid +www.caperren.bugatti valid +www.caperren.build valid +www.caperren.builders valid +www.caperren.business valid +www.caperren.buy valid +www.caperren.buzz valid +www.caperren.bv valid +www.caperren.bw valid +www.caperren.by valid +www.caperren.bz valid +www.caperren.bzh valid +www.caperren.ca valid +www.caperren.cab valid +www.caperren.cafe valid +www.caperren.cal valid +www.caperren.call valid +www.caperren.calvinklein valid +www.caperren.cam valid +www.caperren.camera valid +www.caperren.camp valid +www.caperren.cancerresearch valid +www.caperren.canon valid +www.caperren.capetown valid +www.caperren.capital valid +www.caperren.capitalone valid +www.caperren.car valid +www.caperren.caravan valid +www.caperren.cards valid +www.caperren.care valid +www.caperren.career valid +www.caperren.careers valid +www.caperren.cars valid +www.caperren.cartier valid +www.caperren.casa valid +www.caperren.case valid +www.caperren.caseih valid +www.caperren.cash valid +www.caperren.casino valid +www.caperren.cat valid +www.caperren.catering valid +www.caperren.catholic valid +www.caperren.cba valid +www.caperren.cbn valid +www.caperren.cbre valid +www.caperren.cbs valid +www.caperren.cc valid +www.caperren.cd valid +www.caperren.ceb valid +www.caperren.center valid +www.caperren.ceo valid +www.caperren.cern valid +www.caperren.cf valid +www.caperren.cfa valid +www.caperren.cfd valid +www.caperren.cg valid +www.caperren.ch valid +www.caperren.chanel valid +www.caperren.channel valid +www.caperren.chase valid +www.caperren.chat valid +www.caperren.cheap valid +www.caperren.chintai valid +www.caperren.chloe valid +www.caperren.christmas valid +www.caperren.chrome valid +www.caperren.chrysler valid +www.caperren.church valid +www.caperren.ci valid +www.caperren.cipriani valid +www.caperren.circle valid +www.caperren.cisco valid +www.caperren.citadel valid +www.caperren.citi valid +www.caperren.citic valid +www.caperren.city valid +www.caperren.cityeats valid +www.caperren.ck valid +www.caperren.cl valid +www.caperren.claims valid +www.caperren.cleaning valid +www.caperren.click valid +www.caperren.clinic valid +www.caperren.clinique valid +www.caperren.clothing valid +www.caperren.cloud valid +www.caperren.club valid +www.caperren.clubmed valid +www.caperren.cm valid +www.caperren.cn valid +www.caperren.co valid +www.caperren.coach valid +www.caperren.codes valid +www.caperren.coffee valid +www.caperren.college valid +www.caperren.cologne valid +www.caperren.com valid +www.caperren.comcast valid +www.caperren.commbank valid +www.caperren.community valid +www.caperren.company valid +www.caperren.compare valid +www.caperren.computer valid +www.caperren.comsec valid +www.caperren.condos valid +www.caperren.construction valid +www.caperren.consulting valid +www.caperren.contact valid +www.caperren.contractors valid +www.caperren.cooking valid +www.caperren.cookingchannel valid +www.caperren.cool valid +www.caperren.coop valid +www.caperren.corsica valid +www.caperren.country valid +www.caperren.coupon valid +www.caperren.coupons valid +www.caperren.courses valid +www.caperren.cr valid +www.caperren.credit valid +www.caperren.creditcard valid +www.caperren.creditunion valid +www.caperren.cricket valid +www.caperren.crown valid +www.caperren.crs valid +www.caperren.cruise valid +www.caperren.cruises valid +www.caperren.csc valid +www.caperren.cu valid +www.caperren.cuisinella valid +www.caperren.cv valid +www.caperren.cw valid +www.caperren.cx valid +www.caperren.cy valid +www.caperren.cymru valid +www.caperren.cyou valid +www.caperren.cz valid +www.caperren.dabur valid +www.caperren.dad valid +www.caperren.dance valid +www.caperren.data valid +www.caperren.date valid +www.caperren.dating valid +www.caperren.datsun valid +www.caperren.day valid +www.caperren.dclk valid +www.caperren.dds valid +www.caperren.de valid +www.caperren.deal valid +www.caperren.dealer valid +www.caperren.deals valid +www.caperren.degree valid +www.caperren.delivery valid +www.caperren.dell valid +www.caperren.deloitte valid +www.caperren.delta valid +www.caperren.democrat valid +www.caperren.dental valid +www.caperren.dentist valid +www.caperren.desi valid +www.caperren.design valid +www.caperren.dev valid +www.caperren.dhl valid +www.caperren.diamonds valid +www.caperren.diet valid +www.caperren.digital valid +www.caperren.direct valid +www.caperren.directory valid +www.caperren.discount valid +www.caperren.discover valid +www.caperren.dish valid +www.caperren.diy valid +www.caperren.dj valid +www.caperren.dk valid +www.caperren.dm valid +www.caperren.dnp valid +www.caperren.do valid +www.caperren.docs valid +www.caperren.doctor valid +www.caperren.dodge valid +www.caperren.dog valid +www.caperren.doha valid +www.caperren.domains valid +www.caperren.dot valid +www.caperren.download valid +www.caperren.drive valid +www.caperren.dtv valid +www.caperren.dubai valid +www.caperren.duck valid +www.caperren.dunlop valid +www.caperren.duns valid +www.caperren.dupont valid +www.caperren.durban valid +www.caperren.dvag valid +www.caperren.dvr valid +www.caperren.dz valid +www.caperren.earth valid +www.caperren.eat valid +www.caperren.ec valid +www.caperren.eco valid +www.caperren.edeka valid +www.caperren.edu valid +www.caperren.education valid +www.caperren.ee valid +www.caperren.eg valid +www.caperren.email valid +www.caperren.emerck valid +www.caperren.energy valid +www.caperren.engineer valid +www.caperren.engineering valid +www.caperren.enterprises valid +www.caperren.epost valid +www.caperren.epson valid +www.caperren.equipment valid +www.caperren.er valid +www.caperren.ericsson valid +www.caperren.erni valid +www.caperren.es valid +www.caperren.esq valid +www.caperren.estate valid +www.caperren.esurance valid +www.caperren.et valid +www.caperren.eu valid +www.caperren.eurovision valid +www.caperren.eus valid +www.caperren.events valid +www.caperren.everbank valid +www.caperren.exchange valid +www.caperren.expert valid +www.caperren.exposed valid +www.caperren.express valid +www.caperren.extraspace valid +www.caperren.fage valid +www.caperren.fail valid +www.caperren.fairwinds valid +www.caperren.faith valid +www.caperren.family valid +www.caperren.fan valid +www.caperren.fans valid +www.caperren.farm valid +www.caperren.farmers valid +www.caperren.fashion valid +www.caperren.fast valid +www.caperren.fedex valid +www.caperren.feedback valid +www.caperren.ferrari valid +www.caperren.ferrero valid +www.caperren.fi valid +www.caperren.fiat valid +www.caperren.fidelity valid +www.caperren.fido valid +www.caperren.film valid +www.caperren.final valid +www.caperren.finance valid +www.caperren.financial valid +www.caperren.fire valid +www.caperren.firestone valid +www.caperren.firmdale valid +www.caperren.fish valid +www.caperren.fishing valid +www.caperren.fit valid +www.caperren.fitness valid +www.caperren.fj valid +www.caperren.fk valid +www.caperren.flickr valid +www.caperren.flights valid +www.caperren.flir valid +www.caperren.florist valid +www.caperren.flowers valid +www.caperren.fly valid +www.caperren.fm valid +www.caperren.fo valid +www.caperren.foo valid +www.caperren.food valid +www.caperren.foodnetwork valid +www.caperren.football valid +www.caperren.ford valid +www.caperren.forex valid +www.caperren.forsale valid +www.caperren.forum valid +www.caperren.foundation valid +www.caperren.fox valid +www.caperren.fr valid +www.caperren.free valid +www.caperren.fresenius valid +www.caperren.frl valid +www.caperren.frogans valid +www.caperren.frontdoor valid +www.caperren.frontier valid +www.caperren.ftr valid +www.caperren.fujitsu valid +www.caperren.fujixerox valid +www.caperren.fun valid +www.caperren.fund valid +www.caperren.furniture valid +www.caperren.futbol valid +www.caperren.fyi valid +www.caperren.ga valid +www.caperren.gal valid +www.caperren.gallery valid +www.caperren.gallo valid +www.caperren.gallup valid +www.caperren.game valid +www.caperren.games valid +www.caperren.gap valid +www.caperren.garden valid +www.caperren.gb valid +www.caperren.gbiz valid +www.caperren.gd valid +www.caperren.gdn valid +www.caperren.ge valid +www.caperren.gea valid +www.caperren.gent valid +www.caperren.genting valid +www.caperren.george valid +www.caperren.gf valid +www.caperren.gg valid +www.caperren.ggee valid +www.caperren.gh valid +www.caperren.gi valid +www.caperren.gift valid +www.caperren.gifts valid +www.caperren.gives valid +www.caperren.giving valid +www.caperren.gl valid +www.caperren.glade valid +www.caperren.glass valid +www.caperren.gle valid +www.caperren.global valid +www.caperren.globo valid +www.caperren.gm valid +www.caperren.gmail valid +www.caperren.gmbh valid +www.caperren.gmo valid +www.caperren.gmx valid +www.caperren.gn valid +www.caperren.godaddy valid +www.caperren.gold valid +www.caperren.goldpoint valid +www.caperren.golf valid +www.caperren.goo valid +www.caperren.goodhands valid +www.caperren.goodyear valid +www.caperren.goog valid +www.caperren.google valid +www.caperren.gop valid +www.caperren.got valid +www.caperren.gov valid +www.caperren.gp valid +www.caperren.gq valid +www.caperren.gr valid +www.caperren.grainger valid +www.caperren.graphics valid +www.caperren.gratis valid +www.caperren.green valid +www.caperren.gripe valid +www.caperren.group valid +www.caperren.gs valid +www.caperren.gt valid +www.caperren.gu valid +www.caperren.guardian valid +www.caperren.gucci valid +www.caperren.guge valid +www.caperren.guide valid +www.caperren.guitars valid +www.caperren.guru valid +www.caperren.gw valid +www.caperren.gy valid +www.caperren.hair valid +www.caperren.hamburg valid +www.caperren.hangout valid +www.caperren.haus valid +www.caperren.hbo valid +www.caperren.hdfc valid +www.caperren.hdfcbank valid +www.caperren.health valid +www.caperren.healthcare valid +www.caperren.help valid +www.caperren.helsinki valid +www.caperren.here valid +www.caperren.hermes valid +www.caperren.hgtv valid +www.caperren.hiphop valid +www.caperren.hisamitsu valid +www.caperren.hitachi valid +www.caperren.hiv valid +www.caperren.hk valid +www.caperren.hkt valid +www.caperren.hm valid +www.caperren.hn valid +www.caperren.hockey valid +www.caperren.holdings valid +www.caperren.holiday valid +www.caperren.homedepot valid +www.caperren.homegoods valid +www.caperren.homes valid +www.caperren.homesense valid +www.caperren.honda valid +www.caperren.honeywell valid +www.caperren.horse valid +www.caperren.hospital valid +www.caperren.host valid +www.caperren.hosting valid +www.caperren.hot valid +www.caperren.hoteles valid +www.caperren.hotmail valid +www.caperren.house valid +www.caperren.how valid +www.caperren.hr valid +www.caperren.hsbc valid +www.caperren.ht valid +www.caperren.htc valid +www.caperren.hu valid +www.caperren.hughes valid +www.caperren.hyatt valid +www.caperren.hyundai valid +www.caperren.ibm valid +www.caperren.icbc valid +www.caperren.ice valid +www.caperren.icu valid +www.caperren.id valid +www.caperren.ie valid +www.caperren.ieee valid +www.caperren.ifm valid +www.caperren.ikano valid +www.caperren.il valid +www.caperren.im valid +www.caperren.imamat valid +www.caperren.imdb valid +www.caperren.immo valid +www.caperren.immobilien valid +www.caperren.in valid +www.caperren.industries valid +www.caperren.infiniti valid +www.caperren.info valid +www.caperren.ing valid +www.caperren.ink valid +www.caperren.institute valid +www.caperren.insurance valid +www.caperren.insure valid +www.caperren.int valid +www.caperren.intel valid +www.caperren.international valid +www.caperren.intuit valid +www.caperren.investments valid +www.caperren.io valid +www.caperren.ipiranga valid +www.caperren.iq valid +www.caperren.ir valid +www.caperren.irish valid +www.caperren.is valid +www.caperren.iselect valid +www.caperren.ismaili valid +www.caperren.ist valid +www.caperren.istanbul valid +www.caperren.it valid +www.caperren.itau valid +www.caperren.itv valid +www.caperren.iveco valid +www.caperren.iwc valid +www.caperren.jaguar valid +www.caperren.java valid +www.caperren.jcb valid +www.caperren.jcp valid +www.caperren.je valid +www.caperren.jeep valid +www.caperren.jetzt valid +www.caperren.jewelry valid +www.caperren.jio valid +www.caperren.jlc valid +www.caperren.jll valid +www.caperren.jm valid +www.caperren.jmp valid +www.caperren.jnj valid +www.caperren.jo valid +www.caperren.jobs valid +www.caperren.joburg valid +www.caperren.jot valid +www.caperren.joy valid +www.caperren.jp valid +www.caperren.jpmorgan valid +www.caperren.jprs valid +www.caperren.juegos valid +www.caperren.juniper valid +www.caperren.kaufen valid +www.caperren.kddi valid +www.caperren.ke valid +www.caperren.kerryhotels valid +www.caperren.kerrylogistics valid +www.caperren.kerryproperties valid +www.caperren.kfh valid +www.caperren.kg valid +www.caperren.kh valid +www.caperren.ki valid +www.caperren.kia valid +www.caperren.kim valid +www.caperren.kinder valid +www.caperren.kindle valid +www.caperren.kitchen valid +www.caperren.kiwi valid +www.caperren.km valid +www.caperren.kn valid +www.caperren.koeln valid +www.caperren.komatsu valid +www.caperren.kosher valid +www.caperren.kp valid +www.caperren.kpmg valid +www.caperren.kpn valid +www.caperren.kr valid +www.caperren.krd valid +www.caperren.kred valid +www.caperren.kuokgroup valid +www.caperren.kw valid +www.caperren.ky valid +www.caperren.kyoto valid +www.caperren.kz valid +www.caperren.la valid +www.caperren.lacaixa valid +www.caperren.ladbrokes valid +www.caperren.lamborghini valid +www.caperren.lamer valid +www.caperren.lancaster valid +www.caperren.lancia valid +www.caperren.lancome valid +www.caperren.land valid +www.caperren.landrover valid +www.caperren.lanxess valid +www.caperren.lasalle valid +www.caperren.lat valid +www.caperren.latino valid +www.caperren.latrobe valid +www.caperren.law valid +www.caperren.lawyer valid +www.caperren.lb valid +www.caperren.lc valid +www.caperren.lds valid +www.caperren.lease valid +www.caperren.leclerc valid +www.caperren.lefrak valid +www.caperren.legal valid +www.caperren.lego valid +www.caperren.lexus valid +www.caperren.lgbt valid +www.caperren.li valid +www.caperren.liaison valid +www.caperren.lidl valid +www.caperren.life valid +www.caperren.lifeinsurance valid +www.caperren.lifestyle valid +www.caperren.lighting valid +www.caperren.like valid +www.caperren.lilly valid +www.caperren.limited valid +www.caperren.limo valid +www.caperren.lincoln valid +www.caperren.linde valid +www.caperren.link valid +www.caperren.lipsy valid +www.caperren.live valid +www.caperren.living valid +www.caperren.lixil valid +www.caperren.lk valid +www.caperren.loan valid +www.caperren.loans valid +www.caperren.locker valid +www.caperren.locus valid +www.caperren.loft valid +www.caperren.lol valid +www.caperren.london valid +www.caperren.lotte valid +www.caperren.lotto valid +www.caperren.love valid +www.caperren.lpl valid +www.caperren.lplfinancial valid +www.caperren.lr valid +www.caperren.ls valid +www.caperren.lt valid +www.caperren.ltd valid +www.caperren.ltda valid +www.caperren.lu valid +www.caperren.lundbeck valid +www.caperren.lupin valid +www.caperren.luxe valid +www.caperren.luxury valid +www.caperren.lv valid +www.caperren.ly valid +www.caperren.ma valid +www.caperren.macys valid +www.caperren.madrid valid +www.caperren.maif valid +www.caperren.maison valid +www.caperren.makeup valid +www.caperren.man valid +www.caperren.management valid +www.caperren.mango valid +www.caperren.market valid +www.caperren.marketing valid +www.caperren.markets valid +www.caperren.marriott valid +www.caperren.marshalls valid +www.caperren.maserati valid +www.caperren.mattel valid +www.caperren.mba valid +www.caperren.mc valid +www.caperren.mcd valid +www.caperren.mcdonalds valid +www.caperren.mckinsey valid +www.caperren.md valid +www.caperren.me valid +www.caperren.med valid +www.caperren.media valid +www.caperren.meet valid +www.caperren.melbourne valid +www.caperren.meme valid +www.caperren.memorial valid +www.caperren.men valid +www.caperren.menu valid +www.caperren.meo valid +www.caperren.metlife valid +www.caperren.mg valid +www.caperren.mh valid +www.caperren.miami valid +www.caperren.microsoft valid +www.caperren.mil valid +www.caperren.mini valid +www.caperren.mint valid +www.caperren.mit valid +www.caperren.mitsubishi valid +www.caperren.mk valid +www.caperren.ml valid +www.caperren.mlb valid +www.caperren.mls valid +www.caperren.mm valid +www.caperren.mma valid +www.caperren.mn valid +www.caperren.mo valid +www.caperren.mobi valid +www.caperren.mobile valid +www.caperren.mobily valid +www.caperren.moda valid +www.caperren.moe valid +www.caperren.moi valid +www.caperren.mom valid +www.caperren.monash valid +www.caperren.money valid +www.caperren.monster valid +www.caperren.montblanc valid +www.caperren.mopar valid +www.caperren.mormon valid +www.caperren.mortgage valid +www.caperren.moscow valid +www.caperren.moto valid +www.caperren.motorcycles valid +www.caperren.mov valid +www.caperren.movie valid +www.caperren.movistar valid +www.caperren.mp valid +www.caperren.mq valid +www.caperren.mr valid +www.caperren.ms valid +www.caperren.msd valid +www.caperren.mt valid +www.caperren.mtn valid +www.caperren.mtpc valid +www.caperren.mtr valid +www.caperren.mu valid +www.caperren.museum valid +www.caperren.mutual valid +www.caperren.mv valid +www.caperren.mw valid +www.caperren.mx valid +www.caperren.my valid +www.caperren.mz valid +www.caperren.na valid +www.caperren.nab valid +www.caperren.nadex valid +www.caperren.nagoya valid +www.caperren.name valid +www.caperren.nationwide valid +www.caperren.natura valid +www.caperren.navy valid +www.caperren.nba valid +www.caperren.nc valid +www.caperren.ne valid +www.caperren.nec valid +www.caperren.net valid +www.caperren.netbank valid +www.caperren.netflix valid +www.caperren.network valid +www.caperren.neustar valid +www.caperren.new valid +www.caperren.newholland valid +www.caperren.news valid +www.caperren.next valid +www.caperren.nextdirect valid +www.caperren.nexus valid +www.caperren.nf valid +www.caperren.nfl valid +www.caperren.ng valid +www.caperren.ngo valid +www.caperren.nhk valid +www.caperren.ni valid +www.caperren.nico valid +www.caperren.nike valid +www.caperren.nikon valid +www.caperren.ninja valid +www.caperren.nissan valid +www.caperren.nissay valid +www.caperren.nl valid +www.caperren.no valid +www.caperren.nokia valid +www.caperren.northwesternmutual valid +www.caperren.norton valid +www.caperren.now valid +www.caperren.nowruz valid +www.caperren.nowtv valid +www.caperren.np valid +www.caperren.nr valid +www.caperren.nra valid +www.caperren.nrw valid +www.caperren.ntt valid +www.caperren.nu valid +www.caperren.nyc valid +www.caperren.nz valid +www.caperren.obi valid +www.caperren.observer valid +www.caperren.off valid +www.caperren.office valid +www.caperren.okinawa valid +www.caperren.olayan valid +www.caperren.olayangroup valid +www.caperren.oldnavy valid +www.caperren.ollo valid +www.caperren.om valid +www.caperren.omega valid +www.caperren.one valid +www.caperren.ong valid +www.caperren.onl valid +www.caperren.online valid +www.caperren.onyourside valid +www.caperren.ooo valid +www.caperren.open valid +www.caperren.oracle valid +www.caperren.orange valid +www.caperren.org valid +www.caperren.organic valid +www.caperren.orientexpress valid +www.caperren.origins valid +www.caperren.osaka valid +www.caperren.otsuka valid +www.caperren.ott valid +www.caperren.ovh valid +www.caperren.pa valid +www.caperren.page valid +www.caperren.pamperedchef valid +www.caperren.panasonic valid +www.caperren.panerai valid +www.caperren.paris valid +www.caperren.pars valid +www.caperren.partners valid +www.caperren.parts valid +www.caperren.party valid +www.caperren.passagens valid +www.caperren.pay valid +www.caperren.pccw valid +www.caperren.pe valid +www.caperren.pet valid +www.caperren.pf valid +www.caperren.pfizer valid +www.caperren.pg valid +www.caperren.ph valid +www.caperren.pharmacy valid +www.caperren.philips valid +www.caperren.phone valid +www.caperren.photo valid +www.caperren.photography valid +www.caperren.photos valid +www.caperren.physio valid +www.caperren.piaget valid +www.caperren.pics valid +www.caperren.pictet valid +www.caperren.pictures valid +www.caperren.pid valid +www.caperren.pin valid +www.caperren.ping valid +www.caperren.pink valid +www.caperren.pioneer valid +www.caperren.pizza valid +www.caperren.pk valid +www.caperren.pl valid +www.caperren.place valid +www.caperren.play valid +www.caperren.playstation valid +www.caperren.plumbing valid +www.caperren.plus valid +www.caperren.pm valid +www.caperren.pn valid +www.caperren.pnc valid +www.caperren.pohl valid +www.caperren.poker valid +www.caperren.politie valid +www.caperren.porn valid +www.caperren.post valid +www.caperren.pr valid +www.caperren.pramerica valid +www.caperren.praxi valid +www.caperren.press valid +www.caperren.prime valid +www.caperren.pro valid +www.caperren.prod valid +www.caperren.productions valid +www.caperren.prof valid +www.caperren.progressive valid +www.caperren.promo valid +www.caperren.properties valid +www.caperren.property valid +www.caperren.protection valid +www.caperren.pru valid +www.caperren.prudential valid +www.caperren.ps valid +www.caperren.pt valid +www.caperren.pub valid +www.caperren.pw valid +www.caperren.pwc valid +www.caperren.py valid +www.caperren.qa valid +www.caperren.qpon valid +www.caperren.quebec valid +www.caperren.quest valid +www.caperren.qvc valid +www.caperren.racing valid +www.caperren.radio valid +www.caperren.raid valid +www.caperren.re valid +www.caperren.read valid +www.caperren.realestate valid +www.caperren.realtor valid +www.caperren.realty valid +www.caperren.recipes valid +www.caperren.red valid +www.caperren.redstone valid +www.caperren.redumbrella valid +www.caperren.rehab valid +www.caperren.reise valid +www.caperren.reisen valid +www.caperren.reit valid +www.caperren.reliance valid +www.caperren.ren valid +www.caperren.rent valid +www.caperren.rentals valid +www.caperren.repair valid +www.caperren.report valid +www.caperren.republican valid +www.caperren.rest valid +www.caperren.restaurant valid +www.caperren.review valid +www.caperren.reviews valid +www.caperren.rexroth valid +www.caperren.rich valid +www.caperren.richardli valid +www.caperren.ricoh valid +www.caperren.rightathome valid +www.caperren.ril valid +www.caperren.rio valid +www.caperren.rip valid +www.caperren.rmit valid +www.caperren.ro valid +www.caperren.rocher valid +www.caperren.rocks valid +www.caperren.rodeo valid +www.caperren.rogers valid +www.caperren.room valid +www.caperren.rs valid +www.caperren.rsvp valid +www.caperren.ru valid +www.caperren.ruhr valid +www.caperren.run valid +www.caperren.rw valid +www.caperren.rwe valid +www.caperren.ryukyu valid +www.caperren.sa valid +www.caperren.saarland valid +www.caperren.safe valid +www.caperren.safety valid +www.caperren.sakura valid +www.caperren.sale valid +www.caperren.salon valid +www.caperren.samsclub valid +www.caperren.samsung valid +www.caperren.sandvik valid +www.caperren.sandvikcoromant valid +www.caperren.sanofi valid +www.caperren.sap valid +www.caperren.sapo valid +www.caperren.sarl valid +www.caperren.sas valid +www.caperren.save valid +www.caperren.saxo valid +www.caperren.sb valid +www.caperren.sbi valid +www.caperren.sbs valid +www.caperren.sc valid +www.caperren.sca valid +www.caperren.scb valid +www.caperren.schaeffler valid +www.caperren.schmidt valid +www.caperren.scholarships valid +www.caperren.school valid +www.caperren.schule valid +www.caperren.schwarz valid +www.caperren.science valid +www.caperren.scjohnson valid +www.caperren.scor valid +www.caperren.scot valid +www.caperren.sd valid +www.caperren.se valid +www.caperren.seat valid +www.caperren.secure valid +www.caperren.security valid +www.caperren.seek valid +www.caperren.select valid +www.caperren.sener valid +www.caperren.services valid +www.caperren.ses valid +www.caperren.seven valid +www.caperren.sew valid +www.caperren.sex valid +www.caperren.sexy valid +www.caperren.sfr valid +www.caperren.sg valid +www.caperren.sh valid +www.caperren.shangrila valid +www.caperren.sharp valid +www.caperren.shaw valid +www.caperren.shell valid +www.caperren.shia valid +www.caperren.shiksha valid +www.caperren.shoes valid +www.caperren.shop valid +www.caperren.shopping valid +www.caperren.shouji valid +www.caperren.show valid +www.caperren.showtime valid +www.caperren.shriram valid +www.caperren.si valid +www.caperren.silk valid +www.caperren.sina valid +www.caperren.singles valid +www.caperren.site valid +www.caperren.sj valid +www.caperren.sk valid +www.caperren.ski valid +www.caperren.skin valid +www.caperren.sky valid +www.caperren.skype valid +www.caperren.sl valid +www.caperren.sling valid +www.caperren.sm valid +www.caperren.smart valid +www.caperren.smile valid +www.caperren.sn valid +www.caperren.sncf valid +www.caperren.so valid +www.caperren.soccer valid +www.caperren.social valid +www.caperren.softbank valid +www.caperren.software valid +www.caperren.sohu valid +www.caperren.solar valid +www.caperren.solutions valid +www.caperren.song valid +www.caperren.sony valid +www.caperren.soy valid +www.caperren.space valid +www.caperren.spiegel valid +www.caperren.spot valid +www.caperren.spreadbetting valid +www.caperren.sr valid +www.caperren.srl valid +www.caperren.srt valid +www.caperren.st valid +www.caperren.stada valid +www.caperren.staples valid +www.caperren.star valid +www.caperren.starhub valid +www.caperren.statebank valid +www.caperren.statefarm valid +www.caperren.statoil valid +www.caperren.stc valid +www.caperren.stcgroup valid +www.caperren.stockholm valid +www.caperren.storage valid +www.caperren.store valid +www.caperren.stream valid +www.caperren.studio valid +www.caperren.study valid +www.caperren.style valid +www.caperren.su valid +www.caperren.sucks valid +www.caperren.supplies valid +www.caperren.supply valid +www.caperren.support valid +www.caperren.surf valid +www.caperren.surgery valid +www.caperren.suzuki valid +www.caperren.sv valid +www.caperren.swatch valid +www.caperren.swiftcover valid +www.caperren.swiss valid +www.caperren.sx valid +www.caperren.sy valid +www.caperren.sydney valid +www.caperren.symantec valid +www.caperren.systems valid +www.caperren.sz valid +www.caperren.tab valid +www.caperren.taipei valid +www.caperren.talk valid +www.caperren.taobao valid +www.caperren.target valid +www.caperren.tatamotors valid +www.caperren.tatar valid +www.caperren.tattoo valid +www.caperren.tax valid +www.caperren.taxi valid +www.caperren.tc valid +www.caperren.tci valid +www.caperren.td valid +www.caperren.tdk valid +www.caperren.team valid +www.caperren.tech valid +www.caperren.technology valid +www.caperren.tel valid +www.caperren.telecity valid +www.caperren.telefonica valid +www.caperren.temasek valid +www.caperren.tennis valid +www.caperren.teva valid +www.caperren.tf valid +www.caperren.tg valid +www.caperren.th valid +www.caperren.thd valid +www.caperren.theater valid +www.caperren.theatre valid +www.caperren.tiaa valid +www.caperren.tickets valid +www.caperren.tienda valid +www.caperren.tiffany valid +www.caperren.tips valid +www.caperren.tires valid +www.caperren.tirol valid +www.caperren.tj valid +www.caperren.tjmaxx valid +www.caperren.tjx valid +www.caperren.tk valid +www.caperren.tkmaxx valid +www.caperren.tl valid +www.caperren.tm valid +www.caperren.tmall valid +www.caperren.tn valid +www.caperren.to valid +www.caperren.today valid +www.caperren.tokyo valid +www.caperren.tools valid +www.caperren.top valid +www.caperren.toray valid +www.caperren.toshiba valid +www.caperren.total valid +www.caperren.tours valid +www.caperren.town valid +www.caperren.toyota valid +www.caperren.toys valid +www.caperren.tr valid +www.caperren.trade valid +www.caperren.trading valid +www.caperren.training valid +www.caperren.travel valid +www.caperren.travelchannel valid +www.caperren.travelers valid +www.caperren.travelersinsurance valid +www.caperren.trust valid +www.caperren.trv valid +www.caperren.tt valid +www.caperren.tube valid +www.caperren.tui valid +www.caperren.tunes valid +www.caperren.tushu valid +www.caperren.tv valid +www.caperren.tvs valid +www.caperren.tw valid +www.caperren.tz valid +www.caperren.ua valid +www.caperren.ubank valid +www.caperren.ubs valid +www.caperren.uconnect valid +www.caperren.ug valid +www.caperren.uk valid +www.caperren.unicom valid +www.caperren.university valid +www.caperren.uno valid +www.caperren.uol valid +www.caperren.ups valid +www.caperren.us valid +www.caperren.uy valid +www.caperren.uz valid +www.caperren.va valid +www.caperren.vacations valid +www.caperren.vana valid +www.caperren.vanguard valid +www.caperren.vc valid +www.caperren.ve valid +www.caperren.vegas valid +www.caperren.ventures valid +www.caperren.verisign valid +www.caperren.versicherung valid +www.caperren.vet valid +www.caperren.vg valid +www.caperren.vi valid +www.caperren.viajes valid +www.caperren.video valid +www.caperren.vig valid +www.caperren.viking valid +www.caperren.villas valid +www.caperren.vin valid +www.caperren.vip valid +www.caperren.virgin valid +www.caperren.visa valid +www.caperren.vision valid +www.caperren.vista valid +www.caperren.vistaprint valid +www.caperren.viva valid +www.caperren.vivo valid +www.caperren.vlaanderen valid +www.caperren.vn valid +www.caperren.vodka valid +www.caperren.volkswagen valid +www.caperren.volvo valid +www.caperren.vote valid +www.caperren.voting valid +www.caperren.voto valid +www.caperren.voyage valid +www.caperren.vu valid +www.caperren.vuelos valid +www.caperren.wales valid +www.caperren.walmart valid +www.caperren.walter valid +www.caperren.wang valid +www.caperren.wanggou valid +www.caperren.warman valid +www.caperren.watch valid +www.caperren.watches valid +www.caperren.weather valid +www.caperren.weatherchannel valid +www.caperren.webcam valid +www.caperren.weber valid +www.caperren.website valid +www.caperren.wed valid +www.caperren.wedding valid +www.caperren.weibo valid +www.caperren.weir valid +www.caperren.wf valid +www.caperren.whoswho valid +www.caperren.wien valid +www.caperren.wiki valid +www.caperren.williamhill valid +www.caperren.win valid +www.caperren.windows valid +www.caperren.wine valid +www.caperren.winners valid +www.caperren.wme valid +www.caperren.wolterskluwer valid +www.caperren.woodside valid +www.caperren.work valid +www.caperren.works valid +www.caperren.world valid +www.caperren.wow valid +www.caperren.ws valid +www.caperren.wtc valid +www.caperren.wtf valid +www.caperren.xbox valid +www.caperren.xerox valid +www.caperren.xfinity valid +www.caperren.xihuan valid +www.caperren.xin valid +www.caperren.xn--11b4c3d valid +www.caperren.xn--1ck2e1b valid +www.caperren.xn--1qqw23a valid +www.caperren.xn--30rr7y valid +www.caperren.xn--3bst00m valid +www.caperren.xn--3ds443g valid +www.caperren.xn--3e0b707e valid +www.caperren.xn--3oq18vl8pn36a valid +www.caperren.xn--3pxu8k valid +www.caperren.xn--42c2d9a valid +www.caperren.xn--45brj9c valid +www.caperren.xn--45q11c valid +www.caperren.xn--4gbrim valid +www.caperren.xn--54b7fta0cc valid +www.caperren.xn--55qw42g valid +www.caperren.xn--55qx5d valid +www.caperren.xn--5su34j936bgsg valid +www.caperren.xn--5tzm5g valid +www.caperren.xn--6frz82g valid +www.caperren.xn--6qq986b3xl valid +www.caperren.xn--80adxhks valid +www.caperren.xn--80ao21a valid +www.caperren.xn--80aqecdr1a valid +www.caperren.xn--80asehdb valid +www.caperren.xn--80aswg valid +www.caperren.xn--8y0a063a valid +www.caperren.xn--90a3ac valid +www.caperren.xn--90ae valid +www.caperren.xn--90ais valid +www.caperren.xn--9dbq2a valid +www.caperren.xn--9et52u valid +www.caperren.xn--9krt00a valid +www.caperren.xn--b4w605ferd valid +www.caperren.xn--bck1b9a5dre4c valid +www.caperren.xn--c1avg valid +www.caperren.xn--c2br7g valid +www.caperren.xn--cck2b3b valid +www.caperren.xn--cg4bki valid +www.caperren.xn--clchc0ea0b2g2a9gcd valid +www.caperren.xn--czr694b valid +www.caperren.xn--czrs0t valid +www.caperren.xn--czru2d valid +www.caperren.xn--d1acj3b valid +www.caperren.xn--d1alf valid +www.caperren.xn--e1a4c valid +www.caperren.xn--eckvdtc9d valid +www.caperren.xn--efvy88h valid +www.caperren.xn--estv75g valid +www.caperren.xn--fct429k valid +www.caperren.xn--fhbei valid +www.caperren.xn--fiq228c5hs valid +www.caperren.xn--fiq64b valid +www.caperren.xn--fiqs8s valid +www.caperren.xn--fiqz9s valid +www.caperren.xn--fjq720a valid +www.caperren.xn--flw351e valid +www.caperren.xn--fpcrj9c3d valid +www.caperren.xn--fzc2c9e2c valid +www.caperren.xn--fzys8d69uvgm valid +www.caperren.xn--g2xx48c valid +www.caperren.xn--gckr3f0f valid +www.caperren.xn--gecrj9c valid +www.caperren.xn--gk3at1e valid +www.caperren.xn--h2brj9c valid +www.caperren.xn--hxt814e valid +www.caperren.xn--i1b6b1a6a2e valid +www.caperren.xn--imr513n valid +www.caperren.xn--io0a7i valid +www.caperren.xn--j1aef valid +www.caperren.xn--j1amh valid +www.caperren.xn--j6w193g valid +www.caperren.xn--jlq61u9w7b valid +www.caperren.xn--jvr189m valid +www.caperren.xn--kcrx77d1x4a valid +www.caperren.xn--kprw13d valid +www.caperren.xn--kpry57d valid +www.caperren.xn--kpu716f valid +www.caperren.xn--kput3i valid +www.caperren.xn--l1acc valid +www.caperren.xn--lgbbat1ad8j valid +www.caperren.xn--mgb9awbf valid +www.caperren.xn--mgba3a3ejt valid +www.caperren.xn--mgba3a4f16a valid +www.caperren.xn--mgba7c0bbn0a valid +www.caperren.xn--mgbaam7a8h valid +www.caperren.xn--mgbab2bd valid +www.caperren.xn--mgbai9azgqp6j valid +www.caperren.xn--mgbayh7gpa valid +www.caperren.xn--mgbb9fbpob valid +www.caperren.xn--mgbbh1a71e valid +www.caperren.xn--mgbc0a9azcg valid +www.caperren.xn--mgbca7dzdo valid +www.caperren.xn--mgberp4a5d4ar valid +www.caperren.xn--mgbi4ecexp valid +www.caperren.xn--mgbpl2fh valid +www.caperren.xn--mgbt3dhd valid +www.caperren.xn--mgbtx2b valid +www.caperren.xn--mgbx4cd0ab valid +www.caperren.xn--mix891f valid +www.caperren.xn--mk1bu44c valid +www.caperren.xn--mxtq1m valid +www.caperren.xn--ngbc5azd valid +www.caperren.xn--ngbe9e0a valid +www.caperren.xn--node valid +www.caperren.xn--nqv7f valid +www.caperren.xn--nqv7fs00ema valid +www.caperren.xn--nyqy26a valid +www.caperren.xn--o3cw4h valid +www.caperren.xn--ogbpf8fl valid +www.caperren.xn--p1acf valid +www.caperren.xn--p1ai valid +www.caperren.xn--pbt977c valid +www.caperren.xn--pgbs0dh valid +www.caperren.xn--pssy2u valid +www.caperren.xn--q9jyb4c valid +www.caperren.xn--qcka1pmc valid +www.caperren.xn--qxam valid +www.caperren.xn--rhqv96g valid +www.caperren.xn--rovu88b valid +www.caperren.xn--s9brj9c valid +www.caperren.xn--ses554g valid +www.caperren.xn--t60b56a valid +www.caperren.xn--tckwe valid +www.caperren.xn--tiq49xqyj valid +www.caperren.xn--unup4y valid +www.caperren.xn--vermgensberater-ctb valid +www.caperren.xn--vermgensberatung-pwb valid +www.caperren.xn--vhquv valid +www.caperren.xn--vuq861b valid +www.caperren.xn--w4r85el8fhu5dnra valid +www.caperren.xn--w4rs40l valid +www.caperren.xn--wgbh1c valid +www.caperren.xn--wgbl6a valid +www.caperren.xn--xhq521b valid +www.caperren.xn--xkc2al3hye2a valid +www.caperren.xn--xkc2dl3a5ee0h valid +www.caperren.xn--y9a3aq valid +www.caperren.xn--yfro4i67o valid +www.caperren.xn--ygbi2ammx valid +www.caperren.xn--zfr164b valid +www.caperren.xperia valid +www.caperren.xxx valid +www.caperren.xyz valid +www.caperren.yachts valid +www.caperren.yahoo valid +www.caperren.yamaxun valid +www.caperren.yandex valid +www.caperren.ye valid +www.caperren.yodobashi valid +www.caperren.yoga valid +www.caperren.yokohama valid +www.caperren.you valid +www.caperren.youtube valid +www.caperren.yt valid +www.caperren.yun valid +www.caperren.za valid +www.caperren.zappos valid +www.caperren.zara valid +www.caperren.zero valid +www.caperren.zip valid +www.caperren.zippo valid +www.caperren.zm valid +www.caperren.zone valid +www.caperren.zuerich valid +www.caperren.zw valid +128.128.128.128 valid +0.0.0.0 valid + invalid +256.128.128.128 invalid +128.128.128.128.128 invalid +128.128.128.128. invalid +.128.128.128.128 invalid +test.notvalid invalid +test.n0tvalid invalid +test invalid +.test invalid +test. invalid \ No newline at end of file diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_paths.txt b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_paths.txt new file mode 100644 index 0000000..c0cf2be --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_paths.txt @@ -0,0 +1,10 @@ +/test1 valid +/t123 valid +/$23 valid +/.. invalid +/../ invalid +/test1/ valid + true +/test1/file valid +/..//file invalid +/test1//file invalid \ No newline at end of file diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_ports.txt b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_ports.txt new file mode 100644 index 0000000..ed5ceb7 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_ports.txt @@ -0,0 +1,7 @@ +:80 valid +:65535 valid +:0 valid + valid +:-1 invalid +:65636 valid +:65a invalid \ No newline at end of file diff --git a/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_schemes.txt b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_schemes.txt new file mode 100644 index 0000000..9199ba1 --- /dev/null +++ b/OSU Coursework/CS 362 - Software Engineering II/4 - Final Project - URLValidator Unit Testing/test_files/test_schemes.txt @@ -0,0 +1,21 @@ + valid +http:// valid +https:// valid +ftp:// valid +file:// valid +telnet:// valid +tftp:// valid +smtp:// valid +rtsp:// valid +magnet:// valid +dns:// valid +h3t:// valid +:// invalid +:/ invalid +: invalid +/ invalid +1:// invalid +magnet:/ invalid +magnet/ invalid +magnet// invalid +magnet: invalid \ No newline at end of file