static void set_action_modifier_defaults(struct options *options, char const *action_string) { switch (options->action) { case action_character: options->character_method = ability_score_generation_method_simple; break; case action_check: options->check_constant = 0; break; case action_dungeon: options->dungeon_type_small = false; options->dungeon_options = dungeon_options_alloc_default(); options->dungeon_options->padding = rnd_next_uniform_value(options->rnd, 2); break; case action_magic: options->magic_count = 10; break; case action_treasure: options->treasure_type = toupper(action_string[0]); break; default: break; } }
void rnd_shuffle(struct rnd *rnd, void *items, size_t item_count, size_t item_size) { if (!rnd) return; if (!items) return; if (item_count < 2) return; if (!item_size) return; char temp[item_size]; for (uint32_t i = 0; i < item_count - 1; ++i) { uint32_t exclusive_upper_bound = (uint32_t)item_count - i; uint32_t j = rnd_next_uniform_value(rnd, exclusive_upper_bound); void *item_i = (char *)items + (i * item_size); void *item_j = (char *)items + ((i + j) * item_size); memcpy(temp, item_i, item_size); memcpy(item_i, item_j, item_size); memcpy(item_j, temp, item_size); } }
static bool chambers(struct digger *digger, enum wall_type entrance_type) { int length = 0; int width = 0; struct area *chamber = NULL; int score = roll("1d20", digger->generator->rnd); if (score <= 2) { // square 20x20 length = 2; width = 2; } else if (score <= 4) { // square 20x20 length = 2; width = 2; } else if (score <= 6) { // square 30x30 length = 3; width = 3; } else if (score <= 8) { // square 40x40 length = 4; width = 4; } else if (score <= 10) { // rectangular 20x30 length = 2; width = 3; } else if (score <= 13) { // rectangular 20x30 length = 2; width = 3; } else if (score <= 15) { // rectangular 30x50 length = 3; width = 5; } else if (score <= 17) { // rectangular 40x60 length = 4; width = 6; } else { // unusual shape and size return false; } if (length != width) { int orientation = rnd_next_uniform_value(digger->generator->rnd, 2); if (orientation) swap(&length, &width); } int max_left_offsets_count = max(length, width); int left_offsets[max_left_offsets_count]; fill_shuffled(digger->generator->rnd, left_offsets, width); for (int i = 0; i < width; ++i) { chamber = digger_dig_chamber(digger, length, width, left_offsets[i], entrance_type); if (chamber) break; } if (!chamber && length != width) { swap(&length, &width); fill_shuffled(digger->generator->rnd, left_offsets, width); for (int i = 0; i < width; ++i) { chamber = digger_dig_chamber(digger, length, width, left_offsets[i], entrance_type); if (chamber) break; } } if (!chamber) return false; // TODO: try smaller chambers? bool check_for_secret_doors = false; int door_count = 0; int passage_count = 0; number_of_exits(digger->generator->rnd, chamber, &door_count, &passage_count, &check_for_secret_doors); for (int i = 0; i < door_count; ++i) { // TODO: don't fail if no possible exit struct digger *exit_digger = exit_location(digger, chamber); if (!exit_digger) return false; if (!space_beyond_door(exit_digger, wall_type_door, false)) return false; } for (int i = 0; i < passage_count; ++i) { // TODO: don't fail if no possible exit struct digger *exit_digger = exit_location(digger, chamber); if (!exit_digger) return false; // TODO: check exit direction if (!digger_dig_passage(exit_digger, 3, wall_type_none)) return false; } if (check_for_secret_doors) { check_area_for_secret_doors(digger->generator, chamber); } generator_delete_digger(digger->generator, digger); return true; }