Пример #1
0
// What are my possible next moves (locations)
LocationID *whereCanIgo(HunterView currentView, int *numLocations, int road, int rail, int sea)
{
    assert(currentView != NULL);
    assert(numLocations != NULL);

    // return value
    LocationID *ret;

    // check if first round
    if(getRound(currentView->g) == FIRST_ROUND) {
        // everywhere!
        ret = (LocationID *)(malloc(sizeof(LocationID)*NUM_MAP_LOCATIONS));
        (*numLocations) = 0;

        int i;
        for(i=0;i<NUM_MAP_LOCATIONS;i++) {
            ret[(*numLocations)] = i;
            (*numLocations)++;
        }
    } else {
        ret = connectedLocations(currentView->g, numLocations,
                                 getLocation(currentView->g, 
                                             getCurrentPlayer(currentView->g)),
                                 getCurrentPlayer(currentView->g),
                                 getRound(currentView->g),
                                 road ,rail, sea);
    }
    
    return ret;
}
Пример #2
0
void testGraph(void) {
    printf("Testing graph 1...\n");
    Location path[NUM_MAP_LOCATIONS];
    int a = findShortestPath(NANTES, MARSEILLES, path, ANY,0);
    assert(a == 3);
    assert(path[0] == NANTES);
    assert(path[1] == CLERMONT_FERRAND);
    assert(path[2] == MARSEILLES);
    printf("Test passed!\n");
    printf("Testing graph 2...\n");
    a = findShortestPath(NANTES, MARSEILLES, path, ANY,0);
    assert(a == 3);
    assert(path[0] == NANTES);
    assert(path[1] == CLERMONT_FERRAND);
    assert(path[2] == MARSEILLES);
    printf("Test passed!\n");
    printf("Testing graph by rail...\n");
    a = findShortestPath(MADRID, BARCELONA, path, ANY,2);
    assert(a == 2);
    assert(path[0] == MADRID);
    assert(path[1] == BARCELONA);
    printf("Passed by rail test\n");
    a = findShortestPath(MARSEILLES, COLOGNE, path, ANY,3);
    assert(a == 2);
    assert(path[0] == MARSEILLES);
    assert(path[1] == COLOGNE);
    printf("Passed second rail test\n");
    a = findShortestPath(MARSEILLES, AMSTERDAM, path, ANY,3);
    assert(a == 3);
    assert(path[0] == MARSEILLES);
    assert(path[1] == COLOGNE);
    assert(path[2] == AMSTERDAM);
    printf("Passed final rail test\n");
    printf("Testing fail cases\n");
    printf("Testing Strassburg to CD\n");
    a = findShortestPath(STRASBOURG, CASTLE_DRACULA, path, ANY, 3);
    int i = 0;
    int correct[5] = {51,6,10,21,13};
    for (i = 0; i < a; i++) {
        assert(path[i] == correct[i]);
    }
    printf("Passed\nNow testing same path but without rail (ie round rem 4 equal to 0 )");
    printf("Passed\nNow testing same path but without rail");
    a = findShortestPath(STRASBOURG, CASTLE_DRACULA, path, ANY, 0);
    int correct2[6] = {51,38,58,10,28,13};
    for (i = 0; i < a; i++) {
        assert(path[i] == correct2[i]);
    }
    printf("\nTest Passed\nNow to test the results of connected locs Klaus (expecting CD to be there)\n");
    Graph g = newGraph();
    LocationID *b = connectedLocations(&a, KLAUSENBURG, 0, 0, ANY, g);
    for (i=0; i<a; i++) {
        printf("[%d]",b[i]);
    }
    free(b);
    destroyGraph(g);
    printf("\nDone\n");
}
Пример #3
0
int isLegalMove(HunterView gameState, PlayerID id, LocationID move, int round, Graph g) {
    LocationID currLoc = getLocation(gameState, id);
    int amtLocs = 0, legal = 0, i;
    if (currLoc >= 0 && currLoc < NUM_MAP_LOCATIONS) {
        LocationID * adj = connectedLocations(&amtLocs, currLoc, id, round, ANY, g);
        for (i = 0; i < amtLocs; i++) {
            if (adj[i] == move) legal = 1;
        }
        free(adj);
    }
    return legal;
}
Пример #4
0
// What are the specified player's next possible moves
// FREE THIS ARRAY IN THE AI
LocationID *whereCanTheyGo(DracView currentView, int *numLocations,
                        PlayerID player, int road, int rail, int sea) {

    LocationID *locations;

   // Remember to free the array retured from connectedLocations 
   // if you use it in the AI
   if (player == PLAYER_DRACULA) {
      locations = whereCanIgo(currentView, numLocations, road, sea);
   
   } else {
      locations = connectedLocations(currentView->gv, numLocations, \
                                 whereIs(currentView, player), \
                                 player, (giveMeTheRound(currentView)+1), \
                                 road, rail, sea);
   }

   return locations;
}
Пример #5
0
LocationID *returnConLocs(DracView currentView, int *numLocations) {

   LocationID *locations;
   LocationID myLocation;
   int road;
   int rail;
   int sea;

   myLocation = whereIs(currentView, PLAYER_DRACULA);
   road = 1;
   rail = 0;
   sea = 0;

   locations = connectedLocations(currentView->gv, numLocations, 
                  myLocation, PLAYER_DRACULA, 
                  giveMeTheRound(currentView), road, rail, sea);

   return locations;
}
Пример #6
0
// What are the specified player's next possible moves
LocationID *whereCanTheyGo(HunterView currentView, int *numLocations,
                           PlayerID player, int road, int rail, int sea)
{
    int i, numValidLocations, index;
    LocationID forbidden;
    LocationID *validLocations;
    fprintf(stderr,"From:%d  , player:%d\n",getLocation(currentView->g, player),player);

    LocationID *locations = connectedLocations(currentView->g,
                               numLocations,
                               getLocation(currentView->g, player),
                               player,
                               getRound(currentView->g),
                               road, rail, sea);
    if(player == PLAYER_DRACULA){
        forbidden = ST_JOSEPH_AND_ST_MARYS;
    }

    numValidLocations = 0;
    for(i = 0; i < (*numLocations); i++){
        if(locations[i] != forbidden){
            numValidLocations++;
        }
    }

    index = 0;
    validLocations = malloc(sizeof(LocationID) * numValidLocations);
    for(i = 0; i < numValidLocations; i++){
        if(locations[i] != forbidden){
            validLocations[index] = locations[i];
            index++;
        }
    }

    free(locations);
    *numLocations = numValidLocations;
    return validLocations;
}
Пример #7
0
// What are the specified player's next possible moves
LocationID *whereCanTheyGo(DracView currentView, int *numLocations, PlayerID player, int road, int rail, int sea) {
	// This will get ALL the connected locations.
	LocationID *arrConnected = connectedLocations(currentView->g, numLocations, getLocation(currentView->g, player), player, getRound(currentView->g), road, rail, sea);

	// The only trick is that Dracula must remove his trail.
	if (player == PLAYER_DRACULA) {
		Set setConnected = copyArrayToSet(arrConnected, *numLocations);

		LocationID pastSix[TRAIL_SIZE] = {0};
		giveMeTheTrail(currentView, player, pastSix);

		for (int i = 0; i < TRAIL_SIZE; i++) {
			if (isElem(setConnected, pastSix[i])) {
				setRemove(setConnected, pastSix[i]);
				*numLocations -= 1;
			}
		}

		free(arrConnected);
		arrConnected = copySetToArray(setConnected);
	}
	return arrConnected;
}
Пример #8
0
// find a path between two vertices using breadth-first traversal
int findPath(HunterView h, LocationID src, LocationID dest, int *path, int road, int rail, int sea)
{
	printf("finding path from %d to %d\n",src,dest);
	if(src==dest) {
		printf("trying to get to where you are\n");
		path[1] = dest;
		return 1;
	}
	int tmp_city = src;
	// Temporary store of path_distance for calculations
	int tmp_distance = 0;
	int path_distance = 0;

	// Array of visited cities, if not visited 0, else 1
	int visited[NUM_MAP_LOCATIONS] = {0};

	// Stores index of the previous city, default value -1
	int prev[NUM_MAP_LOCATIONS] = {[0 ... (NUM_MAP_LOCATIONS-1)] = -1};

	Queue cityQ = newQueue();
	QueueJoin(cityQ, src);

	// While Queue is not empty and the tmp_city is not the destination city (e.g. when path to destination city from src is found)
	while (QueueIsEmpty(cityQ) == 0 && tmp_city != dest) {
		tmp_city = QueueLeave(cityQ);
		
		int num_locs;
		int *locs = connectedLocations(h->g, &num_locs,tmp_city, whoAmI(h), giveMeTheRound(h),road,rail,sea);
		
		int i;
		for (i=0;i<num_locs;i++) {
			
		
			if (!visited[locs[i]]) {
				QueueJoin(cityQ, locs[i]);
				prev[locs[i]] = tmp_city;
				visited[locs[i]] = 1;
			}
		}

		if (tmp_city == dest) {
			prev[locs[i]] = tmp_city;

			// Calculating size of path
			int index = locs[i];
			while (index != src) {
				index = prev[index];
				path_distance++;
			}
		
			// Building path array, storing destination first
			tmp_distance = path_distance-1;
			path[tmp_distance] = dest;
			tmp_distance--;

			// Storing rest of array
			index = prev[dest];
			while (tmp_distance >= 0) {
				path[tmp_distance] = index;
				index = prev[index];
				tmp_distance--;
			}
			break;
		}
	}
	
	
	printf("path->");
	int j;
	for(j=0;j<path_distance;j++) {
		printf("%d->",path[j]);
	}
	printf("x\n");
	
	return path_distance;
}
Пример #9
0
int main()
{
    int i;
    GameView gv;

    printf("Test basic empty initialisation\n");
    PlayerMessage messages1[] = {};
    gv = newGameView("", messages1);
    assert(getCurrentPlayer(gv) == PLAYER_LORD_GODALMING);
    assert(getRound(gv) == 0);
    assert(getHealth(gv,PLAYER_DR_SEWARD) == GAME_START_HUNTER_LIFE_POINTS);
    assert(getHealth(gv,PLAYER_DRACULA) == GAME_START_BLOOD_POINTS);
    assert(getScore(gv) == GAME_START_SCORE);
    assert(getLocation(gv,PLAYER_LORD_GODALMING) == UNKNOWN_LOCATION);
    printf("passed\n");
    disposeGameView(gv);

    printf("Test for Dracula trail and basic functions\n");
    PlayerMessage messages2[] = {"Hello","Rubbish","Stuff","","Mwahahah"};
    gv = newGameView("GST.... SAO.... HZU.... MBB.... DC?....", messages2);
    assert(getCurrentPlayer(gv) == PLAYER_LORD_GODALMING);
    assert(getRound(gv) == 1);
    assert(getLocation(gv,PLAYER_LORD_GODALMING) == STRASBOURG);
    assert(getLocation(gv,PLAYER_DR_SEWARD) == ATLANTIC_OCEAN);
    assert(getLocation(gv,PLAYER_VAN_HELSING) == ZURICH);
    assert(getLocation(gv,PLAYER_MINA_HARKER) == BAY_OF_BISCAY);
    assert(getLocation(gv,PLAYER_DRACULA) == CITY_UNKNOWN);
    assert(getHealth(gv,PLAYER_DRACULA) == GAME_START_BLOOD_POINTS);
    printf("passed\n");
    disposeGameView(gv);

    printf("Test for encountering Dracula and hunter history\n");
    PlayerMessage messages3[] = {"Hello","Rubbish","Stuff","","Mwahahah","Aha!"};
    gv = newGameView("GST.... SAO.... HCD.... MAO.... DGE.... GGED...", messages3);
    assert(getLocation(gv,PLAYER_DRACULA) == GENEVA);
    assert(getHealth(gv,PLAYER_LORD_GODALMING) == 5);
    assert(getHealth(gv,PLAYER_DRACULA) == 30);
    assert(getLocation(gv,PLAYER_LORD_GODALMING) == GENEVA);
    LocationID history[TRAIL_SIZE];
    getHistory(gv,PLAYER_DRACULA,history);
    assert(history[0] == GENEVA);
    assert(history[1] == UNKNOWN_LOCATION);
    getHistory(gv,PLAYER_LORD_GODALMING,history);
    assert(history[0] == GENEVA);
    assert(history[1] == STRASBOURG);
    assert(history[2] == UNKNOWN_LOCATION);
    getHistory(gv,PLAYER_DR_SEWARD,history);
    assert(history[0] == ATLANTIC_OCEAN);
    assert(history[1] == UNKNOWN_LOCATION);
    printf("passed\n");
    disposeGameView(gv);

    printf("Test for Dracula doubling back at sea, and losing blood points (Hunter View)\n");
    PlayerMessage messages4[] = {"Hello","Rubbish","Stuff","","Mwahahah","Aha!","","","","Back I go"};
    gv = newGameView("GGE.... SGE.... HGE.... MGE.... DS?.... "
                     "GST.... SST.... HST.... MST.... DD1....", messages4);
    assert(getLocation(gv,PLAYER_DRACULA) == DOUBLE_BACK_1);
    getHistory(gv,PLAYER_DRACULA,history);
    assert(history[0] == DOUBLE_BACK_1);
    assert(history[1] == SEA_UNKNOWN);
    assert(getHealth(gv,PLAYER_DRACULA) == GAME_START_BLOOD_POINTS - 4);
    assert(getCurrentPlayer(gv) == 0);
    printf("passed\n");
    disposeGameView(gv);

    printf("Test for Dracula doubling back at sea, and losing blood points (Drac View)\n");
    PlayerMessage messages5[] = {"Hello","Rubbish","Stuff","","Mwahahah","Aha!","","","","Back I go"};
    gv = newGameView("GGE.... SGE.... HGE.... MGE.... DEC.... "
                     "GST.... SST.... HST.... MST.... DD1....", messages5);
    assert(getLocation(gv,PLAYER_DRACULA) == DOUBLE_BACK_1);
    getHistory(gv,PLAYER_DRACULA,history);
    assert(history[0] == DOUBLE_BACK_1);
    assert(history[1] == ENGLISH_CHANNEL);
    assert(getHealth(gv,PLAYER_DRACULA) == GAME_START_BLOOD_POINTS - 4);
    assert(getCurrentPlayer(gv) == 0);
    printf("passed\n");
    disposeGameView(gv);

    printf("Test for connections\n");
    int size, seen[NUM_MAP_LOCATIONS], *edges;
    gv = newGameView("", messages1);
    printf("Checking Galatz road connections\n");
    edges = connectedLocations(gv,&size,GALATZ,PLAYER_LORD_GODALMING,0,1,0,0);
    memset(seen, 0, NUM_MAP_LOCATIONS*sizeof(int));
    for (i = 0; i< size ; i++) seen[edges[i]] = 1;
    assert(size == 5);
    assert(seen[GALATZ]);
    assert(seen[CONSTANTA]);
    assert(seen[BUCHAREST]);
    assert(seen[KLAUSENBURG]);
    assert(seen[CASTLE_DRACULA]);
    free(edges);
    printf("Checking Ionian Sea sea connections\n");
    edges = connectedLocations(gv,&size,IONIAN_SEA,PLAYER_LORD_GODALMING,0,0,0,1);
    memset(seen, 0, NUM_MAP_LOCATIONS*sizeof(int));
    for (i = 0; i < size; i++) seen[edges[i]] = 1;
    assert(size == 7);
    assert(seen[IONIAN_SEA]);
    assert(seen[BLACK_SEA]);
    assert(seen[ADRIATIC_SEA]);
    assert(seen[TYRRHENIAN_SEA]);
    assert(seen[ATHENS]);
    assert(seen[VALONA]);
    assert(seen[SALONICA]);
    free(edges);
    printf("Checking Athens rail connections (none)\n");
    edges = connectedLocations(gv,&size,ATHENS,PLAYER_LORD_GODALMING,0,0,1,0);
    assert(size == 1);
    assert(edges[0] == ATHENS);
    free(edges);
    printf("passed\n");
    disposeGameView(gv);


    return 0;
}
Пример #10
0
// What are the specified player's next possible moves
LocationID *whereCanTheyGo(HunterView currentView, int *numLocations,
                           PlayerID player, int road, int rail, int sea)
{
    assert(currentView != NULL);
    assert(0 <= player && player < NUM_PLAYERS);
    assert(numLocations != NULL);

    Round theirNextRound;

    // check if they're before or after me
    if(player >= getCurrentPlayer(currentView->g)) {
        theirNextRound = getRound(currentView->g);
    } else {
        theirNextRound = getRound(currentView->g) + 1;
    }

    // return value
    LocationID *ret;

    // check if first round
    if(theirNextRound == FIRST_ROUND) {
        ret = (LocationID *)(malloc(sizeof(LocationID)*NUM_MAP_LOCATIONS));
        (*numLocations) = 0;

        // everywhere! 
        int i;
        for(i=0;i<NUM_MAP_LOCATIONS;i++) {
            // dracula can go everywhere except ST_JOSEPH_AND_ST_MARYS
            if(player != PLAYER_DRACULA || i != ST_JOSEPH_AND_ST_MARYS) {
                ret[(*numLocations)] = i;
                (*numLocations)++;
            }
        }
    } else {
        if(player == PLAYER_DRACULA) {
            // dracula
            // dracula's current location
            LocationID dracLoc = whereIs(currentView, PLAYER_DRACULA);

            // see if we can infer dracula's location
            
            // if valid, do the usual
            if(validPlace(dracLoc)) {
                // dracula can't travel by rail even if he wants to
                ret = connectedLocations(currentView->g, numLocations,
                                        whereIs(currentView, PLAYER_DRACULA),
                                        theirNextRound,
                                        player, road, FALSE, sea);
            } else {
                (*numLocations) = 0;

                // FIXME not sure what to return; probably doesn't matter
                ret = NULL;
            }
        } else {
            // a hunter
            ret =  connectedLocations(currentView->g, numLocations,
                                    getLocation(currentView->g, player),
                                    theirNextRound,
                                    player, road, rail, sea);
        }
    }

    return ret;
}
Пример #11
0
// What are my (Dracula's) possible next moves (locations)
//
// * connectedLocations Conditions:
//
// connectedLocations() returns an array of LocationID that represent
//   all locations that are connected to the given LocationID.
// road, rail and sea are connections should only be considered
//   if the road, rail, sea parameters are TRUE.
// The size of the array is stored in the variable pointed to by numLocations
// The array can be in any order but must contain unique entries
// Your function must take into account the round and player id for rail travel
// Your function must take into account that Dracula can't move to
//   the hospital or travel by rail but need not take into account Dracula's trail
// The destination 'from' should be included in the array
//
// FREE THIS ARRAY IN THE AI
//
// This function only returns a list of locations where duckula can go
// This does not include HIDE or DOUBLE_BACK. Will need to account for
// this somewhere.. somehow
LocationID *whereCanIgo(DracView currentView, int *numLocations,
                        int road, int sea) {

// whereCanIgo() returns an array of LocationIDs giving
//   all locations that Dracula could reach in his next move
// road and/or sea connections should only be considered
//   if the road and/or sea parameters are TRUE.
// The size of the array is stored in the variable pointed to by numLocations
// The array can be in any order but must contain unique entries
// Should not include the hospital nor any locations only reachable by rail
// The current location should be included in the array
// The set of possible locations must be consistent with the rules on Dracula's
//   movement (e.g. can't MOVE to a location currently in his trail)

   LocationID *locations;
   LocationID trail[TRAIL_SIZE];
   LocationID myLocation;
   int i;
   int j;
   int rail;

   rail = 0;
   myLocation = whereIs(currentView, PLAYER_DRACULA);
   // printf("in DV.c; whereCanIGo: myLocation: %d (%s)\n", myLocation, idToAbbrev(myLocation));

   // printf("here0 connectedLocations(%p, %d, %d, %d, %d, %d, %d, %d)\n", currentView->gv, *numLocations, whereIs(currentView, PLAYER_DRACULA), PLAYER_DRACULA, giveMeTheRound(currentView), road, rail, sea);
//   fprintf(stderr,"from %d, round %d\n", whereIs(currentView,PLAYER_DRACULA),giveMeTheRound(currentView));

   locations = connectedLocations(currentView->gv, numLocations, 
                  myLocation, PLAYER_DRACULA, 
                  giveMeTheRound(currentView), road, rail, sea);

   //fprintf(stderr, "in DV.c: connLocs: \n");
   //for (i = 0; i < *numLocations; i++) {
   //   fprintf(stderr, "\tlocations[%d]: %d (%s)\n", i, locations[i], idToAbbrev(locations[i]));
   //}

   getHistory(currentView->gv, PLAYER_DRACULA, trail);

   // check locations aren't in the trail except for trail[0] (current location)
   for (i = 0; i < *numLocations; i++) {
      // printf("in DV.c: locations[%d] = %d (%s)\n", i, locations[i], idToAbbrev(locations[i]));
      for (j = 0; j < TRAIL_SIZE; j++) {
         
         if (locations[i] == myLocation && idToType(myLocation) == SEA) {
            // I'm currently at sea. Remove currently location
            locations[i] = -1;

            int h;

            // shuffle the locations one index to the 'left'
            for (h = i; h < *numLocations; h++) {
               if ((h+1) < *numLocations) {
                  locations[h] = locations[h+1];
               }
            }
            *numLocations -= 1;

         } else if (locations[i] == trail[j] && locations[i] != UNKNOWN_LOCATION && j != 0) {
            // this location is in the trail, remove it
            // printf("in DV.c: locations[%d] (%d : %s) == trail[%d] (%d : %s)\n", i, locations[i], idToAbbrev(locations[i]), j, trail[j], idToAbbrev(trail[j]));
            locations[i] = -1;
            // printf("\tupdated locations[%d] -> %d\n", i, locations[i]);

            int h;

            // shuffle the locations one index to the 'left'
            for (h = i; h < *numLocations; h++) {
               if ((h+1) < *numLocations) {
                  locations[h] = locations[h+1];
               }
            }

            *numLocations -= 1;
         }
      }
   }

   //fprintf(stderr, "new locs: \n");
   //for (i = 0; i < *numLocations; i++) {
   //       fprintf(stderr, "\tin DV.c: locations[%d] (%d : %s)\n", i, locations[i], idToAbbrev(locations[i]));
   //}

   return locations;
}
Пример #12
0
void decideMove (HunterView gameState) {
    printf("at start of code\n"); fflush(stdout);
	Graph g = newGraph();
    char *locations[] = {
        "AL", "AM", "AT", "BA", "BI", "BE", "BR", "BO", "BU", "BC", 
        "BD", "CA", "CG", "CD", "CF", "CO", "CN", "DU", "ED", "FL",
        "FR", "GA", "GW", "GE", "GO", "GR", "HA", "JM", "KL", "LE",
        "LI", "LS", "LV", "LO", "MA", "MN", "MR", "MI", "MU", "NA",
        "NP", "NU", "PA", "PL", "PR", "RO", "SA", "SN", "SR", "SJ",
        "SO", "ST", "SW", "SZ", "TO", "VA", "VR", "VE", "VI", "ZA",
        "ZU", "NS", "EC", "IS", "AO", "BB", "MS", "TS", "IO", "AS", 
        "BS", "C?", "S?", "HI", "D1", "D2", "D3", "D4", "D5", "TP"
	};
	int round = getRound(gameState);
	PlayerID id = getCurrentPlayer(gameState);
    LocationID move = getLocation(gameState, id);
    printf("the original loc is %d and health %d\n",move,getHealth(gameState,id));
	char * msg = "";
    printf("initialised all variables\n"); fflush(stdout);
	//set initial locations
	if (round - id == 0) {
	    if (id == PLAYER_LORD_GODALMING) {move = CASTLE_DRACULA; msg = "camping";}
	    else if (id == PLAYER_DR_SEWARD)  move = BELGRADE;
	    else if (id == PLAYER_VAN_HELSING) move = STRASBOURG;
	    else if (id == PLAYER_MINA_HARKER) move = MADRID;
	    registerBestPlay(locations[move], msg);
	    destroyGraph(g);
	    return;
    }
    printf("done initial moves\n"); fflush(stdout);

    //below code will throw errors if LG is killed
    //if (id == PLAYER_LORD_GODALMING) { registerBestPlay("CD","I'm camping MAN!!!"); return; }
	srand (time(NULL));
	int path[NUM_MAP_LOCATIONS];
    int amtLocs = 0;
    LocationID * adj = connectedLocations(&amtLocs, getLocation(gameState, id), id, round, ANY, g);
    LocationID target = UNKNOWN_LOCATION;
    int camper = 0, i, j;
    printf("setting up connected locs etc\n"); fflush(stdout);

    // check for campers
    // if the current player is camping, then the player
    // will stay camping and ai will return
    
    for (i = 0; i < NUM_HUNTERS; i++) {
        if (getLocation(gameState, i) == CASTLE_DRACULA) {
            camper = 1;
            if (id == i) {
	            registerBestPlay("CD", "Staying camping");
                destroyGraph(g);
                free(adj);
                return; 
            }
        }
    } 

    if (!camper) { //if no camper and hunter is shortest dist to castle dracula, move towards castle dracula
        int hunterDist[NUM_HUNTERS] = {UNKNOWN_LOCATION,UNKNOWN_LOCATION,UNKNOWN_LOCATION,UNKNOWN_LOCATION};
        int closestHunter = PLAYER_LORD_GODALMING;
        for (i = PLAYER_LORD_GODALMING; i < NUM_HUNTERS; i++) {
            hunterDist[i] = findShortestPath(getLocation(gameState, i), CASTLE_DRACULA, path, ANY, round);
            if (hunterDist[i] == -1) hunterDist[i] = 1000; //-1 is when there is no path, so don't want him to be shortest
            if ((hunterDist[closestHunter] > hunterDist[i]) || (hunterDist[closestHunter] == UNKNOWN_LOCATION)) closestHunter = i;
        }
        if (closestHunter == id) move = path[1];
    } else {
        LocationID draculaLoc[TRAIL_SIZE];
        getHistory (gameState, PLAYER_DRACULA, draculaLoc); //updates Dracula trail

        for (i = TRAIL_SIZE - 1; i >= 0 ; i--) //locations newer in trail will override older ones
            target = dracTarget(draculaLoc, i); //we have any useful info on his location...

        if (target != UNKNOWN_LOCATION) {
            //Note: Dracula cannot visit any location currently in his trail - hunters should not visit target itself!
            int pathLen = findShortestPath(getLocation(gameState, id), target, path, ANY, round); //success is any number not -1
        	if (getLocation(gameState, id) != target && pathLen != -1) { //path found, and not at rest on target (Drac's trail)
                if (path[1] != target) move = path[1]; 
                //don't move into Dracula's trail (see note above)
                else move = adj[rand() % amtLocs];
                for (i = 0; i < TRAIL_SIZE ; i++) if (path[1] == dracTarget(draculaLoc, i)) move = adj[rand() % amtLocs];
            } else move = adj[rand() % amtLocs];
		} else { //prevents doubling up of hunters when making a random move, since Dracula 404
            int occupied = 0, newLoc = UNKNOWN_LOCATION;
            move = adj[rand() % amtLocs];
            for (j = 0; j < NUM_HUNTERS; j++) if (move == getLocation(gameState, j)) occupied = 1;
            if (occupied) { 
                for (i = 0; i < amtLocs; i++) { 
                    occupied = 0;
                    for (j = 0; j < NUM_HUNTERS; j++) if (adj[i] == getLocation(gameState, j)) occupied = 1;
                    if (!occupied) {newLoc = i; break;}
                }
            }
            if (newLoc != UNKNOWN_LOCATION) move = adj[newLoc]; 
        }
    } 
    if (target != UNKNOWN_LOCATION) printf("*Moving from %s (%d) to target %s (%d) via %s (%d)*\n", locations[getLocation(gameState, id)], getLocation(gameState, id), locations[target], target, locations[move], move);
    else printf("*No target - moving from %s (%d) to %s (%d)*\n", locations[getLocation(gameState, id)], getLocation(gameState, id), locations[move], move);
    
	if (isLegalMove(gameState, id, move, round, g)) registerBestPlay(locations[move], "");
	else {
        printf("ERROR: Location is invalid! Registering default rest move...");
        registerBestPlay(locations[getLocation(gameState, id)], "");
    }
    destroyGraph(g);
    free(adj);
}