void add_construction(region_t ®ion, const int x, const int y, const int z, const std::string type, bool solid, const std::size_t &civ_owner) { const auto idx = mapidx(x,y,z); region.water_level[idx] = 0; region.solid[idx] = false; region.tile_type[idx] = tile_type::FLOOR; region.tile_flags[idx].set(CONSTRUCTION); const auto plasteel = get_material_by_tag("plasteel").get(); region.tile_material[idx] = plasteel; region.tile_vegetation_type[idx] = 0; const auto wood = get_material_by_tag("wood").get(); if (type == "ship_wall") { region.tile_type[idx] = tile_type::WALL; region.solid[idx] = true; region.opaque[idx] = true; region.tile_flags[idx].set(CONSTRUCTION); region.tile_material[idx] = plasteel; } else if (type == "ship_window") { region.tile_type[idx] = tile_type::WINDOW; region.solid[idx] = true; region.opaque[idx] = false; region.tile_flags[idx].set(CONSTRUCTION); region.tile_material[idx] = plasteel; } else if (type == "ship_floor") { region.tile_type[idx] = tile_type::FLOOR; region.solid[idx] = false; region.opaque[idx] = false; region.tile_flags[idx].set(CONSTRUCTION); region.tile_material[idx] = plasteel; } else if (type == "hut_wall") { region.tile_type[idx] = tile_type::WALL; region.solid[idx] = true; region.opaque[idx] = true; region.tile_flags[idx].set(CONSTRUCTION); region.tile_material[idx] = wood; } else if (type == "hut_floor") { region.tile_type[idx] = tile_type::FLOOR; region.solid[idx] = false; region.opaque[idx] = false; region.tile_flags[idx].set(CONSTRUCTION); region.tile_material[idx] = wood; } else if (type == "ship_up") { region.tile_type[idx] = tile_type::STAIRS_UP; region.solid[idx] = false; region.tile_flags[idx].set(CONSTRUCTION); region.tile_material[idx] = plasteel; } else if (type == "ship_down") { region.tile_type[idx] = tile_type::STAIRS_DOWN; region.solid[idx] = false; region.opaque[idx] = false; region.tile_flags[idx].set(CONSTRUCTION); region.tile_material[idx] = plasteel; } else if (type == "ship_updown") { region.tile_type[idx] = tile_type::STAIRS_UPDOWN; region.solid[idx] = false; region.opaque[idx] = false; region.tile_flags[idx].set(CONSTRUCTION); region.tile_material[idx] = plasteel; } else if (type == "hut_upstairs") { region.tile_type[idx] = tile_type::STAIRS_UP; region.solid[idx] = false; region.opaque[idx] = false; region.tile_flags[idx].set(CONSTRUCTION); region.tile_material[idx] = wood; } else if (type == "hut_downstairs") { region.tile_type[idx] = tile_type::STAIRS_DOWN; region.solid[idx] = false; region.opaque[idx] = false; region.tile_flags[idx].set(CONSTRUCTION); region.tile_material[idx] = wood; } else if (type == "hut_updownstairs") { region.tile_type[idx] = tile_type::STAIRS_UPDOWN; region.solid[idx] = false; region.opaque[idx] = false; region.tile_flags[idx].set(CONSTRUCTION); region.tile_material[idx] = wood; } else if (type == "cordex") { add_building("cordex", x, y, z, civ_owner); } else if (type == "solar_panel") { add_building("solar_panel", x, y, z, civ_owner); } else if (type == "cryo_bed") { add_building("cryo_bed", x, y, z, civ_owner); } else if (type == "storage_locker") { region.tile_flags[idx].set(CONSTRUCTION); add_building("storage_locker", x, y, z, civ_owner); } else if (type == "battery") { add_building("battery", x, y, z, civ_owner); } else if (type == "rtg") { add_building("rtg", x, y, z, civ_owner); } else if (type == "small_replicator") { add_building("small_replicator", x, y, z, civ_owner); } else if (type == "campfire") { add_building("camp_fire", x, y, z, civ_owner); } else if (type == "ship_door") { add_building("energy_door", x, y, z, civ_owner); } else if (type == "door") { //std::cout << "Door owner: " << civ_owner << "\n"; add_building("door", x, y, z, civ_owner); } else { std::cout << "Don't know how to build a " << type << "\n"; } }
bool AI_city::add_random_building() { // This filters out any buildings that are just data for Areas. std::vector<Building_type> buildable = get_true_building_types(); int start = rng(0, buildable.size() - 1); bool done = false; for (int i = start + 1; !done && i != start; i++) { if (i == buildable.size()) { i = 0; // Loop around to the start if (start == 0) { done = true; } } Building_type type = buildable[i]; Building_datum* build_dat = Building_data[type]; bool can_build = true; // Check 1: Do we have available employees Citizen_amount jobs = build_dat->jobs; if (free_citizens[jobs.type] <= 0) { can_build = false; } // Check 2: Ensure we can (and want to) pay the maintenance cost for (int n = 0; can_build && n < build_dat->maintenance_cost.size(); n++) { Resource_amount res_amt = build_dat->maintenance_cost[n]; int deficit = resource_production[res_amt.type] - res_amt.amount; // TODO: Don't hardcode this value. if (deficit < -5) { can_build = false; } } // Check 3: Does it make something we want bool good_output = false; for (int n = 0; !good_output && n < build_dat->production.size(); n++) { Resource_amount res_amt = build_dat->production[n]; if (resource_production.count(res_amt.type) == 0) { // If it produces something we don't have, we want it! good_output = true; } else { // Randomly decide if we want more of that resource. If the building gives us // five percent of our current output, it's an even split; the more we already // produce the less likely it is that we want more. int bldg_roll = rng(0, 20 * res_amt.amount); int cur_roll = rng(0, resource_production[res_amt.type]); if (bldg_roll >= cur_roll) { good_output = true; } } } if (!good_output && !build_dat->recipes.empty()) { // If it doesn't have any constant production we want, maybe we want a recipe? for (int n = 0; !good_output && n < build_dat->recipes.size(); n++) { Recipe recipe = build_dat->recipes[n]; // Ensure that we have all the ingredients. bool has_ingredients = false; for (int m = 0; !has_ingredients && m < recipe.resource_ingredients.size(); m++) { Resource_amount res_amt = recipe.resource_ingredients[m]; int max_deficit = recipe.max_deficit; int deficit = resource_production[res_amt.type] - res_amt.amount; if (deficit > max_deficit) { has_ingredients = true; } } for (int m = 0; !has_ingredients && m < recipe.mineral_ingredients.size(); m++) { Mineral_amount min_amt = recipe.mineral_ingredients[m]; int max_deficit = recipe.max_deficit; int deficit = mineral_production[min_amt.type] - min_amt.amount; if (deficit > max_deficit) { has_ingredients = true; } } // If we have the ingredients, verify that we actually want the output (same as // above) if (has_ingredients) { Resource_amount res_amt = recipe.result; if (resource_production.count(res_amt.type) == 0) { // If it produces something we don't have, we want it! good_output = true; } else { // Randomly decide if we want more of that resource. If the building gives us // five percent of our current output, it's an even split; the more we already // produce the less likely it is that we want more. int bldg_roll = rng(0, 20 * res_amt.amount); int cur_roll = rng(0, resource_production[res_amt.type]); if (bldg_roll >= cur_roll) { good_output = true; } } } } // for (int n = 0; !good_output && n < build_dat->recipes.size(); n++) } // if (!good_output && !build_dat->recipes.empty()) if (can_build && good_output) { // We can build it, and we want to build it, so build it! if (add_building(type)) { // add_building() returns false on fail return true; } } } // for (int i = start_type + 1; i != start_type; i++) // If we reach this point, we didn't find a single building we want! return false; }