int main(int argc, char **argv) { int id1, id2, errs=0; if (argc < 3) { fprintf(stderr, "Usage: %s Place1 Place2\n", argv[0]); exit(1); } // convert args to place IDs id1 = (strlen(argv[1]) == 2) ? abbrevToID(argv[1]) : nameToID(argv[1]); id2 = (strlen(argv[1]) == 2) ? abbrevToID(argv[2]) : nameToID(argv[2]); // check place validity if (id1 == NOWHERE) { errs++; fprintf(stderr, "Invalid place name: %s\n", argv[1]); } if (id2 == NOWHERE) { errs++; fprintf(stderr, "Invalid place name: %s\n", argv[2]); } if (errs > 0) exit(1); Map europe; europe = newMap(); // find shortest path int i, n; LocationID path[NUM_MAP_LOCATIONS]; TransportID trans[NUM_MAP_LOCATIONS]; printf("Starting from %s ...\n", idToName(id1)); n = shortestPath(europe, id1, id2, path, trans); if (n == 0) printf("you cannot reach %s\n", idToName(id2)); else { for (i = 1; i < n; i++) { if (i > 1 && n > 2) printf("then "); printf("go to %s by ", idToName(path[i])); switch (trans[i]) { case ROAD: printf("road\n"); break; case RAIL: printf("rail\n"); break; case BOAT: printf("boat\n"); break; default: printf("????\n"); break; } } printf("You have reached your destination\n"); } //DEBUG printf("start is: %d; end is: %d\n", id1, id2); printf("path[0] is: %d; path[1] is: %d\n", path[0], path[1]); return 0; }
// In house abbrev to Id convertor // Takes care of city and sea unknown // As well as hide and double backs LocationID abbrevToLocationID(char *abbrev) { if (!strcmp(abbrev,"C?")) { return CITY_UNKNOWN; } else if (!strcmp(abbrev,"S?")) { return SEA_UNKNOWN; } else if (!strcmp(abbrev,"HI")) { return HIDE; } else if (!strcmp(abbrev,"D1")) { return DOUBLE_BACK_1; } else if (!strcmp(abbrev,"D2")) { return DOUBLE_BACK_2; } else if (!strcmp(abbrev,"D3")) { return DOUBLE_BACK_3; } else if (!strcmp(abbrev,"D4")) { return DOUBLE_BACK_4; } else if (!strcmp(abbrev,"D5")) { return DOUBLE_BACK_5; } else if (!strcmp(abbrev,"TP")) { return TELEPORT; } else { return abbrevToID(abbrev); } }
static LocationID getNewLocation(char *abbrev) { assert(abbrev != NULL); // return value LocationID ret; if(abbrev[0] == 'C' && abbrev[1] == '?') { ret = CITY_UNKNOWN; } else if(abbrev[0] == 'S' && abbrev[1] == '?') { ret = SEA_UNKNOWN; } else if(abbrev[0] == 'H' && abbrev[1] == 'I') { ret = HIDE; } else if(abbrev[0] == 'D' && '0'+MIN_DOUBLE_BACK <= abbrev[1] && abbrev[1] <= '0'+MAX_DOUBLE_BACK) { ret = (FIRST_DOUBLE_BACK - MIN_DOUBLE_BACK) + (abbrev[1] - '0'); } else if(abbrev[0] == 'T' && abbrev[1] == 'P') { ret = (LocationID)(CASTLE_DRACULA); } else { // doesn't match any, try converting to place name ret = abbrevToID(abbrev); } return ret; }
int main(int argc, char **argv) { int id1, id2, errs=0; if (argc < 3) { fprintf(stderr, "Usage: %s Place1 Place2\n", argv[0]); exit(1); } // convert args to place IDs id1 = (strlen(argv[1]) == 2) ? abbrevToID(argv[1]) : nameToID(argv[1]); id2 = (strlen(argv[1]) == 2) ? abbrevToID(argv[2]) : nameToID(argv[2]); // check place validity if (id1 == NOWHERE) { errs++; fprintf(stderr, "Invalid place name: %s\n", argv[1]); } if (id2 == NOWHERE) { errs++; fprintf(stderr, "Invalid place name: %s\n", argv[2]); } if (errs > 0) exit(1); Map europe; europe = newMap(); // check for direct connection Transport t[NUM_TRANSPORT]; int i, n; printf("Between %s and %s ...\n", idToName(id1), idToName(id2)); n = connections(europe, id1, id2, t); if (n == 0) printf("No direct connection\n"); else { for (i = 0; i < n; i++) { switch (t[i]) { case ROAD: printf("Road connection\n"); break; case RAIL: printf("Rail connection\n"); break; case BOAT: printf("Boat connection\n"); break; default: printf("Weird connection\n"); break; } } } return 0; }
// Given a round and player id, return the location ID of where // that player was int getRoundLocation(DracView dv, int round, PlayerID player) { int location; char locationStr[3] = { '\0' }; int index; location = UNKNOWN_LOCATION; index = dv->pastPlaysIndex[player]; locationStr[0] = dv->past[(round * ROUND_LENGTH) + (index+1)]; locationStr[1] = dv->past[(round * ROUND_LENGTH) + (index+2)]; locationStr[2] = '\0'; location = abbrevToID(locationStr); return location; }
// Creates a new GameView to summarise the current state of the game GameView newGameView(char *pastPlays, PlayerMessage messages[]) { assert(pastPlays != NULL); assert(messages != NULL); GameView g = malloc(sizeof(struct gameView)); assert(g != NULL); g->pastPlays = malloc(sizeof(char) * MAX_PAST_PLAYS_LENGTH); int indexAt = 0; // Initialise the hunters int i; for(i = 0; i < NUM_PLAYERS-1; i++) { g->players[i].health = GAME_START_HUNTER_LIFE_POINTS; g->players[i].position = NOWHERE; } // initialise dracula g->players[PLAYER_DRACULA].health = GAME_START_BLOOD_POINTS; g->players[PLAYER_DRACULA].position = NOWHERE; // initialise turn and score g->turns = 0; g->score = GAME_START_SCORE; // initialise the trails for(i = 0; i < TRAIL_SIZE; i++) { g->trail[i] = NOWHERE; } // make a copy of past plays strncpy(g->pastPlays, pastPlays, MAX_PAST_PLAYS_LENGTH); // process the plays while(pastPlays[indexAt] != '\0') { // D("Play to process here is "); // int x; // for(x = 0; x < CHARS_PER_PLAY; x++) { // D("%c",pastPlays[indexAt+x]); // } // D("\n"); // copy message // current turn index [0-based] is g->turns // first, allocate space for the string g->messages[g->turns] = (char *)(malloc(sizeof(char)*MAX_MESSAGE_LENGTH)); assert(g->messages[g->turns] != NULL); assert(messages[g->turns] != NULL); // copy string, using strncpy for safety strncpy(g->messages[g->turns], messages[g->turns], MAX_MESSAGE_LENGTH); // get the abbreviation for the new location char abbrev[3]; abbrev[0] = pastPlays[indexAt+1]; abbrev[1] = pastPlays[indexAt+2]; // add a NUL terminator for good measure abbrev[2] = '\0'; // try to get the place id of the current place LocationID placeID = abbrevToID(abbrev); // work out if dracula or a hunter if(pastPlays[indexAt] == 'D') { // This player is dracula // We update his position. int isAtSea; int isAtCastle; if(placeID != NOWHERE) { if(idToType(placeID) == SEA) { isAtSea = TRUE; } else { isAtSea = FALSE; } if(placeID == CASTLE_DRACULA) { isAtCastle = TRUE; } else { isAtCastle = FALSE; } pushOnTrail(g, placeID); } else { // This is not dracula's string and we do not know where he is // And cannot update his position, other than saying if he is // on land or at sea. // We still need to know if he is at sea if(abbrev[0] == 'C') { // He is in some city // That is not castle dracula isAtSea = FALSE; isAtCastle = FALSE; pushOnTrail(g, CITY_UNKNOWN); placeID = CITY_UNKNOWN; } else if(abbrev[0] == 'S') { // He is at sea isAtSea = TRUE; isAtCastle = FALSE; pushOnTrail(g, SEA_UNKNOWN); placeID = SEA_UNKNOWN; } else if(abbrev[0] == 'T') { // He is at the castle isAtSea = FALSE; isAtCastle = TRUE; pushOnTrail(g, CASTLE_DRACULA); // set placeID to be teleport placeID = TELEPORT; } else if(abbrev[0] == 'D') { // He doubled back. // Because of the game's rules, we don't be clever and // instead place only the DOUBLE_BACK_ move type onto the // trail, even though we can (and do) infer the at-sea-ness // and location of dracula int numBack = (int)(abbrev[1]-'0'); LocationID newPosition = g->trail[TRAIL_SIZE-numBack]; // D("trail:"); // for(i=0;i<TRAIL_SIZE;i++) { // D(" %d",g->trail[i]); // } // D("\n"); // D("newPosition is %d\n",newPosition); if(newPosition == CITY_UNKNOWN) { isAtSea = FALSE; isAtCastle = FALSE; } else if (newPosition == SEA_UNKNOWN) { isAtSea = TRUE; isAtCastle = FALSE; } else { // We know exactly where dracula is if (idToType(newPosition) == SEA) { isAtSea = TRUE; isAtCastle = FALSE; } else if(newPosition == CASTLE_DRACULA) { isAtSea = FALSE; isAtCastle = TRUE; } else { isAtSea = FALSE; isAtCastle = FALSE; } } pushOnTrail(g, newPosition); // for sake of the getLocation function, we'll set // Dracula's new location to be the TYPE of move as opposed // to the city he's actually at even though we know what // that is placeID = (FIRST_DOUBLE_BACK-MIN_DOUBLE_BACK) + numBack; } else if(abbrev[0] == 'H') { // He's HIDING! // push on the most recent location pushOnTrail(g, g->trail[TRAIL_SIZE-1]); // for sake of getLocation, make current location HIDE placeID = HIDE; } } // set Dracula's 'public' location (as returned by getLocation) g->players[PLAYER_DRACULA].position = placeID; // Now we figure out what exactly dracula does at the new location if(isAtSea) { g->players[PLAYER_DRACULA].health -= LIFE_LOSS_SEA; } else if(isAtCastle) { g->players[PLAYER_DRACULA].health += LIFE_GAIN_CASTLE_DRACULA; } if(pastPlays[indexAt+3] == 'T') { // Dracula placed a trap. // TODO: Processing on what to do with traps // So far, it doesn't seem like we need to do anything // Since any encounters of traps are given to us // so we don't need to know where these things are } if(pastPlays[indexAt+4] == 'V') { // Dracula placed a young vampire // TODO: See the section on traps just above } // What just left the trail? if(pastPlays[indexAt+5] == 'V') { // A vampire has matured g->score -= SCORE_LOSS_VAMPIRE_MATURES; } } else { // This player is one of the hunters PlayerID curHunter; switch (pastPlays[indexAt]) { case 'G': curHunter = PLAYER_LORD_GODALMING; break; case 'S': curHunter = PLAYER_DR_SEWARD; break; case 'H': curHunter = PLAYER_VAN_HELSING; break; case 'M': curHunter = PLAYER_MINA_HARKER; break; default: assert (FALSE && "This is not a valid identifier for a player."); } LocationID newPosition = abbrevToID(abbrev); if(g->players[curHunter].position == ST_JOSEPH_AND_ST_MARYS && g->players[curHunter].health == 0) { // Our hunter has grown his legs back now. g->players[curHunter].health = GAME_START_HUNTER_LIFE_POINTS; } // Check if some encounters were made int i; // only loop while our hunter is alive and kicking // (and dracula, of course) for(i = 3;i < CHARS_PER_PLAY && g->players[curHunter].health > 0 && g->players[PLAYER_DRACULA].health > 0; i++) { if(pastPlays[indexAt+i] == 'T') { // Encountered a trap g->players[curHunter].health -= LIFE_LOSS_TRAP_ENCOUNTER; } else if(pastPlays[indexAt+i] == 'D') { //D("ENCOUNTERED DRACULA\n"); // Encountered Dracula g->players[curHunter].health -= LIFE_LOSS_DRACULA_ENCOUNTER; g->players[PLAYER_DRACULA].health -= LIFE_LOSS_HUNTER_ENCOUNTER; } } // check if our hunter died =( if (g->players[curHunter].health <= 0) { g->players[curHunter].health = 0; g->score -= SCORE_LOSS_HUNTER_HOSPITAL; newPosition = ST_JOSEPH_AND_ST_MARYS; } else if(newPosition == g->players[curHunter].position) { // The hunter rests and regains some health // Hunters need a bit of RnR, too! g->players[curHunter].health += LIFE_GAIN_REST; // cap hunter's health at GAME_START_HUNTER_LIFE_POINTS if (g->players[curHunter].health > GAME_START_HUNTER_LIFE_POINTS) { g->players[curHunter].health = GAME_START_HUNTER_LIFE_POINTS; } } // update our hunter's position g->players[curHunter].position = newPosition; } g->turns++; // we increment this way just in case we overshoot the NUL terminator // at the end of the string indexAt += CHARS_PER_PLAY; if(pastPlays[indexAt] == PLAY_SEP_CHAR) { indexAt++; } } // A little special case to heal the current hunter if they've been // incapacitated last turn. int turnPlayer = getCurrentPlayer(g); if(g->players[turnPlayer].position == ST_JOSEPH_AND_ST_MARYS && g->players[turnPlayer].health == 0) { // The hunter has regrown his legs! g->players[turnPlayer].health = GAME_START_HUNTER_LIFE_POINTS; } // print out messages for teh luls // for(i=0;i<g->turns;i++) { // D("message for turnplay %d: %s\n",i,g->messages[i]); // } return g; }
// Creates a new DracView to summarise the current state of the game DracView newDracView(char *pastPlays, PlayerMessage messages[]) { DracView dracView = malloc(sizeof(struct dracView)); dracView->g = newGameView(pastPlays, messages); dracView->vampLocation = NOWHERE; dracView->traps = newTrail(TRAIL_SIZE); // If pastPlays is empty, we just return early. if (strcmp(pastPlays, "") == 0) { return dracView; } char *currentPlayMarker = pastPlays; char currentPlay[8] = {'\0'}; char givenLocation[3] = {'\0'}; LocationID currentPlace = NOWHERE; while (currentPlayMarker != NULL) { memcpy(currentPlay, currentPlayMarker, 8); // We isolate the location part for easy access.. memcpy(givenLocation, currentPlay + 1, 2); currentPlace = abbrevToID(givenLocation); if (currentPlay[0] == 'D') { // Then we parse each of the next four characters. for (int i = 3; i < 6; i++) { if (i == 3 || i == 4) { switch (currentPlay[i]) { // TRAP PLACED case 'T': prepend(dracView->traps, currentPlace); break; // VAMPIRE PLACED case 'V': dracView->vampLocation = currentPlace; break; // NOTHING default: break; } } else if (i == 5) { switch (currentPlay[i]) { // TRAP LEAVES case 'M': while (showElement(dracView->traps, TRAIL_SIZE - 1) != NOWHERE) { prepend(dracView->traps, NOWHERE); } prepend(dracView->traps, NOWHERE); break; // VAMPIRE MATURES case 'V': dracView->vampLocation = NOWHERE; break; // NOTHING default: break; } } } } else { // Then we parse each of the next four characters. for (int i = 3; i < 7; i++) { switch (currentPlay[i]) { // TRAP FOUND case 'T': removeElement(dracView->traps, abbrevToID(givenLocation)); break; // VAMPIRE FOUND case 'V': dracView->vampLocation = NOWHERE; break; // NOTHING default: break; } } } if (currentPlay[7] == '\0') break; currentPlayMarker += 8; } return dracView; }
// Calculate Dracula's Health int calculateDraculaHealth (char *pastPlays) { //Setup Variables assert(pastPlays != NULL); int i = 0; //Counter int j = 0; //Counter int pastPlaysLength = strlen(pastPlays); char tempLocation[2] = {'0'}; int tempLocationID = 0; int trail[TRAIL_SIZE] = {'0'}; //Dracula begins with 40 "Blood Points" (health) int health = GAME_START_BLOOD_POINTS; //Loop through player's turns for (j = 0; j < pastPlaysLength; j++) { //Keep moving if not the start of a turn if (pastPlays[j] != ' ') { continue; } //Loop through the Action phase for (i = TRAP_CHAR_OFFSET + 1; i < TRAP_CHAR_OFFSET + 1 + MAX_TRAP_LENGTH; i++) { //If a hunter encounters Dracula he loses 10 blood points if (pastPlays[j + i] == 'D') { health = health - LIFE_LOSS_HUNTER_ENCOUNTER; if (health < 0) { return 0; } } } //Keep moving if not the player in question if (pastPlays[j + 1] != 'D') { continue; } //Dracula regains 10 blood points if he is in Castle Dracula at the end of his turn if (pastPlays[j + 1 + LOCATION_CHAR_OFFSET] == 'D' && pastPlays[j + 1 + LOCATION_CHAR_OFFSET - 1] == 'C') { if (health < 0) { return 0; } health = health + LIFE_GAIN_CASTLE_DRACULA; } //Determine Dracula's location //Store location initials temporarily tempLocation[1] = pastPlays[j + 1 + LOCATION_CHAR_OFFSET]; tempLocation[0] = pastPlays[j + 1 + LOCATION_CHAR_OFFSET - 1]; //Obtain useful LocationID tempLocationID = abbrevToID(tempLocation); //Case if tempLocation is not a place if (strncmp(tempLocation, "C?", 2) == 0) { tempLocationID = CITY_UNKNOWN; } else if (strncmp(tempLocation, "S?", 2) == 0) { tempLocationID = SEA_UNKNOWN; } else if (strncmp(tempLocation, "HI", 2) == 0) { tempLocationID = HIDE; } else if (strncmp(tempLocation, "D1", 2) == 0) { tempLocationID = DOUBLE_BACK_1; } else if (strncmp(tempLocation, "D2", 2) == 0) { tempLocationID = DOUBLE_BACK_2; } else if (strncmp(tempLocation, "D3", 2) == 0) { tempLocationID = DOUBLE_BACK_3; } else if (strncmp(tempLocation, "D4", 2) == 0) { tempLocationID = DOUBLE_BACK_4; } else if (strncmp(tempLocation, "D5", 2) == 0) { tempLocationID = DOUBLE_BACK_5; } else if (strncmp(tempLocation, "TP", 2) == 0) { tempLocationID = TELEPORT; } //Dracula loses 2 blood points if he is at sea at the end of his turn if (idToType(tempLocationID) == SEA || tempLocationID == SEA_UNKNOWN) { health = health - LIFE_LOSS_SEA; if (health < 0) { return 0; } //Case if Dracula hid while at sea } else if (tempLocationID == HIDE && idToType(trail[1]) == SEA) { health = health - LIFE_LOSS_SEA; if (health < 0) { return 0; } //Case if Dracula Doubled-Back to sea } else if (tempLocationID == DOUBLE_BACK_1 && (idToType(trail[1]) == SEA || trail[1] == SEA_UNKNOWN)) { health = health - LIFE_LOSS_SEA; if (health < 0) { return 0; } } else if (tempLocationID == DOUBLE_BACK_2 && (idToType(trail[2]) == SEA || trail[2] == SEA_UNKNOWN)) { health = health - LIFE_LOSS_SEA; if (health < 0) { return 0; } } else if (tempLocationID == DOUBLE_BACK_3 && (idToType(trail[3]) == SEA || trail[3] == SEA_UNKNOWN)) { health = health - LIFE_LOSS_SEA; if (health < 0) { return 0; } } else if (tempLocationID == DOUBLE_BACK_4 && (idToType(trail[4]) == SEA || trail[4] == SEA_UNKNOWN)) { health = health - LIFE_LOSS_SEA; if (health < 0) { return 0; } } else if (tempLocationID == DOUBLE_BACK_5 && (idToType(trail[5]) == SEA || trail[5] == SEA_UNKNOWN)) { health = health - LIFE_LOSS_SEA; if (health < 0) { return 0; } } } /* printf("this is gameView.c speaking\n"); printf("Dracula's health is: %d\n", health); */ return health; }
// Calculate the trail for each player void calculateTrail (char *pastPlays, PlayerID player, LocationID trail[TRAIL_SIZE]) { //Setup Variables assert(pastPlays != NULL); assert(trail != NULL); assert(player >= 0 && player <= 4); int i = 0; //Counter int j = 0; //Counter int pastPlaysLength = strlen(pastPlays); char playerInitial; char tempLocation[2] = {'0'}; //Determine which player initial to look for switch (player) { case PLAYER_LORD_GODALMING : playerInitial = 'G'; break; case PLAYER_DR_SEWARD : playerInitial = 'S'; break; case PLAYER_VAN_HELSING : playerInitial = 'H'; break; case PLAYER_MINA_HARKER : playerInitial = 'M'; break; case PLAYER_DRACULA : playerInitial = 'D'; break; } //Fill the trail array with -1 to indicate location unknown initially for (i = 0; i < TRAIL_SIZE; i++) { trail[i] = UNKNOWN_LOCATION; } //Loop backwards through the pastPlays string to find recent turns for (i = pastPlaysLength; i >= 0; i--) { //Keep moving if not the start of a turn if (pastPlays[i] != ' ') { continue; } //Keep moving if not the player in question if (pastPlays[i + 1] != playerInitial) { continue; } //Should now always have the correct player, start of turn //Store location initials temporarily tempLocation[1] = pastPlays[i + 1 + LOCATION_CHAR_OFFSET]; tempLocation[0] = pastPlays[i + 1 + LOCATION_CHAR_OFFSET - 1]; //Input locationID into array - special handling for non-locations trail[j] = abbrevToID(tempLocation); //Special Handling for non-locations //#define in Places.h, lines 106-117 if (strncmp(tempLocation, "C?", 2) == 0) { trail[j] = CITY_UNKNOWN; } else if (strncmp(tempLocation, "S?", 2) == 0) { trail[j] = SEA_UNKNOWN; } else if (strncmp(tempLocation, "HI", 2) == 0) { trail[j] = HIDE; } else if (strncmp(tempLocation, "D1", 2) == 0) { trail[j] = DOUBLE_BACK_1; } else if (strncmp(tempLocation, "D2", 2) == 0) { trail[j] = DOUBLE_BACK_2; } else if (strncmp(tempLocation, "D3", 2) == 0) { trail[j] = DOUBLE_BACK_3; } else if (strncmp(tempLocation, "D4", 2) == 0) { trail[j] = DOUBLE_BACK_4; } else if (strncmp(tempLocation, "D5", 2) == 0) { trail[j] = DOUBLE_BACK_5; } else if (strncmp(tempLocation, "TP", 2) == 0) { trail[j] = TELEPORT; } j++; } //Special case for first turn in game if (pastPlays[0] != playerInitial) { //Do Nothing } else { //Store location initials temporarily tempLocation[1] = pastPlays[LOCATION_CHAR_OFFSET]; tempLocation[0] = pastPlays[LOCATION_CHAR_OFFSET - 1]; //Input locationID into array trail[j] = abbrevToID(tempLocation); } }
// Creates a new HunterView to summarise the current state of the game HunterView newHunterView(char *pastPlays, PlayerMessage messages[]) { assert(pastPlays != NULL); assert(messages != NULL); // malloc HunterView hunterView = malloc(sizeof(struct hunterView)); assert(hunterView != NULL); // setup the gameview hunterView->g = newGameView(pastPlays, messages); assert(hunterView->g != NULL); int i; // initialise Dracula's actual locations to all UNKNOWN_LOCATION for(i=0;i<TRAIL_SIZE;i++) { hunterView->trailLocs[i] = UNKNOWN_LOCATION; } // length of pastPlays int pastPlaysLength = strnlen(pastPlays, MAX_PAST_PLAYS_LENGTH); // iterate over each turn and process for(i=0;i<pastPlaysLength;i+=CHARS_PER_PLAY_BLOCK) { // get curPlayer PlayerID curPlayer = ( (i/CHARS_PER_PLAY_BLOCK) % NUM_PLAYERS); // ensure it's dracula if(curPlayer == PLAYER_DRACULA) { // try to get current loc (if it's exact) LocationID curLoc = abbrevToID(pastPlays+i+LOC_ABBREV_INDEX); // fprintf(stderr,"here = %.7s curLoc = %d\n",pastPlays+i,curLoc); // test if exact location if(!validPlace(curLoc)) { // not exact; try to use trail to work out where we really are // either a HIDE, DOUBLE_BACK_ or TELEPORT if(pastPlays[i+LOC_ABBREV_INDEX] == 'H') { // HIDE: go to most recent location curLoc = hunterView->trailLocs[LAST_TRAIL_LOC_INDEX]; } else if(pastPlays[i+LOC_ABBREV_INDEX] == 'D') { // DOUBLE BACK int numBack = (int)(pastPlays[i+LOC_ABBREV_INDEX+1]-'0'); curLoc = hunterView->trailLocs[numBack]; } else if(pastPlays[i+LOC_ABBREV_INDEX] == 'T') { // TELEPORT back to CASTLE_DRACULA curLoc = CASTLE_DRACULA; } else if(pastPlays[i+LOC_ABBREV_INDEX] == 'C') { curLoc = CITY_UNKNOWN; } else if(pastPlays[i+LOC_ABBREV_INDEX] == 'S') { curLoc = SEA_UNKNOWN; } else { curLoc = UNKNOWN_LOCATION; } } // push curLoc onto the trail pushOnTrailLocs(hunterView, curLoc); } } return hunterView; }
// Creates a new GameView to summarise the current state of the game GameView newGameView(char *pastPlays, PlayerMessage messages[]) { GameView g = malloc(sizeof(struct gameView)); int i = 0; int currplay = 0; LocationID newlocid = 0; char newloc[3]; int messagecount = 0; int offset; g->map = newMap(); assert(g != NULL); //initialize score, roundnum g->score = 366; g->roundnum = 0; g->currplayer = 0; //initialize hunters for(i=0; i<(NUM_PLAYERS-1); i++) { g->players[i].health = GAME_START_HUNTER_LIFE_POINTS; g->players[i].currlocation = UNKNOWN_LOCATION; } //initialize dracula g->players[i].health = GAME_START_BLOOD_POINTS; g->players[i].currlocation = UNKNOWN_LOCATION; //initialize trails to -1 initializetrails(g); //loop through pastPlays to create game status if (pastPlays[currplay] != '\0') { do { printf("--'%s'--\n",messages[messagecount]); newloc[0] = pastPlays[currplay+1]; newloc[1] = pastPlays[currplay+2]; newloc[2] = '\0'; if(strcmp(newloc,"C?") == 0) { newlocid = CITY_UNKNOWN; } else if (strcmp(newloc,"S?") == 0) { newlocid = SEA_UNKNOWN; } else if (strcmp(newloc,"D1") == 0) { newlocid = DOUBLE_BACK_1; } else if (strcmp(newloc,"D2") == 0) { newlocid = DOUBLE_BACK_2; } else if (strcmp(newloc,"D3") == 0) { newlocid = DOUBLE_BACK_3; } else if (strcmp(newloc,"D4") == 0) { newlocid = DOUBLE_BACK_4; } else if (strcmp(newloc,"D5") == 0) { newlocid = DOUBLE_BACK_5; } else { newlocid = abbrevToID(newloc); } g->players[g->currplayer].currlocation = newlocid; //push location to trail pushtotrail(g, newlocid); printtrail(g); //if Hunter if(g->currplayer < 4) { for(offset=3; offset<7; offset++) { if(pastPlays[currplay+offset] == 'T') { //encounter with trap g->players[g->currplayer].health -= 2; } else if (pastPlays[currplay+offset] == 'D') { //encounter with Dracula g->players[g->currplayer].health -= 4; g->players[4].health -= 10; } } //else Dracula } else { for(offset=3; offset<6; offset++) { if(pastPlays[currplay+offset] == 'T') { //trap placed } else if (pastPlays[currplay+offset] == 'V') { //vampire placed } } if(pastPlays[currplay+offset] == 'M') { //trap has left the trail } else if (pastPlays[currplay+offset] == 'V') { //vampire has matured } //if at sea, Dracula loses health if(g->players[g->currplayer].currlocation == SEA_UNKNOWN) { g->players[g->currplayer].health -= 2; } } //increment currplayer and roundnum g->currplayer++; if(g->currplayer > 4) { g->roundnum++; g->currplayer = 0; } //move through string input 8 chars currplay += PLAY_LENGTH; messagecount++; } while(pastPlays[currplay-1] != '\0'); } return g; }
DracView newDracView(char *pastPlays, PlayerMessage messages[]) { //REPLACE THIS WITH YOUR OWN IMPLEMENTATION DracView dracView = malloc(sizeof(struct dracView)); int j,i=0; int player=0; Playersave currentstate; //initialise struct dracView->hello = 42; dracView->gameround = 0; dracView->gameturn = 0; dracView->playerturn = 0; dracView->score = GAME_START_SCORE ; dracView->traps = 0; dracView->vamps = 0; //initialise array of traps and vamps for( i=0; i<NUM_MAP_LOCATIONS ;i++){ dracView->vampsarray[i] = 0; dracView->trapsarray[i] = 0; } //initialise hunters 1-4 for( i=0; i<PLAYER_DRACULA ; i++){ //create struct dracView->playerstate[i] = malloc(sizeof(struct PlayerSave)); //quick access variable currentstate = dracView->playerstate[i]; //set player number currentstate->playernumber = i; //set player health to 9 currentstate->health = GAME_START_HUNTER_LIFE_POINTS; //set player starting position (nowhere) currentstate->current = UNKNOWN_LOCATION; //fill trail with nowheres for( j=0; j<TRAIL_SIZE ; j++){ currentstate->trail[j] = NOWHERE; } } //initialise Dracula if(1){ //player Dracula i = PLAYER_DRACULA ; //create struct dracView->playerstate[i] = malloc(sizeof(struct PlayerSave)); //quick access variable currentstate = dracView->playerstate[i]; //set player number currentstate->playernumber = i; //set player health to 40 currentstate->health = GAME_START_BLOOD_POINTS; //set player starting position (nowhere) currentstate->current = UNKNOWN_LOCATION; //fill trail with nowheres for( j=0; j<TRAIL_SIZE ; j++){ currentstate->trail[j] = NOWHERE; } } //ACTUALLY READING THE STRING //reinitialise searching variables i = 0; //continue if still things is past plays string. while( (strlen( pastPlays ) > i) && ((pastPlays[i-1] != '\0')||i==0) ){ //increment game turn, round dracView->gameturn++; if(dracView->gameturn == PLAYER_DRACULA+1){ dracView->gameturn = 0; dracView->gameround++; } //player quick variable player = dracView->playerturn; //easy access pointer currentstate = dracView->playerstate[player]; //hunterwrite //hunterwrite if( player < PLAYER_DRACULA ){ //check if player stayed in city to heal if( (currentstate->current == abbrevToID( pastPlays+i+1 )) && (idToType(currentstate->current) == LAND) ){ currentstate->health += LIFE_GAIN_REST ; //hunter health cannot exceed starting health if( currentstate->health > GAME_START_HUNTER_LIFE_POINTS){ currentstate->health = GAME_START_HUNTER_LIFE_POINTS; } } //update locations for player currentstate->current = abbrevToID( pastPlays+i+1 ); //check if player is at a hospital if( currentstate->current == ST_JOSEPH_AND_ST_MARYS){ currentstate->health = GAME_START_HUNTER_LIFE_POINTS; } //fix trail array for( j=TRAIL_SIZE; j>1 ; j--){ currentstate->trail[j-1] = currentstate->trail[j-2]; } currentstate->trail[0] = currentstate->current; //check remainder of string for( j=3 ; pastPlays[i+j] != '.'; j++){ //different occurrences switch( pastPlays[i+j] ){ //check if trap encountered case 'T':{ //update health dracView->trapsarray[currentstate->current]--; dracView->traps--; currentstate->health -= LIFE_LOSS_TRAP_ENCOUNTER; break; } //check if immature vamp encountered case 'V':{ //update vamps dracView->vampsarray[currentstate->current]--; dracView->vamps--; break; } //check if Dracula encountered case 'D':{ //update health -> hunter currentstate->health -= LIFE_LOSS_DRACULA_ENCOUNTER; //update health -> Dracula dracView->playerstate[PLAYER_DRACULA]->health -= LIFE_LOSS_HUNTER_ENCOUNTER; break; } } //RULECHECK: what happens if hunter goes into a city with drac, but dies to a trap before encounter? //check if hunter is dead if( currentstate->health < 0 ){ dracView->score -= SCORE_LOSS_HUNTER_HOSPITAL; currentstate->health = GAME_START_HUNTER_LIFE_POINTS; currentstate->current = ST_JOSEPH_AND_ST_MARYS; } } } //draculawrite //draculawrite else if( player == PLAYER_DRACULA) { //check if drac stayed in castle to heal if( (currentstate->current == abbrevToID( pastPlays+i+1 )) && ( currentstate->current == CASTLE_DRACULA) ){ currentstate->health += LIFE_GAIN_CASTLE_DRACULA; //Drac health can exceed 40 } //update locations for dracula switch( pastPlays[i+1] ){ //C? case 'C': currentstate->current = CITY_UNKNOWN; break; //S? case 'S': currentstate->current = SEA_UNKNOWN; break; //HI case 'H': currentstate->current = HIDE; break; //TP case 'T': currentstate->current = TELEPORT; break; //Dn case 'D':{ //which double back? switch( pastPlays[i+2] ){ case '1': currentstate->current = DOUBLE_BACK_1; break; case '2': currentstate->current = DOUBLE_BACK_2; break; case '3': currentstate->current = DOUBLE_BACK_3; break; case '4': currentstate->current = DOUBLE_BACK_4; break; case '5': currentstate->current = DOUBLE_BACK_5; break; } break; } //XX proper city coordinates default: currentstate->current = abbrevToID( pastPlays+i+1 ); break; } //fix trail array LocationID fallenofftrail = currentstate->trail[TRAIL_SIZE-1]; for( j=TRAIL_SIZE; j>1 ; j--){ currentstate->trail[j-1] = currentstate->trail[j-2]; } currentstate->trail[0] = currentstate->current; //if 'other' locations (hunterview) //check if at sea //HUNTERVIEW if( currentstate->current == SEA_UNKNOWN ){ //update health currentstate->health -= LIFE_LOSS_SEA; } //DRACVIEW else if( currentstate->current >= 0 && currentstate->current <= 70 ){ if( idToType( currentstate->current ) == SEA ){ currentstate->health -= LIFE_LOSS_SEA; } } //check if doublebacked to sea if( pastPlays[i+1] == 'D' ){ //verify double back location from trail array is not sea //HUNTERVIEW if( currentstate->trail[(pastPlays[i+2]-'0')] == SEA_UNKNOWN ){ currentstate->health -= LIFE_LOSS_SEA; } //DRACVIEW else if( (currentstate->trail[(pastPlays[i+2]-'0')]) >= 0 && (currentstate->trail[(pastPlays[i+2]-'0')]) <= 70 ){ if( idToType(currentstate->trail[(pastPlays[i+2]-'0')]) == SEA ){ currentstate->health -= LIFE_LOSS_SEA; } } } //update score due to dracula turn dracView->score -= SCORE_LOSS_DRACULA_TURN; //check if trap placed if( pastPlays[i+3] == 'T' ){ //update traps if(dracView->trapsarray[currentstate->current] < 3){ dracView->trapsarray[currentstate->current]++; dracView->traps++; } } //check if immature vamp placed if( pastPlays[i+4] == 'V' ){ //update vamps dracView->vampsarray[currentstate->current]++; dracView->vamps++; } //check if trap died if( pastPlays[i+5] == 'M' ){ //update traps dracView->traps -= dracView->vampsarray[fallenofftrail]; dracView->vampsarray[fallenofftrail] = 0; } //check if vamp matures if( pastPlays[i+6] == 'V' ){ //update vamps dracView->vampsarray[currentstate->current]--; dracView->vamps--; dracView->score -= SCORE_LOSS_VAMPIRE_MATURES; } } //nowrite else; //determine which player will be acting in the next turn switch( pastPlays[i] ){ case 'G': player = 1; break; case 'S': player = 2; break; case 'H': player = 3; break; case 'M': player = 4; break; case 'D': player = 0; break; default: player = 0xDEADBEEF; break; } dracView->playerturn = player; //move into next play i += 8; } return dracView; }
// Creates a new GameView to summarise the current state of the game GameView newGameView(char *pastPlays, PlayerMessage messages[]) { //REPLACE THIS WITH YOUR OWN IMPLEMENTATION GameView gameView = malloc(sizeof(struct gameView)); //Extract information from the pastPlays //how many characters are there in pastPlays int numberOfChars = 0; while(pastPlays[numberOfChars] != 0){ numberOfChars++; } //Initialise the roundCounter if(numberOfChars == 0){ gameView->roundCounter = 0; }else gameView->roundCounter = (int)numberOfChars/40 + 1; printf("numberOfChars is %d roundCounter is %d\n",numberOfChars,gameView->roundCounter); //Initialise the turn //whoseTurn has to be passed to getCurrentPlayer() gameView->whoseTurn = (numberOfChars+1)/8; //Initialise the game points gameView->gamePoints = GAME_START_SCORE; //gamepoints decreases by one every time dracula's turn has been finished gameView->gamePoints -= (int)(numberOfChars+1)/ 40; //gamepoints decreases by 13 when vampire is mature(six round after dracula place the immature vampire) if(numberOfChars+1 > 520){ int dracVampire = 517; while(pastPlays[dracVampire] != 'V' && dracVampire < numberOfChars){ dracVampire += 40; } int vampireDead = 0; for(int a = dracVampire + 6; a < dracVampire + 40 * 6; a += 8){ int b = dracVampire; while(pastPlays[b] != '.' && ((a-3)/8 % 5) != 4){ if(pastPlays[b] == 'V') vampireDead = 1; b++; } //six rounds if(!vampireDead){ gameView->gamePoints -= SCORE_LOSS_VAMPIRE_MATURES; } } } //Initialise the blood and life points int a = 0; int b = 0; gameView->blood[PLAYER_LORD_GODALMING] = GAME_START_HUNTER_LIFE_POINTS; gameView->blood[PLAYER_DR_SEWARD] = GAME_START_HUNTER_LIFE_POINTS; gameView->blood[PLAYER_VAN_HELSING] = GAME_START_HUNTER_LIFE_POINTS; gameView->blood[PLAYER_MINA_HARKER] = GAME_START_HUNTER_LIFE_POINTS; gameView->blood[PLAYER_DRACULA] = GAME_START_BLOOD_POINTS; //change of hunters' health for(a = 3; a < numberOfChars; a += 8){ b = a; while(pastPlays[b] != '.' && ((a-3)/8 % 5) != 4){ if(pastPlays[b] == 'T'){ gameView->blood[(a-3)/8 % 5] -= LIFE_LOSS_TRAP_ENCOUNTER; if(gameView->blood[(a-3)/8 % 5] < 0) gameView->blood[(a-3)/8 % 5] = GAME_START_HUNTER_LIFE_POINTS; } if(pastPlays[b] == 'D') { gameView->blood[(a-3)/8 % 5] -= LIFE_LOSS_DRACULA_ENCOUNTER; gameView->blood[PLAYER_DRACULA] -= LIFE_LOSS_HUNTER_ENCOUNTER; } b++; } } //change of dracula's blood //dracula hate water for(a = 33; a < numberOfChars; a += 40){ b = a; char message[3]; message[0] = pastPlays[a]; message[1] = pastPlays[a+1]; message[2] = 0; if((message[0] == 'C' && message[1] == '?') || (message[0] == 'H' && message[1] == 'I') || (message[0] == 'T' && message[1] == 'P')){ break; }else if(abbrevToID(message) >= MIN_MAP_LOCATION && abbrevToID(message) <= MAX_MAP_LOCATION){ if(idToType(abbrevToID(message)) == SEA) { gameView->blood[PLAYER_DRACULA] -= 2; } }else if(message[0] == 'S' && message[1] == '?'){ gameView->blood[PLAYER_DRACULA] -= 2; }else if(message[1] >= '1' && message[1] <= '5'){ message[0] = pastPlays[b - 40 * (message[1] - 48)]; message[1] = pastPlays[b - 40 * (message[1] - 48) + 1]; if(message[0] == 'S' && message[1] == '?'){ gameView->blood[PLAYER_DRACULA] -= 2; break; }else if(idToType(abbrevToID(message)) == SEA) gameView->blood[PLAYER_DRACULA] -= 2; } } //Initialise the location if(numberOfChars == 0){ gameView->location[PLAYER_LORD_GODALMING] = UNKNOWN_LOCATION; gameView->location[PLAYER_DR_SEWARD] = UNKNOWN_LOCATION; gameView->location[PLAYER_VAN_HELSING] = UNKNOWN_LOCATION; gameView->location[PLAYER_MINA_HARKER] = UNKNOWN_LOCATION; gameView->location[PLAYER_DRACULA] = UNKNOWN_LOCATION; }else { int first = 0; if(numberOfChars < 32) { first = 1; int a = (39 - numberOfChars)/8; int b = 0; while (b < a){ gameView->location[4-b] = UNKNOWN_LOCATION; b++; } } else{ for(first = numberOfChars - 38;first < numberOfChars; first += 8){ char message[3]; message[0] = pastPlays[first]; message[1] = pastPlays[first+1]; message[2] = 0; printf("%s\n",message); if((first-1)/8 % 5 == 4){ if(message[1] == '?'){ switch(message[0]){ case 'C': gameView->location[PLAYER_DRACULA] = CITY_UNKNOWN; break; case 'S': gameView->location[PLAYER_DRACULA] = SEA_UNKNOWN; break; } }else if(message[0] == 'H' && message[1] == 'I'){ gameView->location[PLAYER_DRACULA] = HIDE; }else if(message[1] >= '1' && message[1] <= '5'){ gameView->location[PLAYER_DRACULA] = DOUBLE_BACK_1 + message[1] - 49; }else if(message[0] == 'T' && message[1] == 'P'){ gameView->location[PLAYER_DRACULA] = TELEPORT; gameView->blood[PLAYER_DRACULA] += LIFE_GAIN_CASTLE_DRACULA; } else{ gameView->location[PLAYER_DRACULA] = abbrevToID(message); if(gameView->location[PLAYER_DRACULA] == CASTLE_DRACULA){ gameView->blood[PLAYER_DRACULA] += LIFE_GAIN_CASTLE_DRACULA; } } }else{ gameView->location[((first-1)/8) % 5] = abbrevToID(message); if (gameView->location[((first-1)/8) % 5] == ST_JOSEPH_AND_ST_MARYS){ gameView->blood[((first-1)/8) % 5] = GAME_START_HUNTER_LIFE_POINTS; gameView->gamePoints -= SCORE_LOSS_HUNTER_HOSPITAL; } if (gameView->roundCounter >= 2){ message[0] = pastPlays[first - 40]; message[1] = pastPlays[first - 39]; if(abbrevToID(message) == gameView->location[(first-1)/8 % 5]){ gameView->blood[(first-1)/8 % 5] += LIFE_GAIN_REST; if(gameView->blood[(first-1)/8 % 5] > 9){ gameView->blood[(first-1)/8 % 5] = GAME_START_HUNTER_LIFE_POINTS; } } } } } } } //initialising the trail a = 0; b = 0; int counter = 0; int totalNumberPlayers = 0; for (a = numberOfChars - 6; a > 0; a -= 8){ int currentPlayer = 0; for(b = a ; b > 0; b -= 40){ currentPlayer = (b-1)/8 % 5; char message[3]; message[0] = pastPlays[b]; message[1] = pastPlays[b+1]; message[2] = 0; if((b-1)/8 % 5 == PLAYER_DRACULA){ if(message[1] == '?'){ switch(message[0]){ case 'C': gameView->trail[PLAYER_DRACULA][counter] = CITY_UNKNOWN; break; case 'S': gameView->trail[PLAYER_DRACULA][counter] = SEA_UNKNOWN; break; } }else if (message[0] == 'H' && message[1] == 'I'){ gameView->trail[PLAYER_DRACULA][counter] = HIDE; }else if (message[1] >= '1' && message[1] <= '5'){ gameView->trail[PLAYER_DRACULA][counter] = DOUBLE_BACK_1 + message[1] - 49; }else if(message[0] == 'T' && message[1] == 'P'){ gameView->trail[PLAYER_DRACULA][counter] = TELEPORT; }else gameView->trail[PLAYER_DRACULA][counter] = abbrevToID(message); }else gameView->trail[currentPlayer][counter] = abbrevToID(message); counter++; if(counter == 6) break; } while(counter < 6){ gameView->trail[currentPlayer][counter] = UNKNOWN_LOCATION; counter++; } counter = 0; totalNumberPlayers++; if(totalNumberPlayers > 4) break; } return gameView; }