Ejemplo n.º 1
0
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;
    }
}
Ejemplo n.º 2
0
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);
    }
}
Ejemplo n.º 3
0
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;
}