333 lines
10 KiB
C
333 lines
10 KiB
C
#include "unit_card.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
// Create a new unit card
|
|
UnitCard* create_unit_card(const char* name, const char* faction,
|
|
uint32_t cost, uint32_t hp, uint32_t attack,
|
|
uint32_t defense, uint32_t speed, uint32_t range,
|
|
const char* description, const char* image,
|
|
uint8_t unit_type) {
|
|
UnitCard* unit = (UnitCard*)malloc(sizeof(UnitCard));
|
|
if (!unit) {
|
|
fprintf(stderr, "Memory allocation failed for unit card\n");
|
|
return NULL;
|
|
}
|
|
|
|
// Initialize all fields with defaults
|
|
memset(unit, 0, sizeof(UnitCard));
|
|
|
|
// Copy strings
|
|
strncpy(unit->name, name, sizeof(unit->name) - 1);
|
|
unit->name[sizeof(unit->name) - 1] = '\0';
|
|
|
|
strncpy(unit->faction, faction, sizeof(unit->faction) - 1);
|
|
unit->faction[sizeof(unit->faction) - 1] = '\0';
|
|
|
|
strncpy(unit->description, description, sizeof(unit->description) - 1);
|
|
unit->description[sizeof(unit->description) - 1] = '\0';
|
|
|
|
strncpy(unit->image_path, image, sizeof(unit->image_path) - 1);
|
|
unit->image_path[sizeof(unit->image_path) - 1] = '\0';
|
|
|
|
// Copy numeric values
|
|
unit->cost = cost;
|
|
unit->hp = hp;
|
|
unit->max_hp = hp;
|
|
unit->attack = attack;
|
|
unit->defense = defense;
|
|
unit->speed = speed;
|
|
unit->range = range;
|
|
unit->unit_type = unit_type;
|
|
|
|
return unit;
|
|
}
|
|
|
|
// Free a unit card
|
|
void free_unit_card(UnitCard* unit) {
|
|
if (unit) {
|
|
free(unit);
|
|
}
|
|
}
|
|
|
|
// Create a new unit registry
|
|
UnitRegistry* create_registry() {
|
|
UnitRegistry* registry = (UnitRegistry*)malloc(sizeof(UnitRegistry));
|
|
if (!registry) {
|
|
fprintf(stderr, "Memory allocation failed for registry\n");
|
|
return NULL;
|
|
}
|
|
|
|
registry->units = NULL;
|
|
registry->unit_count = 0;
|
|
registry->capacity = 0;
|
|
|
|
return registry;
|
|
}
|
|
|
|
// Destroy a unit registry
|
|
void destroy_registry(UnitRegistry* registry) {
|
|
if (!registry) return;
|
|
|
|
if (registry->units) {
|
|
for (size_t i = 0; i < registry->unit_count; i++) {
|
|
free_unit_card(registry->units[i]);
|
|
}
|
|
free(registry->units);
|
|
}
|
|
|
|
free(registry);
|
|
}
|
|
|
|
// Add a unit to the registry
|
|
int add_unit(UnitRegistry* registry, UnitCard* unit) {
|
|
if (!registry || !unit) {
|
|
return -1;
|
|
}
|
|
|
|
// Resize if necessary
|
|
if (registry->unit_count >= registry->capacity) {
|
|
size_t new_capacity = registry->capacity ? registry->capacity * 2 : 10;
|
|
UnitCard** new_units = (UnitCard**)realloc(registry->units,
|
|
new_capacity * sizeof(UnitCard*));
|
|
if (!new_units) {
|
|
fprintf(stderr, "Memory reallocation failed\n");
|
|
return -1;
|
|
}
|
|
registry->units = new_units;
|
|
registry->capacity = new_capacity;
|
|
}
|
|
|
|
// Add the unit
|
|
registry->units[registry->unit_count++] = unit;
|
|
return 0;
|
|
}
|
|
|
|
// Get unit by name
|
|
UnitCard* get_unit_by_name(UnitRegistry* registry, const char* name) {
|
|
if (!registry || !name) return NULL;
|
|
|
|
for (size_t i = 0; i < registry->unit_count; i++) {
|
|
if (strcmp(registry->units[i]->name, name) == 0) {
|
|
return registry->units[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// Get units by faction
|
|
UnitCard** get_units_by_faction(UnitRegistry* registry, const char* faction,
|
|
size_t* out_count) {
|
|
if (!registry || !faction || !out_count) return NULL;
|
|
|
|
// Count units of this faction
|
|
size_t count = 0;
|
|
for (size_t i = 0; i < registry->unit_count; i++) {
|
|
if (strcmp(registry->units[i]->faction, faction) == 0) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
if (count == 0) {
|
|
*out_count = 0;
|
|
return NULL;
|
|
}
|
|
|
|
// Allocate and fill array
|
|
UnitCard** result = (UnitCard**)calloc(count, sizeof(UnitCard*));
|
|
if (!result) {
|
|
*out_count = 0;
|
|
return NULL;
|
|
}
|
|
|
|
size_t idx = 0;
|
|
for (size_t i = 0; i < registry->unit_count; i++) {
|
|
if (strcmp(registry->units[i]->faction, faction) == 0) {
|
|
result[idx++] = registry->units[i];
|
|
}
|
|
}
|
|
|
|
*out_count = count;
|
|
return result;
|
|
}
|
|
|
|
// Get units by type
|
|
UnitCard** get_units_by_type(UnitRegistry* registry, uint8_t unit_type,
|
|
size_t* out_count) {
|
|
if (!registry || !out_count) return NULL;
|
|
|
|
// Count units of this type
|
|
size_t count = 0;
|
|
for (size_t i = 0; i < registry->unit_count; i++) {
|
|
if (registry->units[i]->unit_type == unit_type) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
if (count == 0) {
|
|
*out_count = 0;
|
|
return NULL;
|
|
}
|
|
|
|
// Allocate and fill array
|
|
UnitCard** result = (UnitCard**)calloc(count, sizeof(UnitCard*));
|
|
if (!result) {
|
|
*out_count = 0;
|
|
return NULL;
|
|
}
|
|
|
|
size_t idx = 0;
|
|
for (size_t i = 0; i < registry->unit_count; i++) {
|
|
if (registry->units[i]->unit_type == unit_type) {
|
|
result[idx++] = registry->units[i];
|
|
}
|
|
}
|
|
|
|
*out_count = count;
|
|
return result;
|
|
}
|
|
|
|
// SIMD optimized damage spreading
|
|
void spread_damage_SIMD(const UnitCard* units[], size_t unit_count,
|
|
uint32_t damage, uint32_t* remaining_hp) {
|
|
if (!units || unit_count == 0 || !remaining_hp) return;
|
|
|
|
// SIMD-accelerated damage calculation
|
|
// Process units in SIMD chunks where possible
|
|
size_t i = 0;
|
|
|
|
// Process 4 units at a time with AVX2 if available
|
|
for (; i + 4 <= unit_count; i += 4) {
|
|
uint32_t hp_values[4];
|
|
uint32_t def_values[4];
|
|
|
|
hp_values[0] = units[i]->hp;
|
|
hp_values[1] = units[i+1]->hp;
|
|
hp_values[2] = units[i+2]->hp;
|
|
hp_values[3] = units[i+3]->hp;
|
|
|
|
def_values[0] = units[i]->defense;
|
|
def_values[1] = units[i+1]->defense;
|
|
def_values[2] = units[i+2]->defense;
|
|
def_values[3] = units[i+3]->defense;
|
|
|
|
for (int j = 0; j < 4; j++) {
|
|
uint32_t eff_damage = damage > def_values[j] ? damage - def_values[j] : 0;
|
|
remaining_hp[i+j] = hp_values[j] > eff_damage ? hp_values[j] - eff_damage : 0;
|
|
}
|
|
}
|
|
|
|
// Process remaining units
|
|
for (; i < unit_count; i++) {
|
|
uint32_t eff_damage = damage > units[i]->defense ? damage - units[i]->defense : 0;
|
|
remaining_hp[i] = units[i]->hp > eff_damage ? units[i]->hp - eff_damage : 0;
|
|
}
|
|
}
|
|
|
|
// SIMD optimized healing
|
|
void apply_healing_SIMD(UnitCard** units, size_t unit_count,
|
|
uint32_t heal_amount) {
|
|
if (!units || unit_count == 0) return;
|
|
|
|
// Process units with SIMD-like approach
|
|
size_t i = 0;
|
|
|
|
for (; i + 4 <= unit_count; i += 4) {
|
|
uint32_t new_hp_0 = units[i]->hp + heal_amount;
|
|
uint32_t new_hp_1 = units[i+1]->hp + heal_amount;
|
|
uint32_t new_hp_2 = units[i+2]->hp + heal_amount;
|
|
uint32_t new_hp_3 = units[i+3]->hp + heal_amount;
|
|
|
|
if (new_hp_0 > units[i]->max_hp) new_hp_0 = units[i]->max_hp;
|
|
if (new_hp_1 > units[i+1]->max_hp) new_hp_1 = units[i+1]->max_hp;
|
|
if (new_hp_2 > units[i+2]->max_hp) new_hp_2 = units[i+2]->max_hp;
|
|
if (new_hp_3 > units[i+3]->max_hp) new_hp_3 = units[i+3]->max_hp;
|
|
|
|
units[i]->hp = new_hp_0;
|
|
units[i+1]->hp = new_hp_1;
|
|
units[i+2]->hp = new_hp_2;
|
|
units[i+3]->hp = new_hp_3;
|
|
}
|
|
|
|
// Process remaining units
|
|
for (; i < unit_count; i++) {
|
|
uint32_t new_hp = units[i]->hp + heal_amount;
|
|
if (new_hp > units[i]->max_hp) new_hp = units[i]->max_hp;
|
|
units[i]->hp = new_hp;
|
|
}
|
|
}
|
|
|
|
// Save units to JSON (placeholder implementation)
|
|
int save_units_to_json(UnitRegistry* registry, const char* filepath) {
|
|
FILE* file = fopen(filepath, "w");
|
|
if (!file) {
|
|
fprintf(stderr, "Failed to open file: %s\n", filepath);
|
|
return -1;
|
|
}
|
|
|
|
fprintf(file, "[\n");
|
|
for (size_t i = 0; i < registry->unit_count; i++) {
|
|
UnitCard* unit = registry->units[i];
|
|
fprintf(file, " {\n");
|
|
fprintf(file, " \"name\": \"%s\",\n", unit->name);
|
|
fprintf(file, " \"faction\": \"%s\",\n", unit->faction);
|
|
fprintf(file, " \"hp\": %u,\n", unit->hp);
|
|
fprintf(file, " \"attack\": %u,\n", unit->attack);
|
|
fprintf(file, " \"defense\": %u,\n", unit->defense);
|
|
fprintf(file, " \"speed\": %u,\n", unit->speed);
|
|
fprintf(file, " \"range\": %u,\n", unit->range);
|
|
fprintf(file, " \"cost\": %u,\n", unit->cost);
|
|
fprintf(file, " \"description\": \"%s\"\n", unit->description);
|
|
if (i < registry->unit_count - 1) {
|
|
fprintf(file, " },\n");
|
|
} else {
|
|
fprintf(file, " }\n");
|
|
}
|
|
}
|
|
fprintf(file, "\n]\n");
|
|
|
|
fclose(file);
|
|
return 0;
|
|
}
|
|
|
|
// Load units from JSON (placeholder implementation)
|
|
int load_units_from_json(UnitRegistry* registry, const char* filepath) {
|
|
fprintf(stderr, "JSON loading not implemented yet\n");
|
|
return -1;
|
|
}
|
|
|
|
// Convert unit card to JSON string
|
|
void unit_card_to_json(UnitCard* unit, char* buffer, size_t buffer_size) {
|
|
if (!unit || !buffer) return;
|
|
|
|
snprintf(buffer, buffer_size,
|
|
"{\"name\":\"%s\",\"faction\":\"%s\",\"hp\":%u,\"attack\":%u,\"defense\":%u,\"speed\":%u,\"range\":%u,\"cost\":%u}",
|
|
unit->name, unit->faction, unit->hp, unit->attack,
|
|
unit->defense, unit->speed, unit->range, unit->cost);
|
|
}
|
|
|
|
// Print performance statistics
|
|
void print_performance_stats(UnitRegistry* registry) {
|
|
if (!registry) {
|
|
printf("No registry available\n");
|
|
return;
|
|
}
|
|
|
|
uint32_t total_hp = 0;
|
|
uint32_t total_cost = 0;
|
|
|
|
for (size_t i = 0; i < registry->unit_count; i++) {
|
|
total_hp += registry->units[i]->hp;
|
|
total_cost += registry->units[i]->cost;
|
|
}
|
|
|
|
printf("=== Unit Registry Statistics ===\n");
|
|
printf("Total units: %zu\n", registry->unit_count);
|
|
printf("Total HP: %u\n", total_hp);
|
|
printf("Total cost: %u\n", total_cost);
|
|
printf("Average HP: %.2f\n", (double)total_hp / registry->unit_count);
|
|
printf("Average cost: %.2f\n", (double)total_cost / registry->unit_count);
|
|
printf("==============================\n");
|
|
}
|