Exemple #1
0
// Returns the number of direct connections between two nodes
// Also fills the type[] array with the various connection types
// Returns 0 if no direct connection (i.e. not adjacent in graph)
int connections(Map g, LocationID start, LocationID end, TransportID type[])
{
   int numConnections = 0;
    
   assert(g != NULL);
   if (!validPlace(start) || !validPlace(end)) {
        fprintf(stderr, "Map.c: connections(): start location(%d) || end locations(%d) not valid", start, end);
        return numConnections;
   } 

   VList curr = g->connections[start];
   while (curr != NULL) {

      // Check for regular connections
      if (curr->v == end) {
         type[numConnections] = curr->type;
         numConnections++;

      // Check for connections via a common sea
      } else if (idToType(curr->v) == SEA) {
         VList endCurr = g->connections[end];
         while (endCurr != NULL) {
            if (endCurr->v == curr->v) {
               type[numConnections] = curr->type;
               numConnections++;
            }
            endCurr = endCurr->next;
         }
      }
      curr = curr->next;
   }
   return numConnections;
}
Exemple #2
0
/*  This function returns true if input locations have a connection of type 
    and false if there is no connection */
int haveConnectionByType (Map g, LocationID from, LocationID to, TransportID type, PlayerID player)
{
    if (!validPlace(from) || !validPlace(to)) {
        fprintf(stderr, "Map.c: haveConnectionByType(): Invalid location input: %d ----> %d", from, to);
        return 0;
    }
    VList curr;
    for (curr = g->connections[from]; curr->next != NULL; curr = curr->next) 
        if (curr->v == to && (curr->type == type || 
           (type == ANY && player != PLAYER_DRACULA))) return 1;
    
    if (curr->v == to && (curr->type == type || 
       (type == ANY && player != PLAYER_DRACULA))) return 1;
    
    return 0;
}
Exemple #3
0
/*  Input: a locationID, transportID and a Map  
    Returns: the input pointer to an array with all adjacent nodes connected by 
            type transportID  */
