long room_has_slab_adjacent(const struct Room *room, long slbkind)
{
    long i;
    unsigned long k;
    k = 0;
    i = room->slabs_list;
    while (i > 0)
    {
        // Per room tile code
        long n;
        for (n=0; n < AROUND_SLAB_LENGTH; n++)
        {
            long slab_num;
            slab_num = i + around_slab[n];
            struct SlabMap *slb;
            slb = get_slabmap_direct(slab_num);
            if (!slabmap_block_invalid(slb))
            {
                if (slb->kind == slbkind) {
                    return true;
                }
            }
        }
        // Per room tile code ends
        i = get_next_slab_number_in_room(i);
        k++;
        if (k > room->slabs_count)
        {
            ERRORLOG("Room slabs list length exceeded when sweeping");
            break;
        }
    }
    return 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;
}
/**
 * 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;
}
Beispiel #4
0
void setup_workshop_search_for_post(struct Thing *creatng)
{
    struct Room *room;
    struct Thing *postng;
    postng = INVALID_THING;
    room = get_room_thing_is_on(creatng);
    // Find a random slab in the room to be used as our starting point
    long i;
    unsigned long n;
    i = ACTION_RANDOM(room->slabs_count);
    n = room->slabs_list;
    while (i > 0)
    {
        n = get_next_slab_number_in_room(n);
        i--;
    }
    i = room->slabs_count;
    while (i > 0)
    {
        // Loop the slabs list
        if (n <= 0) {
            n = room->slabs_list;
        }
        MapSlabCoord slb_x, slb_y;
        slb_x = subtile_slab_fast(stl_num_decode_x(n));
        slb_y = subtile_slab_fast(stl_num_decode_y(n));
        struct Thing *objtng;
        objtng = get_workshop_equipment_to_work_with_on_subtile(creatng->owner, slab_subtile_center(slb_x), slab_subtile_center(slb_y));
        if (!thing_is_invalid(objtng)) {
            postng = objtng;
        }
        n = get_next_slab_number_in_room(n);
        i--;
    }
    if (thing_is_invalid(postng))
    {
        SYNCDBG(9,"Work in %s, the %s moves to new pos",room_code_name(room->kind),thing_model_name(creatng));
        setup_move_to_new_workshop_position(creatng, room, 1);
    } else
    {
        SYNCDBG(9,"Work in %s, the %s found a post",room_code_name(room->kind),thing_model_name(creatng));
        setup_workshop_move(creatng, get_subtile_number(postng->mappos.x.stl.num, postng->mappos.y.stl.num));
    }
}
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;
}
Beispiel #6
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);
    }
}
Beispiel #7
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;
}