Exemplo n.º 1
0
static bool
chimney_up_two_levels(struct digger *digger)
{
    struct area *passage = digger_dig_passage(digger, 1, wall_type_none);
    if (!passage) return false;
    passage->features |= area_features_chimney_up;
    digger_move_backward(digger, 1);
    struct tile *tile = generator_tile_at(digger->generator, digger->point);
    tile->features |= tile_features_chimney_up;
    struct digger *digger_up_1 = generator_copy_digger(digger->generator, digger);
    digger_move_forward(digger, 1);
    
    digger_ascend(digger_up_1, 1);
    if (digger_up_1->point.z < generator_min_level(digger->generator)) {
        generator_delete_digger(digger_up_1->generator, digger_up_1);
        return true;
    }
    
    // TODO: random direction?
    // TODO: random passage/room/chamber?
    // TODO: add chimney to existing area?
    passage = digger_dig_passage(digger_up_1, 1, wall_type_solid);
    if (!passage) return false;
    passage->features |= area_features_chimney_down | area_features_chimney_up;
    digger_move_backward(digger_up_1, 1);
    tile = generator_tile_at(digger_up_1->generator, digger_up_1->point);
    tile->features |= tile_features_chimney_down | tile_features_chimney_up;
    struct digger *digger_up_2 = generator_copy_digger(digger_up_1->generator, digger_up_1);
    digger_move_forward(digger_up_1, 1);
    
    digger_ascend(digger_up_2, 1);
    if (digger_up_2->point.z < generator_min_level(digger->generator)) {
        generator_delete_digger(digger_up_2->generator, digger_up_2);
        return true;
    }
    
    // TODO: random direction?
    // TODO: random passage/room/chamber?
    // TODO: add chimney to existing area?
    passage = digger_dig_passage(digger_up_2, 1, wall_type_solid);
    if (!passage) return false;
    passage->features |= area_features_chimney_up;
    digger_move_backward(digger_up_2, 1);
    tile = generator_tile_at(digger_up_2->generator, digger_up_2->point);
    tile->features |= tile_features_chimney_down;
    digger_move_forward(digger_up_2, 1);
    
    return true;
}
Exemplo n.º 2
0
static void
check_for_chute_down_one_level(struct digger *digger, struct area *area)
{
    if (digger->point.z == generator_max_level(digger->generator)) return;
    
    int score = roll("1d6", digger->generator->rnd);
    if (score == 1) {
        area->features |= area_features_chute_entrance;
        struct digger *chute_digger = generator_copy_digger(digger->generator, digger);
        digger_move_backward(chute_digger, 1);
        struct tile *tile = generator_tile_at(chute_digger->generator, chute_digger->point);
        tile->features |= tile_features_chute_entrance;
        digger_descend(chute_digger, 1);
        // TODO: random direction?
        // TODO: random passage/room/chamber?
        // TODO: add chute to existing area
        struct area *passage = digger_dig_passage(chute_digger, 1, wall_type_solid);
        if (passage) {
            passage->features |= area_features_chute_exit;
            digger_move_backward(chute_digger, 1);
            tile = generator_tile_at(chute_digger->generator, chute_digger->point);
            tile->features |= tile_features_chute_exit;
            digger_move_forward(chute_digger, 1);
        } else {
            generator_delete_digger(chute_digger->generator, chute_digger);
        }
    }
}
static void
generator_add_digger_test(void)
{
    struct dungeon *dungeon = dungeon_alloc();
    
    struct dungeon_options *dungeon_options = dungeon_options_alloc_default();
    struct generator *generator = generator_alloc(dungeon, global_rnd, dungeon_options, NULL, NULL);
    assert(0 == generator->diggers_count);
    
    struct digger *digger1 = generator_add_digger(generator,
                                                  point_make(1, 1, 1),
                                                  direction_north);
    assert(1 == generator->diggers_count);
    
    generator_delete_digger(generator, digger1);
    assert(0 == generator->diggers_count);

    digger1 = generator_add_digger(generator,
                                   point_make(1, 1, 1),
                                   direction_north);
    assert(1 == generator->diggers_count);

    struct digger *digger2 = generator_add_digger(generator,
                                                  point_make(2, 2, 2),
                                                  direction_north);
    assert(2 == generator->diggers_count);
    
    struct digger *digger3 = generator_add_digger(generator,
                                                  point_make(3, 3, 3),
                                                  direction_north);
    assert(3 == generator->diggers_count);
    
    generator_delete_digger(generator, digger2);
    assert(2 == generator->diggers_count);
    assert(digger1 == generator->diggers[0]);
    assert(digger3 == generator->diggers[1]);
    
    generator_delete_digger(generator, digger1);
    assert(1 == generator->diggers_count);
    assert(digger3 == generator->diggers[0]);
    
    generator_free(generator);
    dungeon_options_free(dungeon_options);
    dungeon_free(dungeon);
}
Exemplo n.º 4
0
static bool
dead_end(struct digger *digger)
{
    digger_move_backward(digger, 1);
    check_wall_for_secret_door(digger->generator, digger->point,
                               digger->direction);
    check_wall_for_secret_door(digger->generator, digger->point,
                               direction_90_degrees_left(digger->direction));
    check_wall_for_secret_door(digger->generator, digger->point,
                               direction_90_degrees_right(digger->direction));
    generator_delete_digger(digger->generator, digger);
    return true;
}
Exemplo n.º 5
0
static void
check_wall_for_secret_door(struct generator *generator,
                           struct point point,
                           enum direction direction)
{
    struct tile *inside_tile = generator_tile_at(generator, point);
    struct tile *outside_tile = generator_tile_at(generator,
                                                  point_move(point, 1, direction));
    switch (direction) {
        case direction_north:
            if (wall_type_solid != outside_tile->walls.south) return;
            break;
        case direction_south:
            if (wall_type_solid != inside_tile->walls.south) return;
            break;
        case direction_east:
            if (wall_type_solid != outside_tile->walls.west) return;
            break;
        case direction_west:
            if (wall_type_solid != inside_tile->walls.west) return;
            break;
        default:
            fail("Unrecognized direction %i", direction);
            break;
    }
    
    int score = roll("1d4", generator->rnd);
    if (score == 1) {
        if (tile_type_empty == outside_tile->type) {
            generator_set_wall(generator,
                               inside_tile->point,
                               direction,
                               wall_type_secret_door);
        } else {
            struct digger *door_digger = generator_add_digger(generator,
                                                              point_move(point, 1, direction),
                                                              direction);
            if (!space_beyond_door(door_digger, wall_type_secret_door, false)) {
                generator_delete_digger(generator, door_digger);
            }
        }
    }
}
Exemplo n.º 6
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;
}