예제 #1
0
TbBool jailbreak_possible(struct Room *room, long plyr_idx)
{
    unsigned long i;
    unsigned long k;
    struct SlabMap *slb;
    if (room->owner == plyr_idx) {
        return false;
    }
    k = 0;
    i = room->slabs_list;
    while (i > 0)
    {
        slb = get_slabmap_direct(i);
        if (slabmap_block_invalid(slb))
        {
            ERRORLOG("Jump to invalid room slab detected");
            break;
        }
        if (slab_by_players_land(plyr_idx, slb_num_decode_x(i), slb_num_decode_y(i)))
            return true;
        i = get_next_slab_number_in_room(i);
        k++;
        if (k > map_tiles_x * map_tiles_y)
        {
            ERRORLOG("Infinite loop detected when sweeping room slabs");
            break;
        }
    }
    return false;
}
예제 #2
0
/**
 * Finds a creature passing by a room and having job different than given one, which has direct combat sight for given creature.
 * If such creature is not found, the function returns false and gives closest creature passing by a room and having job different than given one.
 * @param creatng The creature which should have combat sight of the target.
 * @param job_kind The job target should'n be performing.
 * @param room The room on which target creature is searched.
 * @param found_dist Distance to the target creature found.
 * @param found_thing The target creature found, either closest one or one with combat sight.
 * @return True if a target with combat sight was found. False if closest creature was found, or no creature met the conditions.
 * @note If no creature met the conditions, output variables are not initialized. Therefore, they should be initialized before calling this function.
 */
TbBool find_combat_target_passing_by_room_but_having_unrelated_job(const struct Thing *creatng, CreatureJob job_kind, const struct Room *room, unsigned long *found_dist, struct Thing **found_thing)
{
    unsigned long i;
    unsigned long k;
    k = 0;
    i = room->slabs_list;
    while (i > 0)
    {
        MapSubtlCoord slb_x,slb_y;
        slb_x = slb_num_decode_x(i);
        slb_y = slb_num_decode_y(i);
        // Per-slab code
        if (find_combat_target_passing_by_slab_but_having_unrelated_job(creatng, job_kind, slb_x, slb_y, found_dist, found_thing)) {
            return true;
        }
        // Per-slab code ends
        i = get_next_slab_number_in_room(i);
        k++;
        if (k > room->slabs_count)
        {
            ERRORLOG("Infinite loop detected when sweeping room slabs");
            break;
        }
    }
    // If found a creature, but it's not on sight
    return false;
}
예제 #3
0
TbBool setup_head_for_random_unused_lair_slab(struct Thing *creatng, struct Room *room)
{
    SlabCodedCoords slbnum;
    long n;
    unsigned long k;
    n = ACTION_RANDOM(room->slabs_count);
    slbnum = room->slabs_list;
    for (k = n; k > 0; k--)
    {
        if (slbnum == 0)
            break;
        slbnum = get_next_slab_number_in_room(slbnum);
    }
    if (slbnum == 0) {
        ERRORLOG("Taking random slab (%d/%d) in %s index %d failed - internal inconsistency.",(int)n,(int)room->slabs_count,room_code_name(room->kind),(int)room->index);
        slbnum = room->slabs_list;
    }
    k = 0;
    while (1)
    {
        MapSlabCoord slb_x,slb_y;
        slb_x = slb_num_decode_x(slbnum);
        slb_y = slb_num_decode_y(slbnum);
        struct Thing *lairtng;
        lairtng = find_creature_lair_at_subtile(slab_subtile_center(slb_x), slab_subtile_center(slb_y), 0);
        if (thing_is_invalid(lairtng))
        {
            if (setup_person_move_to_position(creatng, slab_subtile_center(slb_x), slab_subtile_center(slb_y), NavRtF_Default)) {
                return true;
            }
            WARNLOG("Cannot get somewhere in room");
        }
        slbnum = get_next_slab_number_in_room(slbnum);
        if (slbnum == 0) {
            slbnum = room->slabs_list;
        }
        k++;
        if (k >= room->slabs_count) {
            break;
        }
    }
    return false;
}
예제 #4
0
long calculate_effeciency_score_for_room_slab(SlabCodedCoords slab_num, PlayerNumber plyr_idx)
{
    //return _DK_calculate_effeciency_score_for_room_slab(slab_num, plyr_idx);
    long eff_score;
    TbBool is_room_inside;
    is_room_inside = true;
    eff_score = 0;
    struct SlabMap *slb;
    slb = get_slabmap_direct(slab_num);
    long n;
    for (n=1; n < AROUND_SLAB_LENGTH; n+=2)
    {
        long round_slab_num;
        round_slab_num = slab_num + around_slab[n];
        struct SlabMap *round_slb;
        round_slb = get_slabmap_direct(round_slab_num);
        if (!slabmap_block_invalid(round_slb))
        {
            MapSlabCoord slb_x,slb_y;
            slb_x = slb_num_decode_x(round_slab_num);
            slb_y = slb_num_decode_y(round_slab_num);
            // Per slab code
            if ((slabmap_owner(round_slb) == slabmap_owner(slb)) && (round_slb->kind == slb->kind))
            {
                eff_score += 2;
            } else
            {
                is_room_inside = false;
                switch (find_core_slab_type(slb_x, slb_y))
                {
                  case SlbT_ROCK:
                  case SlbT_GOLD:
                  case SlbT_EARTH:
                  case SlbT_GEMS:
                    eff_score++;
                    break;
                  case SlbT_WALLDRAPE:
                    if (slabmap_owner(round_slb) == slabmap_owner(slb))
                        eff_score += 2;
                    break;
                  case SlbT_DOORWOOD1:
                    if (slabmap_owner(round_slb) == slabmap_owner(slb))
                        eff_score += 2;
                    break;
                  default:
                    break;
                }
            }
            // Per slab code ends
        }
    }
    // If we already know this is not an inside - finish
    if (!is_room_inside) {
        return eff_score;
    }
    // Make sure this is room inside by checking corners
    for (n=0; n < AROUND_SLAB_LENGTH; n+=2)
    {
        long round_slab_num;
        round_slab_num = slab_num + around_slab[n];
        struct SlabMap *round_slb;
        round_slb = get_slabmap_direct(round_slab_num);
        if (!slabmap_block_invalid(round_slb))
        {
            // Per slab code
            if ((slabmap_owner(round_slb) != slabmap_owner(slb)) || (round_slb->kind != slb->kind))
            {
                is_room_inside = 0;
                break;
            }
            // Per slab code ends
        }
    }
    if (is_room_inside) {
        eff_score += 2;
    }
    return eff_score;
}
예제 #5
0
/**
 *  Finds a random training post near to the current position of given creature.
 *  Used when finding a training post seems to be taking too long; in that case, creature should start training with a nearest post.
 *  Note that this routine does not always select the nearest post - it is enough if it's 3 subtiles away.
 *
 * @param creatng The creature who wish to train with training post.
 */
