summaryrefslogtreecommitdiff
path: root/city.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'city.cpp')
-rw-r--r--city.cpp227
1 files changed, 227 insertions, 0 deletions
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 <iostream>
+#include <cstdlib>
+#include <typeinfo>
+
+// 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<jewl> *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<jewl> &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;
+}