From afa02f645056c5823b0d8a29d37c1ff10aedce7a Mon Sep 17 00:00:00 2001 From: root Date: Tue, 27 Feb 2024 21:53:44 -0600 Subject: init --- city.cpp | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 city.cpp (limited to 'city.cpp') diff --git a/city.cpp b/city.cpp new file mode 100644 index 0000000..aa009f9 --- /dev/null +++ b/city.cpp @@ -0,0 +1,227 @@ +#include +#include +#include + +// Programmer: Brett Weiland +// Date: 4/30/23 +// File: city.cpp +// Assignment: SP-B-finalProject +// Purpose: functions for class city. see header for more details + +#include "city.h" + +unsigned int city::rounds_taken = 0; + +city::city(const unsigned int robber_win_value, const unsigned int rounds) + : ROBBER_WIN_VALUE(robber_win_value), MAX_ROUNDS(rounds) { + for(size_t cop_i = 0; cop_i < COPS_COUNT; cop_i++) { + cops[cop_i].includeInMap(this, randomLocation()); + addMapMarker(cops[cop_i]); + } + + for(size_t robber_i = 0; robber_i < ROBBERS_COUNT; robber_i++) { + robbers[robber_i].includeInMap(this, randomLocation()); + addMapMarker(robbers[robber_i]); + robbers[robber_i].setGreedy(robber_i < ROBBERS_GREEDY); + } + + for(size_t jewl_i = 0; jewl_i < JEWL_COUNT; jewl_i++) { + jewls[jewl_i].includeInMap(this, randomLocation()); + addMapMarker(jewls[jewl_i]); + jewls_available[jewl_i] = &jewls[jewl_i]; + } + + renderMap(); + printMap(); +} + +void city::printMap() const { + if(rounds_taken) { + //prints round in middle at top of map + const std::string round_header = "ROUND " + std::to_string(rounds_taken); + const size_t header_size = round_header.length(); + if(header_size > (MAP_WIDTH * 2)) { std::cout << round_header << std::endl; } + else { + for(size_t spacing = 0; spacing < (MAP_WIDTH - ((header_size + 1) / 2.0)); spacing++) + std::cout << " "; + std::cout << round_header << std::endl; + } + } + else { + //initial print before rounds are startred + std::cout << "Initial positions" << std::endl; + } + + for(size_t y = 0; y < MAP_HEIGHT; y++) { + for(size_t x = 0; x < MAP_HEIGHT; x++) { + std::cout << rendered_map[y][x] << " " << std::flush; + } + std::cout << "\r\n"; + } + std::cout << std::endl; +} + +coordinate city::randomLocation() const { + coordinate rand_cord; + do { + rand_cord.set_xy(rand() % MAP_WIDTH, rand() % MAP_HEIGHT); + } while (map_ptr[rand_cord.get_y()][rand_cord.get_x()] != NULL); + return rand_cord; +} + +//see coordinate.h for a descriptions of how directions work. +direction::TYPE city::randomDirection(const coordinate &scanner) const { + direction::TYPE rand_dir; + + direction::TYPE border_map = ( + ((scanner.get_y() <= 0) << direction::N) | + ((scanner.get_x() >= (MAP_WIDTH - 1)) << direction::E) | + ((scanner.get_y() >= (MAP_HEIGHT - 1)) << direction::S) | + ((scanner.get_x() <= 0) << direction::W)); + + do { + rand_dir = ((1 | ((rand() % 2) << 1)) << (rand() % 4)); + rand_dir |= ((rand_dir & (1 << 4)) >> 4); + rand_dir &= (~(border_map) & direction::MASK) ; + } while(!rand_dir); + + return rand_dir; +} + +direction::TYPE city::directionToAnyJewl(const coordinate &scanner) const { + direction::TYPE d = scanner.getDirection(jewls_available[rand() % jewls_available_qty]->getLocation()); + if(d) return d; + return randomDirection(scanner); +} + +gameObject *city::findObjsByLocation(const coordinate loc) { + return map_ptr[loc.get_y()][loc.get_x()]; +} + +direction::TYPE city::nearestCopDirection(const coordinate &scanner) const { + int min_steps = INT_MAX; + int min_cop_id = INT_MAX; + int distance; + const cop *closest_cop; + for(size_t cop_i = 0; cop_i < COPS_COUNT; cop_i++) { + distance = scanner.getSteps(cops[cop_i].getLocation()); + if((distance < min_steps) || + ((distance == min_steps) && (cops[cop_i].get_id() < min_cop_id))) { + min_steps = distance; + min_cop_id = cops[cop_i].get_id(); + closest_cop = &cops[cop_i]; + } + } + return scanner.getDirection(closest_cop->getLocation()); +} + +void city::renderMap() { + const char MAP_EMPTY = '*'; + for(size_t y = 0; y < MAP_HEIGHT; y++) { + for(size_t x = 0; x < MAP_HEIGHT; x++) { + if(map_ptr[y][x] == NULL) { + rendered_map[y][x] = MAP_EMPTY; + continue; + } + rendered_map[y][x] = map_ptr[y][x]->getIcon(); + } + } +} + +void city::addMapMarker(gameObject &item) { + gameObject **map_location = &map_ptr[item.getLocation().get_y()][item.getLocation().get_x()]; + gameObject *lower_item = *map_location; + gameObject *upper_item = NULL; + + while((lower_item != NULL) && (item.get_drawPriority() > lower_item->get_drawPriority())) { + lower_item = lower_item->get_bottom(); + if(upper_item == NULL) { upper_item = *map_location; } + else { upper_item = upper_item->get_bottom(); } + } + if(upper_item != NULL) { upper_item->set_bottom(&item); } + else { *map_location = &item; } + if(lower_item != NULL) { lower_item->set_top(&item); } + item.set_top(upper_item); + item.set_bottom(lower_item); + +} + +void city::delMapMarker(gameObject &item) { + gameObject **map_location = &map_ptr[item.getLocation().get_y()][item.getLocation().get_x()]; + if(item.get_top() != NULL) item.get_top()->set_bottom(item.get_bottom()); + if(item.get_bottom() != NULL) item.get_bottom()->set_top(item.get_top()); + if(&item == *map_location) *map_location = item.get_bottom(); +} + +void city::moveNPC(npc &character) { + if((!character.is_attached()) || (!character.is_active())) return; + delMapMarker(character); + character.move(); + addMapMarker(character); +} + +city::CITY_STATUS city::runTurn() { + rounds_taken += 1; + for(size_t robber_i = 0; robber_i < ROBBERS_COUNT; robber_i++) { + moveNPC(robbers[robber_i]); + if(robbers[0].get_totalRobberValue() >= ROBBER_WIN_VALUE) return CITY_STATUS::ROBBERS_MAX_VAL; + if(allRobbersArrested()) return CITY_STATUS::COPS_WIN; + } + + for(size_t cop_i = 0; cop_i < COPS_COUNT; cop_i++) { + moveNPC(cops[cop_i]); + if(allRobbersArrested()) return CITY_STATUS::COPS_WIN; + } + renderMap(); + if(rounds_taken >= MAX_ROUNDS) return CITY_STATUS::ROUNDS_DEPLETED; + return CITY_STATUS::CONTINUE; +} + +void city::summarize() const { + for(size_t cop_i = 0; cop_i < COPS_COUNT; cop_i++) { + std::cout << "Police ID: " << cops[cop_i].get_id() + << "\n\tConfiscated jewls amount: $" << cops[cop_i].get_inventoryValue() + << "\n\tFinal number of robbers caught: " << cops[cop_i].get_robbersCaught() << "\n\n"; + + } + + for(size_t robber_i = 0; robber_i < ROBBERS_COUNT; robber_i++) { + std::cout << (robbers[robber_i].isGreedy() ? "Greedy" : "Ordinary") + << " Robber ID: " << robbers[robber_i].get_id() + << "\n\tJewls picked up: " << robbers[robber_i].get_inventoryQty() + << "\n\tTotal jewl worth: " << robbers[robber_i].get_inventoryValue() << "\n\n"; + } + std::cout << std::endl; +} + +//I would have liked to set up a linked list for this as well, however I was running out of time. +//Probably would have been nice to set up a generic linked list header type. +void city::markJewlTaken(jewl &item) { + size_t jewl_i; + for(jewl_i = 0; jewls_available[jewl_i] != &item; jewl_i++); //find jewl in array + + //shift all jewls over by 1 at/after position of removed jewls + for(; jewl_i < jewls_available_qty - 1; jewl_i++) + jewls_available[jewl_i] = jewls_available[jewl_i + 1]; + + jewls_available_qty--; +} + +void city::markJewlAvailable(jewl &item) { + jewls_available[jewls_available_qty++] = &item; +} + +void city::freeAllRobbers() { + for(size_t robber_i = 0; robber_i < ROBBERS_COUNT; robber_i++) + robbers[robber_i].free(); + for(size_t cop_i = 0; cop_i < COPS_COUNT; cop_i++) + cops[cop_i].robbersReleased(); + +} + +bool city::allRobbersArrested() const { + for(size_t robber_i = 0; robber_i < ROBBERS_COUNT; robber_i++) + if(robbers[robber_i].is_active()) return false; + + return true; +} -- cgit v1.2.3