Added Software Engineering II code

This commit is contained in:
2017-11-29 12:18:13 -08:00
parent c036c6e53f
commit 4566d98b5f
54 changed files with 9288 additions and 0 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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 <stdio.h>
#include <stdlib.h>
#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;
}
}

View File

@@ -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 <stdio.h>
#include <stdlib.h>
#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;
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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 <stdio.h>
#include <time.h>
#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");
}

View File

@@ -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