Skip to content

Commit

Permalink
feat: Condition count buildings in area (#940)
Browse files Browse the repository at this point in the history
* feat: Condition count buildings in area

fix: Inconsistent counting of buildings

* chore: Refactor defines

* chore: PR comments

Add counting using map_building_at.
Fix enum for BUILDING_ANY.
Fix counting in area for fort types.

* chore: PR comments.
  • Loading branch information
UberWaffe authored Sep 29, 2023
1 parent 9b7eca5 commit b1a70db
Show file tree
Hide file tree
Showing 10 changed files with 469 additions and 135 deletions.
275 changes: 275 additions & 0 deletions src/building/count.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,77 @@

#include "building/building.h"
#include "building/monument.h"
#include "core/array.h"
#include "city/buildings.h"
#include "city/health.h"
#include "figure/figure.h"
#include "map/building.h"
#include "map/grid.h"

static const building_type building_set_farms[] = {
BUILDING_WHEAT_FARM, BUILDING_VEGETABLE_FARM, BUILDING_FRUIT_FARM, BUILDING_OLIVE_FARM,
BUILDING_VINES_FARM, BUILDING_PIG_FARM
};

#define BUILDING_SET_SIZE_FARMS (sizeof(building_set_farms) / sizeof(building_type))

static const building_type building_set_raw_materials[] = {
BUILDING_MARBLE_QUARRY, BUILDING_IRON_MINE, BUILDING_TIMBER_YARD, BUILDING_CLAY_PIT,
BUILDING_GOLD_MINE, BUILDING_STONE_QUARRY, BUILDING_SAND_PIT
};

#define BUILDING_SET_SIZE_RAW_MATERIALS (sizeof(building_set_raw_materials) / sizeof(building_type))

static const building_type building_set_workshops[] = {
BUILDING_WINE_WORKSHOP, BUILDING_OIL_WORKSHOP, BUILDING_WEAPONS_WORKSHOP, BUILDING_FURNITURE_WORKSHOP,
BUILDING_POTTERY_WORKSHOP, BUILDING_CONCRETE_MAKER, BUILDING_BRICKWORKS, BUILDING_CITY_MINT
};

#define BUILDING_SET_SIZE_WORKSHOPS (sizeof(building_set_workshops) / sizeof(building_type))

static const building_type building_set_small_temples[] = {
BUILDING_SMALL_TEMPLE_CERES, BUILDING_SMALL_TEMPLE_NEPTUNE, BUILDING_SMALL_TEMPLE_MERCURY, BUILDING_SMALL_TEMPLE_MARS,
BUILDING_SMALL_TEMPLE_VENUS
};

#define BUILDING_SET_SIZE_SMALL_TEMPLES (sizeof(building_set_small_temples) / sizeof(building_type))

static const building_type building_set_large_temples[] = {
BUILDING_LARGE_TEMPLE_CERES, BUILDING_LARGE_TEMPLE_NEPTUNE, BUILDING_LARGE_TEMPLE_MERCURY, BUILDING_LARGE_TEMPLE_MARS,
BUILDING_LARGE_TEMPLE_VENUS
};

#define BUILDING_SET_SIZE_LARGE_TEMPLES (sizeof(building_set_large_temples) / sizeof(building_type))

static const building_type building_set_grand_temples[] = {
BUILDING_GRAND_TEMPLE_CERES, BUILDING_GRAND_TEMPLE_NEPTUNE, BUILDING_GRAND_TEMPLE_MERCURY, BUILDING_GRAND_TEMPLE_MARS,
BUILDING_GRAND_TEMPLE_VENUS, BUILDING_PANTHEON
};

#define BUILDING_SET_SIZE_GRAND_TEMPLES (sizeof(building_set_grand_temples) / sizeof(building_type))

static const building_type building_set_deco_trees[] = {
BUILDING_PINE_TREE, BUILDING_FIR_TREE, BUILDING_OAK_TREE, BUILDING_ELM_TREE,
BUILDING_FIG_TREE, BUILDING_PLUM_TREE, BUILDING_PALM_TREE, BUILDING_DATE_TREE
};

#define BUILDING_SET_SIZE_DECO_TREES (sizeof(building_set_deco_trees) / sizeof(building_type))

static const building_type building_set_deco_paths[] = {
BUILDING_PINE_PATH, BUILDING_FIR_PATH, BUILDING_OAK_PATH, BUILDING_ELM_PATH,
BUILDING_FIG_PATH, BUILDING_PLUM_PATH, BUILDING_PALM_PATH, BUILDING_DATE_PATH,
BUILDING_GARDEN_PATH
};

#define BUILDING_SET_SIZE_DECO_PATHS (sizeof(building_set_deco_paths) / sizeof(building_type))

static const building_type building_set_deco_statues[] = {
BUILDING_GARDENS, BUILDING_GRAND_GARDEN, BUILDING_SMALL_STATUE, BUILDING_MEDIUM_STATUE,
BUILDING_LARGE_STATUE, BUILDING_SMALL_STATUE_ALT, BUILDING_SMALL_STATUE_ALT_B, BUILDING_LEGION_STATUE,
BUILDING_GLADIATOR_STATUE, BUILDING_SMALL_POND, BUILDING_LARGE_POND, BUILDING_DOLPHIN_FOUNTAIN
};

#define BUILDING_SET_SIZE_DECO_STATUES (sizeof(building_set_deco_statues) / sizeof(building_type))

int building_count_grand_temples(void)
{
Expand Down Expand Up @@ -48,6 +116,26 @@ int building_count_total(building_type type)
return total;
}

int building_count_any_total(int active_only)
{
int total = 0;
for (int id = 1; id < building_count(); id++) {
building *b = building_get(id);
if (b == building_main(b)) {
if (active_only) {
if (building_is_active(b)) {
total++;
}
} else {
if (b->state == BUILDING_STATE_IN_USE || b->state == BUILDING_STATE_CREATED) {
total++;
}
}
}
}
return total;
}

int building_count_upgraded(building_type type)
{
int upgraded = 0;
Expand All @@ -59,6 +147,193 @@ int building_count_upgraded(building_type type)
return upgraded;
}

int building_count_in_area(building_type type, int minx, int miny, int maxx, int maxy)
{
int grid_area = abs((maxx - minx) * (maxy - miny));
int array_size = grid_area < building_count() ? grid_area : building_count();
int *found_buildings = (int *) malloc(array_size * sizeof(int));

int total = 0;
for (int x = minx; x <= maxx; x++) {
for (int y = miny; y <= maxy; y++) {
int grid_offset = map_grid_offset(x, y);
int building_id = map_building_at(grid_offset);
if (building_id) {
building *b = building_main(building_get(building_id));
if (type != BUILDING_ANY && b->type != type) {
continue;
}
if (b->state != BUILDING_STATE_IN_USE && b->state != BUILDING_STATE_CREATED) {
continue;
}

for (int i = 0; i < total; i++) {
if (found_buildings[i] == b->id) {
continue;
}
}

found_buildings[total] = b->id;
total++;
}
}
}

free(found_buildings);
return total;
}

int building_count_fort_type_in_area(int minx, int miny, int maxx, int maxy, figure_type type)
{
int grid_area = abs((maxx - minx) * (maxy - miny));
int array_size = grid_area < building_count() ? grid_area : building_count();
int *found_buildings = (int *) malloc(array_size * sizeof(int));

int total = 0;
for (int x = minx; x <= maxx; x++) {
for (int y = miny; y <= maxy; y++) {
int grid_offset = map_grid_offset(x, y);
int building_id = map_building_at(grid_offset);
if (building_id) {
building *b = building_main(building_get(building_id));
if (b->type != BUILDING_FORT || b->subtype.fort_figure_type != type) {
continue;
}
if (b->state != BUILDING_STATE_IN_USE && b->state != BUILDING_STATE_CREATED) {
continue;
}

for (int i = 0; i < total; i++) {
if (found_buildings[i] == b->id) {
continue;
}
}

found_buildings[total] = b->id;
total++;
}
}
}

free(found_buildings);
return total;
}

static int building_count_with_active_check(building_type type, int active_only)
{
if (active_only) {
return building_count_active(type);
} else {
return building_count_total(type);
}
}

static int count_all_types_in_set(int active_only, const building_type *set, int count)
{
int total = 0;
for (int i = 0; i < count; i++) {
building_type type = set[i];
total += building_count_with_active_check(type, active_only);
}
return total;
}

static int count_all_types_in_set_in_area(const building_type *set, int count, int minx, int miny, int maxx, int maxy)
{
int total = 0;
for (int i = 0; i < count; i++) {
building_type type = set[i];
total += building_count_in_area(type, minx, miny, maxx, maxy);
}
return total;
}

int building_set_count_farms(int active_only)
{
return count_all_types_in_set(active_only, building_set_farms, BUILDING_SET_SIZE_FARMS);
}

int building_set_count_raw_materials(int active_only)
{
return count_all_types_in_set(active_only, building_set_raw_materials, BUILDING_SET_SIZE_RAW_MATERIALS);
}

int building_set_count_workshops(int active_only)
{
return count_all_types_in_set(active_only, building_set_workshops, BUILDING_SET_SIZE_WORKSHOPS);
}

int building_set_count_small_temples(int active_only)
{
return count_all_types_in_set(active_only, building_set_small_temples, BUILDING_SET_SIZE_SMALL_TEMPLES);
}

int building_set_count_large_temples(int active_only)
{
return count_all_types_in_set(active_only, building_set_large_temples, BUILDING_SET_SIZE_LARGE_TEMPLES);
}

int building_set_count_deco_trees(void)
{
return count_all_types_in_set(0, building_set_deco_trees, BUILDING_SET_SIZE_DECO_TREES);
}

int building_set_count_deco_paths(void)
{
return count_all_types_in_set(0, building_set_deco_paths, BUILDING_SET_SIZE_DECO_PATHS);
}

int building_set_count_deco_statues(void)
{
return count_all_types_in_set(0, building_set_deco_statues, BUILDING_SET_SIZE_DECO_STATUES);
}

int building_set_area_count_farms(int minx, int miny, int maxx, int maxy)
{
return count_all_types_in_set_in_area(building_set_farms, BUILDING_SET_SIZE_FARMS, minx, miny, maxx, maxy);
}

int building_set_area_count_raw_materials(int minx, int miny, int maxx, int maxy)
{
return count_all_types_in_set_in_area(building_set_raw_materials, BUILDING_SET_SIZE_RAW_MATERIALS, minx, miny, maxx, maxy);
}

int building_set_area_count_workshops(int minx, int miny, int maxx, int maxy)
{
return count_all_types_in_set_in_area(building_set_workshops, BUILDING_SET_SIZE_WORKSHOPS, minx, miny, maxx, maxy);
}

int building_set_area_count_small_temples(int minx, int miny, int maxx, int maxy)
{
return count_all_types_in_set_in_area(building_set_small_temples, BUILDING_SET_SIZE_SMALL_TEMPLES, minx, miny, maxx, maxy);
}

int building_set_area_count_large_temples(int minx, int miny, int maxx, int maxy)
{
return count_all_types_in_set_in_area(building_set_large_temples, BUILDING_SET_SIZE_LARGE_TEMPLES, minx, miny, maxx, maxy);
}

int building_set_area_count_grand_temples(int minx, int miny, int maxx, int maxy)
{
return count_all_types_in_set_in_area(building_set_grand_temples, BUILDING_SET_SIZE_GRAND_TEMPLES, minx, miny, maxx, maxy);
}

int building_set_area_count_deco_trees(int minx, int miny, int maxx, int maxy)
{
return count_all_types_in_set_in_area(building_set_deco_trees, BUILDING_SET_SIZE_DECO_TREES, minx, miny, maxx, maxy);
}

int building_set_area_count_deco_paths(int minx, int miny, int maxx, int maxy)
{
return count_all_types_in_set_in_area(building_set_deco_paths, BUILDING_SET_SIZE_DECO_PATHS, minx, miny, maxx, maxy);
}

int building_set_area_count_deco_statues(int minx, int miny, int maxx, int maxy)
{
return count_all_types_in_set_in_area(building_set_deco_statues, BUILDING_SET_SIZE_DECO_STATUES, minx, miny, maxx, maxy);
}


int building_count_active_fort_type(figure_type type)
{
int active = 0;
Expand Down
67 changes: 66 additions & 1 deletion src/building/count.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ int building_count_active(building_type type);
*/
int building_count_total(building_type type);

/**
* Returns the building count of all building types
* @param active_only Only count the building if it is active
* @return Total number of buildings
*/
int building_count_any_total(int active_only);

/**
* Returns the upgraded building count for the type
* @param type Building type
Expand All @@ -42,9 +49,67 @@ int building_count_grand_temples(void);
* Returns the total number of active grand temples
* @return Number of active grand temples
*/
int building_count_grand_temples(void);
int building_count_grand_temples_active(void);

/**
* Returns the building count for the type in the given area
* @param type Building type
* @param minx Minimum x-axis value of the area to count in
* @param miny Minimum y-axis value of the area to count in
* @param maxx Maximum x-axis value of the area to count in
* @param maxy Maximum y-axis value of the area to count in
* @return Total number of buildings
*/
int building_count_in_area(building_type type, int minx, int miny, int maxx, int maxy);

/**
* Returns the building count for any type in the given area
* @param minx Minimum x-axis value of the area to count in
* @param miny Minimum y-axis value of the area to count in
* @param maxx Maximum x-axis value of the area to count in
* @param maxy Maximum y-axis value of the area to count in
* @param type Figure type
* @return Total number of buildings
*/
int building_count_fort_type_in_area(int minx, int miny, int maxx, int maxy, figure_type type);

/**
* Returns the total number of buildings (where the type is from the set of buildings)
* @param active_only Only count the building if it is active
* @return Number of buildings
*/
int building_set_count_farms(int active_only);
int building_set_count_raw_materials(int active_only);
int building_set_count_workshops(int active_only);
int building_set_count_small_temples(int active_only);
int building_set_count_large_temples(int active_only);

/**
* Returns the total number of buildings (where the type is from the set of buildings)
* @return Number of buildings
*/
int building_set_count_deco_trees(void);
int building_set_count_deco_paths(void);
int building_set_count_deco_statues(void);

/**
* Returns the total number of buildings (where the type is from the set of buildings) in the given area
* @param minx Minimum x-axis value of the area to count in
* @param miny Minimum y-axis value of the area to count in
* @param maxx Maximum x-axis value of the area to count in
* @param maxy Maximum y-axis value of the area to count in
* @return Number of buildings
*/
int building_set_area_count_farms(int minx, int miny, int maxx, int maxy);
int building_set_area_count_raw_materials(int minx, int miny, int maxx, int maxy);
int building_set_area_count_workshops(int minx, int miny, int maxx, int maxy);
int building_set_area_count_small_temples(int minx, int miny, int maxx, int maxy);
int building_set_area_count_large_temples(int minx, int miny, int maxx, int maxy);
int building_set_area_count_grand_temples(int minx, int miny, int maxx, int maxy);
int building_set_area_count_deco_trees(int minx, int miny, int maxx, int maxy);
int building_set_area_count_deco_paths(int minx, int miny, int maxx, int maxy);
int building_set_area_count_deco_statues(int minx, int miny, int maxx, int maxy);

/**
* Returns the active building count for forts based on the assigned soldier (figure) type
* @param type Figure type
Expand Down
1 change: 1 addition & 0 deletions src/building/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* Building types
*/
typedef enum {
BUILDING_ANY = 0,
BUILDING_NONE = 0,
BUILDING_MENU_FARMS = 2,
BUILDING_MENU_RAW_MATERIALS = 3,
Expand Down
2 changes: 2 additions & 0 deletions src/scenario/condition_types/condition_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ int scenario_condition_type_is_met(scenario_condition_t *condition)
return scenario_condition_type_building_count_active_met(condition);
case CONDITION_TYPE_BUILDING_COUNT_ANY:
return scenario_condition_type_building_count_any_met(condition);
case CONDITION_TYPE_BUILDING_COUNT_AREA:
return scenario_condition_type_building_count_area_met(condition);
case CONDITION_TYPE_CITY_POPULATION:
return scenario_condition_type_city_population_met(condition);
case CONDITION_TYPE_COUNT_OWN_TROOPS:
Expand Down
Loading

0 comments on commit b1a70db

Please sign in to comment.