void setup_training_search_for_post(struct Thing *creatng)
{
    struct Room *room;
    struct Thing *traintng;
    struct Thing *thing;
    long start_slab;
    long min_distance,dist;
    long slb_x,slb_y;
    long i,k;
    room = get_room_thing_is_on(creatng);
    // Let's start from a random slab
    slb_x = -1;
    slb_y = -1;
    min_distance = LONG_MAX;
    traintng = INVALID_THING;
    start_slab = ACTION_RANDOM(room->slabs_count);
    k = start_slab;
    i = room->slabs_list;
    while (i != 0)
    {
        slb_x = slb_num_decode_x(i);
        slb_y = slb_num_decode_y(i);
        i = get_next_slab_number_in_room(i);
        if (k <= 0)
            break;
        k--;
    }
    // Got random starting slab, now sweep room slabs from it
    thing = INVALID_THING;
    k = room->slabs_count;
    i = get_slab_number(slb_x,slb_y);
    while (k > 0)
    {
        slb_x = slb_num_decode_x(i);
        slb_y = slb_num_decode_y(i);
        i = get_next_slab_number_in_room(i);
        if (i == 0)
          i = room->slabs_list;
        // Per room tile code - find a nearest training post
        thing = get_object_at_subtile_of_model_and_owned_by(slab_subtile_center(slb_x), slab_subtile_center(slb_y), 31, creatng->owner);
        if (!thing_is_invalid(thing))
        {
            dist = get_2d_distance(&creatng->mappos, &thing->mappos);
            if (dist < min_distance) {
                traintng = thing;
                min_distance = dist;
                if (min_distance < (3<<8))
                    break;
            }
        }
        // Per room tile code ends
        k--;
    }
    // Got trainer (or not...), now do the correct action
    if (thing_is_invalid(traintng))
    {
        SYNCDBG(6,"Room no longer have training post, moving somewhere else.");
        setup_move_to_new_training_position(creatng, room, true);
    } else
    {
        i = get_subtile_number(traintng->mappos.x.stl.num,traintng->mappos.y.stl.num);
        setup_training_move_near(creatng, i);
    }
}
예제 #6
0
void make_safe(struct PlayerInfo *player)
{
    //_DK_make_safe(player);
    unsigned char *areamap;
    areamap = (unsigned char *)scratch;
    MapSlabCoord slb_x, slb_y;
    // Prepare the array to remember which slabs were already taken care of
    for (slb_y=0; slb_y < map_tiles_y; slb_y++)
    {
        for (slb_x=0; slb_x < map_tiles_x; slb_x++)
        {
            SlabCodedCoords slb_num;
            struct SlabMap *slb;
            slb_num = get_slab_number(slb_x, slb_y);
            slb = get_slabmap_direct(slb_num);
            struct SlabAttr *slbattr;
            slbattr = get_slab_attrs(slb);
            if ((slbattr->block_flags & (SlbAtFlg_Filled|SlbAtFlg_Digable|SlbAtFlg_Valuable)) != 0)
                areamap[slb_num] = 0x01;
            else
                areamap[slb_num] = 0x00;
        }
    }
    {
        const struct Coord3d *center_pos;
        center_pos = dungeon_get_essential_pos(player->id_number);
        slb_x = subtile_slab_fast(center_pos->x.stl.num);
        slb_y = subtile_slab_fast(center_pos->y.stl.num);
        SlabCodedCoords slb_num;
        slb_num = get_slab_number(slb_x, slb_y);
        areamap[slb_num] |= 0x02;
    }

    unsigned int list_cur, list_len;
    PlayerNumber plyr_idx;
    plyr_idx = player->id_number;
    SlabCodedCoords *slblist;
    slblist = (SlabCodedCoords *)(scratch + map_tiles_x*map_tiles_y);
    list_len = 0;
    list_cur = 0;
    while (list_cur <= list_len)
    {
        SlabCodedCoords slb_num;

        if (slb_x > 0)
        {
            slb_num = get_slab_number(slb_x-1, slb_y);
            if ((areamap[slb_num] & 0x01) != 0)
            {
                areamap[slb_num] |= 0x02;
                struct SlabMap *slb;
                slb = get_slabmap_direct(slb_num);
                struct SlabAttr *slbattr;
                slbattr = get_slab_attrs(slb);
                if ((slbattr->category == SlbAtCtg_FriableDirt) && slab_by_players_land(plyr_idx, slb_x-1, slb_y))
                {
                    unsigned char pretty_type;
                    pretty_type = choose_pretty_type(plyr_idx, slb_x-1, slb_y);
                    place_slab_type_on_map(pretty_type, slab_subtile(slb_x-1,0), slab_subtile(slb_y,0), plyr_idx, 1);
                    do_slab_efficiency_alteration(slb_x-1, slb_y);
                    fill_in_reinforced_corners(plyr_idx, slb_x-1, slb_y);
                }
            } else
            if ((areamap[slb_num] & 0x02) == 0)
            {
                areamap[slb_num] |= 0x02;
                slblist[list_len] = slb_num;
                list_len++;
            }
        }
        if (slb_x < map_tiles_x-1)
        {
            slb_num = get_slab_number(slb_x+1, slb_y);
            if ((areamap[slb_num] & 0x01) != 0)
            {
                areamap[slb_num] |= 0x02;
                struct SlabMap *slb;
                slb = get_slabmap_direct(slb_num);
                struct SlabAttr *slbattr;
                slbattr = get_slab_attrs(slb);
                if ((slbattr->category == SlbAtCtg_FriableDirt) &&  slab_by_players_land(plyr_idx, slb_x+1, slb_y))
                {
                    unsigned char pretty_type;
                    pretty_type = choose_pretty_type(plyr_idx, slb_x+1, slb_y);
                    place_slab_type_on_map(pretty_type, slab_subtile(slb_x+1,0), slab_subtile(slb_y,0), plyr_idx, 1u);
                    do_slab_efficiency_alteration(slb_x+1, slb_y);
                    fill_in_reinforced_corners(plyr_idx, slb_x+1, slb_y);
                }
            } else
            if ((areamap[slb_num] & 0x02) == 0)
            {
                areamap[slb_num] |= 0x02;
                slblist[list_len] = slb_num;
                list_len++;
            }
        }
        if (slb_y > 0)
        {
            slb_num = get_slab_number(slb_x, slb_y-1);
            if ((areamap[slb_num] & 0x01) != 0)
            {
                areamap[slb_num] |= 0x02;
                struct SlabMap *slb;
                slb = get_slabmap_direct(slb_num);
                struct SlabAttr *slbattr;
                slbattr = get_slab_attrs(slb);
                if ((slbattr->category == SlbAtCtg_FriableDirt) && slab_by_players_land(plyr_idx, slb_x, slb_y-1))
                {
                    unsigned char pretty_type;
                    pretty_type = choose_pretty_type(plyr_idx, slb_x, slb_y-1);
                    place_slab_type_on_map(pretty_type, slab_subtile(slb_x,0), slab_subtile(slb_y-1,0), plyr_idx, 1u);
                    do_slab_efficiency_alteration(slb_x, slb_y-1);
                    fill_in_reinforced_corners(plyr_idx, slb_x, slb_y-1);
                }
            } else
            if ((areamap[slb_num] & 0x02) == 0)
            {
                areamap[slb_num] |= 0x02;
                slblist[list_len] = slb_num;
                list_len++;
            }
        }
        if (slb_y < map_tiles_y-1)
        {
            slb_num = get_slab_number(slb_x, slb_y+1);
            if ((areamap[slb_num] & 0x01) != 0)
            {
                areamap[slb_num] |= 0x02;
                struct SlabMap *slb;
                slb = get_slabmap_direct(slb_num);
                struct SlabAttr *slbattr;
                slbattr = get_slab_attrs(slb);
                if ((slbattr->category == SlbAtCtg_FriableDirt) && slab_by_players_land(plyr_idx, slb_x, slb_y+1))
                {
                    unsigned char pretty_type;
                    pretty_type = choose_pretty_type(plyr_idx, slb_x, slb_y+1);
                    place_slab_type_on_map(pretty_type, slab_subtile(slb_x,0), slab_subtile(slb_y+1,0), plyr_idx, 1u);
                    do_slab_efficiency_alteration(slb_x, slb_y+1);
                    fill_in_reinforced_corners(plyr_idx, slb_x, slb_y+1);
                }
            } else
            if ((areamap[slb_num] & 0x02) == 0)
            {
                areamap[slb_num] |= 0x02;
                slblist[list_len] = slb_num;
                list_len++;
            }
        }

        slb_x = slb_num_decode_x(slblist[list_cur]);
        slb_y = slb_num_decode_y(slblist[list_cur]);
        list_cur++;
    }
    pannel_map_update(0, 0, map_subtiles_x+1, map_subtiles_y+1);
}
예제 #7
0
void check_treasure_map(unsigned char *treasure_map, unsigned short *vein_list, long *gold_next_idx, MapSlabCoord veinslb_x, MapSlabCoord veinslb_y)
{
    struct GoldLookup *gldlook;
    struct SlabMap *slb;
    SlabCodedCoords slb_num,slb_around;
    MapSlabCoord slb_x,slb_y;
    long gold_slabs,gem_slabs;
    long vein_total,vein_idx;
    long gld_v1,gld_v2,gld_v3;
    long gold_idx;
    // First, find a vein
    vein_total = 0;
    slb_x = veinslb_x;
    slb_y = veinslb_y;
    gld_v1 = 0;
    gld_v2 = 0;
    gld_v3 = 0;
    gem_slabs = 0;
    gold_slabs = 0;
    slb_num = get_slab_number(slb_x, slb_y);
    treasure_map[slb_num] |= 0x02;
    for (vein_idx=0; vein_idx <= vein_total; vein_idx++)
    {
        gld_v1 += slb_x;
        gld_v2 += slb_y;
        gld_v3++;
        slb_around = get_slab_number(slb_x, slb_y);
        slb = get_slabmap_direct(slb_around);
        if (slb->kind == SlbT_GEMS)
        {
            gem_slabs++;
        } else
        {
            gold_slabs++;
            slb_around = get_slab_number(slb_x-1, slb_y);
            if ((treasure_map[slb_around] & 0x03) == 0)
            {
                treasure_map[slb_around] |= 0x02;
                vein_list[vein_total] = slb_around;
                vein_total++;
            }
            slb_around = get_slab_number(slb_x+1, slb_y);
            if ((treasure_map[slb_around] & 0x03) == 0)
            {
                treasure_map[slb_around] |= 0x02;
                vein_list[vein_total] = slb_around;
                vein_total++;
            }
            slb_around = get_slab_number(slb_x, slb_y-1);
            if ((treasure_map[slb_around] & 0x03) == 0)
            {
                treasure_map[slb_around] |= 0x02;
                vein_list[vein_total] = slb_around;
                vein_total++;
            }
            slb_around = get_slab_number(slb_x, slb_y+1);
            if ((treasure_map[slb_around] & 0x03) == 0)
            {
                treasure_map[slb_around] |= 0x02;
                vein_list[vein_total] = slb_around;
                vein_total++;
            }
        }
        // Move to next slab in list
        slb_x = slb_num_decode_x(vein_list[vein_idx]);
        slb_y = slb_num_decode_y(vein_list[vein_idx]);
    }
    // Now get a GoldLookup struct to put the vein into
    if (*gold_next_idx < GOLD_LOOKUP_COUNT)
    {
        gold_idx = *gold_next_idx;
        (*gold_next_idx)++;
    } else
    {
        gold_idx = smaller_gold_vein_lookup_idx(gold_slabs, gem_slabs);
    }
    // Write the vein to GoldLookup item
    if (gold_idx != -1)
    {
        gldlook = get_gold_lookup(gold_idx);
        LbMemorySet(gldlook, 0, sizeof(struct GoldLookup));
        gldlook->flags |= 0x01;
        gldlook->x_stl_num = slab_subtile_center(gld_v1 / gld_v3);
        gldlook->y_stl_num = slab_subtile_center(gld_v2 / gld_v3);
        gldlook->field_A = gold_slabs;
        gldlook->field_C = 0;
        gldlook->num_gold_slabs = gold_slabs;
        gldlook->num_gem_slabs = gem_slabs;
        SYNCDBG(8,"Added vein %d at (%d,%d)",(int)gold_idx,(int)gldlook->x_stl_num,(int)gldlook->y_stl_num);
    }
}
예제 #8
0
/**
 * This function generates "expand room" action on a tile which is claimed ground and could have a room placed on.
 * It is used to fix vandalized or not fully built rooms, so that they will cover the whole area digged for them.
 *
 * @param comp
 * @param check Computer check data.
 * @param room The room to be checked for expand.
 * @param max_radius The max distance of the slab being put to the center of the room, in subtiles.
 * @param around_start Random value used for setting starting point of the check process.
 * @return
 */
