char * area_alloc_description(struct area const *area) { int width = area->box.size.width * 10; int length = area->box.size.length * 10; int level = area->box.origin.z; char *description; switch (area->type) { case area_type_chamber: description = str_alloc_formatted("%u' x %u' chamber", width, length); break; case area_type_intersection: description = strdup_or_die("intersection"); break; case area_type_passage: { enum orientation orientation = orientation_from_direction(area->direction); if (orientation_east_to_west == orientation) swap(&width, &length); description = str_alloc_formatted("%u' passage %s", length, orientation_name(orientation)); break; } case area_type_room: description = str_alloc_formatted("%u' x %u' room", width, length); break; case area_type_stairs_down: description = alloc_stairs_description(level + 1, area_type_stairs_down); break; case area_type_stairs_up: description = alloc_stairs_description(level - 1, area_type_stairs_up); break; default: description = str_alloc_formatted("%u' x %u' area", width, length); break; } if (!area->features) return description; if (area->features & area_features_chimney_up) { str_realloc_append_formatted(&description, ", chimney up to "); realloc_append_level_description(&description, level - 1); } if (area->features & area_features_chimney_down) { str_realloc_append_formatted(&description, ", chimney down to "); realloc_append_level_description(&description, level + 1); } if (area->features & area_features_chute_entrance) { str_realloc_append_formatted(&description, ", chute down to "); realloc_append_level_description(&description, level + 1); } if (area->features & area_features_chute_exit) { str_realloc_append_formatted(&description, ", chute down from "); realloc_append_level_description(&description, level - 1); } return description; }
static void realloc_append_level_description(char **s, int level) { if (level <= 0) { str_realloc_append_formatted(s, "surface"); } else { str_realloc_append_formatted(s, "level %i", level); } }
char * dice_alloc_description(struct dice dice) { assert(dice_is_valid(dice)); char *description = NULL; if (!dice.count || !dice.sides) { str_realloc_append_formatted(&description, "0"); } else if (1 == dice.sides) { str_realloc_append_formatted(&description, "%i", dice.count); } else { str_realloc_append_formatted(&description, "%id%i", dice.count, dice.sides); } if (dice.modifier) { str_realloc_append_formatted(&description, "%+i", dice.modifier); } if (1 != dice.multiplier) { str_realloc_append_formatted(&description, "x%i", dice.multiplier); } return description; }
static void str_realloc_format_test(void) { char *str = NULL; str_realloc_append_formatted(&str, "foo"); assert(0 == strcmp("foo", str)); str_realloc_append_formatted(&str, "%s", "bar"); assert(0 == strcmp("foobar", str)); str_realloc_append_formatted(&str, "%c%c%c", 'b', 'a', 'z'); assert(0 == strcmp("foobarbaz", str)); str_realloc_append_formatted(&str, " %i", 42); assert(0 == strcmp("foobarbaz 42", str)); str_realloc_append_formatted(&str, " x %.2f", M_PI); assert(0 == strcmp("foobarbaz 42 x 3.14", str)); str_realloc_append_formatted(&str, " x %i%%", 42); assert(0 == strcmp("foobarbaz 42 x 3.14 x 42%", str)); free_or_die(str); }