phantasia

Phantasia - 2D SDL3 RPG prototype.
git clone git://git.beep.wimdupont.com/phantasia.git
Log | Files | Refs | README | LICENSE

validate.c (3348B)


      1 #include "game/content.h"
      2 #include "engine/validate.h"
      3 
      4 #include <math.h>
      5 #include <stdio.h>
      6 
      7 #define FAIL(...) do { \
      8 	if (error && size) snprintf(error, size, __VA_ARGS__); \
      9 	return -1; \
     10 } while (0)
     11 
     12 static int
     13 ph_asset_valid(int id)
     14 {
     15 	return id >= 0 && id < PH_ASSET_COUNT &&
     16 		(id == PH_ASSET_NONE || (ph_asset_defs[id].path && *ph_asset_defs[id].path));
     17 }
     18 
     19 int
     20 ph_game_validate_content(char *error, size_t size)
     21 {
     22 	PhWorld lookup = { .content = ph_game_world.content };
     23 	int i, j;
     24 
     25 	if (ph_validate_world(&ph_game_world, error, size) < 0 ||
     26 			ph_validate_spells(&ph_player_spellbook, error, size) < 0) return -1;
     27 	for (i = 1; i < PH_AUDIO_COUNT; ++i)
     28 		if (!ph_audio_defs[i].path || !*ph_audio_defs[i].path ||
     29 				!isfinite(ph_audio_defs[i].gain) || ph_audio_defs[i].gain < 0)
     30 			FAIL("audio %d: invalid path or gain", i);
     31 	for (i = 0; i < PH_TILE_DEF_COUNT; ++i) {
     32 		const PhTileDef *tile = &ph_tile_defs[i];
     33 
     34 		if (!ph_asset_valid(tile->asset_id) || !ph_asset_valid(tile->background_asset_id) ||
     35 				tile->sprite_tile_x < 0 || tile->sprite_tile_y < 0 ||
     36 				tile->background_sprite_tile_x < 0 || tile->background_sprite_tile_y < 0)
     37 			FAIL("tile '%c': invalid sprite reference", tile->symbol);
     38 	}
     39 	for (i = 0; i < PH_ITEM_DEF_COUNT; ++i)
     40 		if (!ph_asset_valid(ph_item_defs[i].asset_id))
     41 			FAIL("item %d: invalid asset %d", ph_item_defs[i].id, ph_item_defs[i].asset_id);
     42 	for (i = 0; i < PH_ENTITY_DEF_COUNT; ++i) {
     43 		const PhEntityDef *entity = &ph_entity_defs[i];
     44 
     45 		if (!ph_asset_valid(entity->asset_id)) FAIL("entity %d: invalid asset %d", entity->id, entity->asset_id);
     46 		if (entity->interaction_id && !ph_game_interaction_def(entity->interaction_id))
     47 			FAIL("entity %d: unknown interaction %d", entity->id, entity->interaction_id);
     48 	}
     49 	for (i = 0; i < PH_INTERACTION_COUNT; ++i) {
     50 		const PhInteractionDef *interaction = &ph_interaction_defs[i];
     51 
     52 		if (interaction->id <= 0 || interaction->kind != PH_INTERACTION_SHOP ||
     53 				!ph_game_shop_def(interaction->content_id))
     54 			FAIL("interaction %d: invalid kind or shop %d", interaction->id, interaction->content_id);
     55 		for (j = 0; j < i; ++j)
     56 			if (ph_interaction_defs[j].id == interaction->id) FAIL("interaction %d: duplicate ID", interaction->id);
     57 	}
     58 	for (i = 0; i < PH_SHOP_COUNT; ++i) {
     59 		const PhShopDef *shop = &ph_shop_defs[i];
     60 
     61 		if (shop->id <= 0 || !shop->name || shop->kind < PH_SHOP_ITEMS ||
     62 				shop->kind > PH_SHOP_SPELLS || shop->stock_count < 0 || shop->stock_count > PH_SHOP_STOCK_MAX)
     63 			FAIL("shop %d: invalid definition", shop->id);
     64 		for (j = 0; j < i; ++j)
     65 			if (ph_shop_defs[j].id == shop->id) FAIL("shop %d: duplicate ID", shop->id);
     66 		for (j = 0; j < PH_SHOP_TALK_LINES; ++j)
     67 			if (!shop->talk[j]) FAIL("shop %d: missing talk line %d", shop->id, j);
     68 		for (j = 0; j < shop->stock_count; ++j) {
     69 			const PhItemDef *item = ph_world_item_def(&lookup, shop->stock[j]);
     70 			const PhSpellDef *spell = ph_spellbook_def(&ph_player_spellbook, shop->stock[j]);
     71 			int k;
     72 
     73 			if (shop->kind == PH_SHOP_ITEMS ? (!item || item->buy_value <= 0) : (!spell || spell->buy_value <= 0))
     74 				FAIL("shop %d stock entry %d: invalid %s %d", shop->id, j,
     75 					shop->kind == PH_SHOP_ITEMS ? "item" : "spell", shop->stock[j]);
     76 			for (k = 0; k < j; ++k)
     77 				if (shop->stock[k] == shop->stock[j]) FAIL("shop %d: duplicate stock ID %d", shop->id, shop->stock[j]);
     78 		}
     79 	}
     80 	return 0;
     81 }