TbBool computer_check_for_expand_specific_room(struct Computer2 *comp, struct ComputerCheck * check, struct Room *room, MapSubtlCoord max_radius, long around_start)
{
    struct Dungeon *dungeon;
    dungeon = comp->dungeon;
    unsigned long i;
    unsigned long k;
    k = 0;
    i = room->slabs_list;
    while (i > 0)
    {
        MapSlabCoord slb_x,slb_y;
        struct SlabMap *slb;
        slb = get_slabmap_direct(i);
        slb_x = slb_num_decode_x(i);
        slb_y = slb_num_decode_y(i);
        i = get_next_slab_number_in_room(i);
        // Per-slab code
        int room_around, claimed_around;
        room_around = count_slabs_around_of_kind(slb_x, slb_y, slb->kind, dungeon->owner);
        claimed_around = 0;
        if (room_around < 8) {
            claimed_around = count_slabs_around_of_kind(slb_x, slb_y, SlbT_CLAIMED, dungeon->owner);
        }
        if (((room_around >= 3) && (claimed_around >= 2) && (room_around+claimed_around < 8)) // If there's something besides room and claimed, then grow more aggressively
         || ((room_around >= 4) && (claimed_around >= 2) && (room_around+claimed_around >= 8)) // If we're in open space, don't expand that much
         || ((room_around >= 6) && (claimed_around >= 1))) // Allow fixing one-slab holes inside rooms
        {
            unsigned long m,n;
            m = around_start % SMALL_AROUND_SLAB_LENGTH;
            for (n=0; n < SMALL_AROUND_SLAB_LENGTH; n++)
            {
                MapSlabCoord arslb_x, arslb_y;
                arslb_x = slb_x + small_around[m].delta_x;
                arslb_y = slb_y + small_around[m].delta_y;
                MapSubtlCoord arstl_x, arstl_y;
                arstl_x = slab_subtile_center(arslb_x);
                arstl_y = slab_subtile_center(arslb_y);
                long dist;
                dist = abs(room->central_stl_x - arstl_x) + abs(room->central_stl_y - arstl_y);
                if (dist <= max_radius)
                {
                    if (can_build_room_at_slab(dungeon->owner, room->kind, arslb_x, arslb_y))
                    {
                        if (try_game_action(comp, dungeon->owner, GA_PlaceRoom, 0, arstl_x, arstl_y, 1, room->kind) > Lb_OK) {
                            return true;
                        }
                    }
                }
                m = (m+1) % SMALL_AROUND_SLAB_LENGTH;
            }
        }
        // Per-slab code ends
        k++;
        if (k > room->slabs_count)
        {
            ERRORLOG("Infinite loop detected when sweeping room slabs");
            break;
        }
    }
    return false;
}