LocationID *allAdjacent (Map g, LocationID loc, TransportID type, LocationID *adjacent)
{
    #ifdef DEBUG
        if (g == NULL) {
            fprintf(stderr, "Map.c:allAdjacent(): Map input == NULL");
            abort();
        }
        if (!validPlace(loc)) {
        fprintf(stderr, "Map.c: allAdjacent(): Invalid location input");
        abort();
    }
    #else 
        if (loc < MIN_MAP_LOCATION || loc > MAX_MAP_LOCATION)
            return adjacent;
    #endif    
        
    // traverse list[loc] and find all locations of transportID type
    VList curr = g->connections[loc];
    int i = 0;
    do {
        if (curr->type == type) { 
            adjacent[i] = curr->v; 
            i++;            
        }
        curr = curr->next;
    } while (curr != NULL);
    
    return adjacent;
}
LocationID *connectedLocations(GameView currentView, int *numLocations,
        LocationID from, PlayerID player, Round round,
        int road, int rail, int sea)
{
    assert(currentView != NULL);
    assert(numLocations != NULL);
    assert(validPlace(from));
    assert(0 <= player && player < NUM_PLAYERS);
    
    int i, j, k;

    // our map
    Map ourMap = newMap();

    // boolean array storing whether or not we can reach each vertex
    int canReach[NUM_MAP_LOCATIONS];

    // initialise it
    for(i=0;i<NUM_MAP_LOCATIONS;i++) {
        canReach[i] = FALSE;
    }
    
    // remember we can always reach ourselves
    canReach[from] = TRUE;

    // pairwise shortest rail distances
    int railDist[NUM_MAP_LOCATIONS][NUM_MAP_LOCATIONS];

    // floyd warshall to calculate pariwse shortest paths.

    // initialise distances
    for(i=0;i<NUM_MAP_LOCATIONS;i++) {
        for(j=0;j<NUM_MAP_LOCATIONS;j++) {
            if(i == j) {
                railDist[i][j] = 0;
            } else {
                int edgeDist = getDist(ourMap, RAIL, i, j);
                if(edgeDist == NO_EDGE) {
                    edgeDist = INFINITY;
                }
                railDist[i][j] = edgeDist;
            }
        }
    }

    // floyd warshall time!
    for(j=0;j<NUM_MAP_LOCATIONS;j++) {
        for(i=0;i<NUM_MAP_LOCATIONS;i++) {
            for(k=0;k<NUM_MAP_LOCATIONS;k++) {
                railDist[i][k] = min(railDist[i][k], railDist[i][j] + railDist[j][k]);
            }
        }
    }

    // actually do the thing
    
    // invoke special rules: transform road, rail and sea not just to store
    // TRUE/FALSE but to store the maximum number of edges of that type we can
    // move in

    if(rail == TRUE) {
        if(player == PLAYER_DRACULA) {
            // dracula can't move by rail
            rail = 0;
        } else {
            // determine how far hunters can move by rail
            rail = (round+player) % RAIL_RESTRICT;
        }
    } else {
        rail = 0;
    }

//    D("rail=%d\n",rail);

    // add rail links
    for(i=0;i<NUM_MAP_LOCATIONS;i++) {
        if(railDist[from][i] <= rail) {
            canReach[i] = TRUE;
        }
    }

    if(road == TRUE) {
        road = 1;
    } else {
        road = 0;
    }

    // add road links
    for(i=0;i<NUM_MAP_LOCATIONS;i++) {
        int distHere = getDist(ourMap, ROAD, from, i);
        if(distHere != NO_EDGE && distHere <= road) {
            canReach[i] = TRUE;
        }
    }

    if(sea == TRUE) {
        sea = 1;
    } else {
        sea = 0;
    }

    // add sea links
    for(i=0;i<NUM_MAP_LOCATIONS;i++) {
        int distHere = getDist(ourMap, BOAT, from, i);
        if(distHere != NO_EDGE && distHere <= sea) {
            canReach[i] = TRUE;
        }
    }

    // ensure Dracula can't move to the hospital
    if(player == PLAYER_DRACULA) {
        canReach[ST_JOSEPH_AND_ST_MARYS] = FALSE;
    }

    // output

    // work out numLocations; initialise it to be 0
    (*numLocations) = 0;

    // count number of locations
    for(i=0;i<NUM_MAP_LOCATIONS;i++) {
        if(canReach[i] == TRUE) {
            (*numLocations)++;
        }
    }

    // our return array; big enough to conserve memory
    LocationID *ret = 
        (LocationID *)(malloc((*numLocations) * sizeof(LocationID)));

    // current index we're up to
    int upto = 0;
    for(i=0;i<NUM_MAP_LOCATIONS;i++) {
        if(canReach[i] == TRUE) {
            ret[upto] = i;
            upto++;
        }
    }

    return ret;
}
// 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;
}
// 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;
}
// given a Place number, return its type
int idToType(LocationID p)
{
    assert(validPlace(p));
    return places[p].type;
}
// Find out what minions are placed at the specified location
void whatsThere(DracView currentView, LocationID where,
                   int *numTraps, int *numVamps) {
   
   DracView dv;
   int count;
   LocationID trail[TRAIL_SIZE] = { -1 };
   LocationID whereType;
   int index;
   int round;
   int trapSetRound;

   dv = currentView;
   count = 0;
   whereType = idToType(where);
   *numTraps = 0;
   *numVamps = 0;
   index = dv->pastPlaysIndex[PLAYER_DRACULA];
   round = getLastRound(dv, PLAYER_DRACULA);
   trapSetRound = -1;

   // printf("whatsThere: round is: %d, currRound: %d\n", round, getRound(dv->gv));

   /* 
    * 1. Get minions placed by Drac
    *       1a. Get Drac's trail
    *       1b. if city is in the trail: increment for any traps/vamps
    *
    * 2. If traps found: 
    *       2a. get each hunter's trail
    *       2b. check if city is in hunter's trail, AND if traps/vamps
    *             have been encountered
    *       2c. if traps/vamps have been encountered, decrement them
    */ 


   // 1. Get minions placed by Drac

   // 'where' restrictions:
   //    - not in the sea,
   //    - is a valid city number,
   //    - not the hospital

   if (whereType != SEA && validPlace(where) && 
                  where != ST_JOSEPH_AND_ST_MARYS) {

      // 1a.
      getHistory(dv->gv, PLAYER_DRACULA, trail);

      
      // 1b. Store the traps set by Drac within that city, if applicable

      // if 'where' is within the trail
      while (count < TRAIL_SIZE) {
         // Starting at the latest round, check if the city the user 
         // wants to check is in drac's trail. 
         // If so, increment if any traps or vamps are there and note
         // which round in which they were set by Drac

         if (trail[count] == where) {

            // index+3 and index+4: the indices where
            //             dracula's encounters will be stored

            if (dv->past[((round - count) * ROUND_LENGTH) + (index + MINION_ONE)] == 'T') {
               *numTraps += 1;
               //printf("yep0: loc[%c%c], round: %d, count: %d\n",dv->past[((round-count) * ROUND_LENGTH) + index+1], dv->past[((round-count) * ROUND_LENGTH) + index+2], round, count);
            } else if (dv->past[((round - count) * ROUND_LENGTH) + (index + MINION_ONE)] == 'V') {
               *numVamps += 1;
            }

            if (dv->past[((round - count) * ROUND_LENGTH) + (index + MINION_TWO)] == 'T') {
               *numTraps += 1;
            } else if (dv->past[((round - count) * ROUND_LENGTH) + (index + MINION_TWO)] == 'V') {
               *numVamps += 1;
            }

            // break out of the loop since 'where' can only be 
            // in the trail once
            trapSetRound = round - count;
            count = TRAIL_SIZE;
         }

         count += 1;
      }
   }

   //printf("found drac's: at %s, traps: %d, vamps: %d\n", idToName(where), *numTraps, *numVamps);


   // 2. If traps found

   // Traps have been found at the given city.
   // Check to see if any hunters have visited that city since,
   // hence encountering and disabling that trap/vamp
   if (trapSetRound != -1 && *numTraps > 0 && *numVamps > 0) {
      int hunter;
      int index;

      hunter = 0;

      // go through all hunter's (NUM_PLAYERS-1) trails**
      // if a hunter has visited the 'where' city, and has
      // encountered a trap/vamp, then decrement trap/vamp
      //
      // **since drac's and hunter's giveMeTheTrails are out of sync,
      // go through the pastPlays string
      // Will need to do that anyway because we need to check the string
      // for T&V encounters
      while (hunter < NUM_PLAYERS-1) {
         index = dv->pastPlaysIndex[hunter];
         round = getLastRound(dv, hunter);
         

         for (count = 0; count < TRAIL_SIZE; count++) {
            if (getRoundLocation(dv, round, hunter) == where) {
               if (dv->past[(round * ROUND_LENGTH) + (index + MINION_ONE)] == 'T') {
                  *numTraps -= 1;
               } else if (dv->past[(round * ROUND_LENGTH) + (index + MINION_ONE)] == 'V') {
                  *numTraps -= 1;
               }

               if (dv->past[(round * ROUND_LENGTH) + (index + MINION_TWO)] == 'T') {
                  *numTraps -= 1;
               } else if (dv->past[(round * ROUND_LENGTH) + (index + MINION_TWO)] == 'V') {
                  *numTraps -= 1;
               }
            }

            round -= 1;
         }
         
         hunter += 1;
      }
   }

   // printf("where: %s (%d), numTraps: %d, numVamps: %d\n", idToName(where), where, *numTraps, *numVamps);
}
Exemple #9
0
// given a Place number, return its name
char *idToName(LocationID p)
{
   assert(validPlace(p));
   return places[p].name;
}