예제 #1
0
struct Room * find_nearest_navigable_room_for_thing_with_capacity_and_closer_than(struct Thing *thing, PlayerNumber owner, RoomKind rkind, unsigned char nav_flags, long used, long *neardistance)
{
    struct Dungeon *dungeon;
    struct Room *nearoom;
    long distance;
    int i;
    SYNCDBG(18,"Searching for %s navigable by %s index %d",room_code_name(rkind),thing_model_name(thing),(int)thing->index);
    dungeon = get_dungeon(owner);
    nearoom = INVALID_ROOM;
    distance = *neardistance;
    i = dungeon->room_kind[rkind];
    while (i != 0)
    {
        struct Room *room;
        room = find_next_navigable_room_for_thing_with_capacity_and_closer_than(thing, i, nav_flags, used, &distance);
        if (room_is_invalid(room)) {
            break;
        }
        // Found closer room
        i = room->next_of_owner;
        nearoom = room;
    }
    *neardistance = distance;
    return nearoom;
}
예제 #2
0
long instf_attack_room_slab(struct Thing *creatng, long *param)
{
    TRACE_THING(creatng);
    //return _DK_instf_attack_room_slab(creatng, param);
    struct Room *room;
    room = get_room_thing_is_on(creatng);
    if (room_is_invalid(room))
    {
        ERRORLOG("The %s is not on room",thing_model_name(creatng));
        return 0;
    }
    struct SlabMap *slb;
    slb = get_slabmap_thing_is_on(creatng);
    if (slb->health > 2)
    {
        //TODO CONFIG damage made to room slabs is constant - doesn't look good
        slb->health -= 2;
        thing_play_sample(creatng, 128 + UNSYNC_RANDOM(3), NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS);
        return 1;
    }
    if (room->owner != game.neutral_player_num)
    {
        struct Dungeon *dungeon;
        dungeon = get_dungeon(room->owner);
        dungeon->rooms_destroyed++;
    }
    if (!delete_room_slab(coord_slab(creatng->mappos.x.val), coord_slab(creatng->mappos.y.val), 1))
    {
        ERRORLOG("Cannot delete %s room tile destroyed by %s",room_code_name(room->kind),thing_model_name(creatng));
        return 0;
    }
    create_effect(&creatng->mappos, 3, creatng->owner);
    thing_play_sample(creatng, 47, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS);
    return 1;
}
예제 #3
0
struct Room *get_hated_room_for_quick_attack(struct Computer2 *comp, long min_hate)
{
    struct THate hates[PLAYERS_COUNT];
    long i;
    SYNCDBG(8,"Starting for player %d",(int)comp->dungeon->owner);
    get_opponent(comp, hates);
    // note that 'i' is not player index, player index is inside THate struct
    for (i=0; i < PLAYERS_COUNT; i++)
    {
        struct THate *hate;
        hate = &hates[i];
        if (players_are_enemies(comp->dungeon->owner, hate->plyr_idx))
        {
            if ((hate->pos_near != NULL) && (hate->amount > min_hate))
            {
                struct Room *room;
                room = get_opponent_room(comp, hate->plyr_idx);
                if (!room_is_invalid(room)) {
                    return room;
                }
            }
        }
    }
    return INVALID_ROOM;
}
예제 #4
0
long count_player_rooms_entrances(PlayerNumber plyr_idx)
{
    struct Room *room;
    long i;
    unsigned long k;
    long count;
    count = 0;
    i = game.entrance_room_id;
    k = 0;
    while (i != 0)
    {
        room = room_get(i);
        if (room_is_invalid(room))
        {
            ERRORLOG("Jump to invalid room detected");
            break;
        }
        i = room->next_of_kind;
        // Per-room code
        if ((plyr_idx < 0) || (room->owner == plyr_idx))
            count++;
        // Per-room code ends
        k++;
        if (k > ROOMS_COUNT)
        {
            ERRORLOG("Infinite loop detected when sweeping rooms list");
            break;
        }
    }
    return count;
}
예제 #5
0
long process_lair_enemy(struct Thing *thing, struct Room *room)
{
    struct CreatureControl *cctrl;
    struct CreatureStats *crstat;
    struct Thing *enemytng;
    long combat_factor;
    cctrl = creature_control_get_from_thing(thing);
    // Shouldn't be possible. But just for sure.
    if (room_is_invalid(room))
    {
        return 0;
    }
    // If the room changed during creature's journey, end
    if ((room->kind != RoK_LAIR) || (room->owner != thing->owner) || (room->index != cctrl->lair_room_id))
    {
        return 0;
    }
    crstat = creature_stats_get_from_thing(thing);
    // End if the creature has no lair enemy
    if (crstat->lair_enemy == 0)
    {
        return 0;
    }
    // Search for enemies no often than every 64 turns
    if (((game.play_gameturn + thing->index) & 0x3F) != 0)
    {
        return 0;
    }
    combat_factor = find_fellow_creature_to_fight_in_room(thing,room,crstat->lair_enemy,&enemytng);
    if (combat_factor < 1)
        return 0;
    if (!set_creature_in_combat_to_the_death(thing, enemytng, combat_factor))
        return 0;
    return 1;
}
예제 #6
0
TbBool good_setup_attack_rooms(struct Thing *creatng, long dngn_id)
{
    struct Room *room;
    struct CreatureControl *cctrl;
    struct Coord3d pos;
    room = find_nearest_room_for_thing_excluding_two_types(creatng, dngn_id, 7, 1, 1);
    if (room_is_invalid(room))
    {
        return false;
    }
    if (!find_random_valid_position_for_thing_in_room(creatng, room, &pos)
      || !creature_can_navigate_to_with_storage(creatng, &pos, NavRtF_NoOwner) )
    {
        ERRORLOG("The %s cannot destroy %s because it can't reach position within it",thing_model_name(creatng),room_code_name(room->kind));
        return false;
    }
    if (!setup_random_head_for_room(creatng, room, NavRtF_NoOwner))
    {
        ERRORLOG("The %s cannot destroy %s because it can't head for it",thing_model_name(creatng),room_code_name(room->kind));
        return false;
    }
    cctrl = creature_control_get_from_thing(creatng);
    creatng->continue_state = CrSt_GoodArrivedAtAttackRoom;
    cctrl->target_room_id = room->index;
    return true;
}
예제 #7
0
TbBool good_setup_loot_research_room(struct Thing *thing, long dngn_id)
{
    struct CreatureControl *cctrl;
    struct Room *room;
    room = find_random_room_creature_can_navigate_to(thing, dngn_id, RoK_LIBRARY, NavRtF_Default);
    if (room_is_invalid(room))
    {
        SYNCDBG(6,"No accessible player %d library found",(int)dngn_id);
        return false;
    }
    struct Coord3d pos;
    if (!find_random_valid_position_for_thing_in_room(thing, room, &pos))
    {
        SYNCDBG(6,"No position for %s index %d in %s owned by player %d",
            thing_model_name(thing),(int)thing->index,room_code_name(room->kind),(int)room->owner);
        return false;
    }
    if (!setup_person_move_to_coord(thing, &pos, NavRtF_Default))
    {
        SYNCDBG(6,"Cannot setup move %s index %d to %s owned by player %d",
            thing_model_name(thing),(int)thing->index,room_code_name(room->kind),(int)room->owner);
        return false;
    }
    cctrl = creature_control_get_from_thing(thing);
    thing->continue_state = CrSt_CreatureSearchForSpellToStealInRoom;
    cctrl->target_room_id = room->index;
    return true;
}
예제 #8
0
TbBool creature_can_freeze_prisoners_for_player(const struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job)
{
    // To freeze prisoners, our prison can't be empty
    struct Room *room;
    room = find_room_for_thing_with_used_capacity(creatng, creatng->owner, get_room_for_job(Job_FREEZE_PRISONERS), NavRtF_Default, 1);
    return creature_instance_is_available(creatng, CrInst_FREEZE) && !room_is_invalid(room);
}
예제 #9
0
TbBool attempt_job_work_in_room_for_player(struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job)
{
    struct Coord3d pos;
    struct Room *room;
    RoomKind rkind;
    rkind = get_room_for_job(new_job);
    SYNCDBG(6,"Starting for %s (owner %d) and job %s in %s room",thing_model_name(creatng),(int)creatng->owner,creature_job_code_name(new_job),room_code_name(rkind));
    if ((get_flags_for_job(new_job) & JoKF_NeedsCapacity) != 0) {
        room = find_nearest_room_for_thing_with_spare_capacity(creatng, creatng->owner, rkind, NavRtF_Default, 1);
    } else {
        room = find_nearest_room_for_thing(creatng, creatng->owner, rkind, NavRtF_Default);
    }
    if (room_is_invalid(room)) {
        return false;
    }
    if (!find_random_valid_position_for_thing_in_room(creatng, room, &pos)) {
        return false;
    }
    if (get_arrive_at_state_for_job(new_job) == CrSt_Unused) {
        ERRORLOG("No arrive at state for job %s in %s room",creature_job_code_name(new_job),room_code_name(room->kind));
        return false;
    }
    if (!setup_person_move_to_coord(creatng, &pos, NavRtF_Default)) {
        return false;
    }
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    creatng->continue_state = get_arrive_at_state_for_job(new_job);
    cctrl->target_room_id = room->index;
    return true;
}
예제 #10
0
TbBool attempt_anger_job_destroy_rooms(struct Thing *creatng)
{
    //return _DK_attempt_anger_job_destroy_rooms(creatng);
    if (!can_change_from_state_to(creatng, creatng->active_state, CrSt_CreatureVandaliseRooms)) {
        return false;
    }
    struct Room *room;
    struct Coord3d pos;
    room = find_nearest_room_for_thing_excluding_two_types(creatng, creatng->owner, 7, 1, 1);
    if (room_is_invalid(room)) {
        return false;
    }
    if (!find_random_valid_position_for_thing_in_room(creatng, room, &pos)) {
        return false;
    }
    if (!creature_can_navigate_to_with_storage(creatng, &pos, NavRtF_NoOwner)) {
        return false;
    }
    if (!external_set_thing_state(creatng, CrSt_CreatureVandaliseRooms)) {
        return false;
    }
    if (!setup_random_head_for_room(creatng, room, NavRtF_NoOwner)) {
        return false;
    }
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    creatng->continue_state = CrSt_CreatureVandaliseRooms;
    cctrl->target_room_id = room->index;
    return true;
}
예제 #11
0
long computer_check_for_place_door(struct Computer2 *comp, struct ComputerCheck * check)
{
	if (is_newdig_enabled(comp))
		return 4;

    SYNCDBG(8,"Starting");
    ThingModel doorkind;
    struct Dungeon *dungeon;
    dungeon = comp->dungeon;
    //TODO COMPUTER_PLAYER Computer prefers to put wooden doors, and uses other types only if wooden are depleted. That should be changed.
    for (doorkind = 1; doorkind < DOOR_TYPES_COUNT; doorkind++)
    {
        if (dungeon->door_amount_stored[doorkind] <= 0) {
            continue;
        }
        long rkind;
        rkind = check->param1;
        if (rkind == 0)
        {
            rkind = (check->param2 + 1) % ROOM_TYPES_COUNT;
            check->param2 = rkind;
        }
        unsigned long k;
        k = 0;
        long i;
        i = dungeon->room_kind[rkind];
        while (i != 0)
        {
            struct Room *room;
            room = room_get(i);
            if (room_is_invalid(room))
            {
                ERRORLOG("Jump to invalid room detected");
                break;
            }
            i = room->next_of_owner;
            // Per-room code
            struct Coord3d pos;
            pos.x.val = 0;
            pos.y.val = 0;
            pos.z.val = 0;
            if (find_place_to_put_door_around_room(room, &pos))
            {
                if (try_game_action(comp, dungeon->owner, GA_PlaceDoor, 0, pos.x.stl.num, pos.y.stl.num, doorkind, 0) > Lb_OK) {
                    return CTaskRet_Unk1;
                }
            }
            // Per-room code ends
            k++;
            if (k > ROOMS_COUNT)
            {
                ERRORLOG("Infinite loop detected when sweeping rooms list");
                break;
            }
        }
    }
    return CTaskRet_Unk4;
}
예제 #12
0
short creature_sleep(struct Thing *thing)
{
    //return _DK_creature_sleep(thing);
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(thing);
    if ((cctrl->slap_turns > 0) || !creature_will_sleep(thing)) {
        set_start_state(thing);
        return 0;
    }
    struct Room *room;
    room = get_room_thing_is_on(thing);
    if (room_is_invalid(room) || (room->kind != RoK_LAIR)
        || (cctrl->lair_room_id != room->index) || (room->owner != thing->owner)) {
        set_start_state(thing);
        return 0;
    }
    thing->movement_flags &= ~0x0020;
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(thing);
    if (((game.play_gameturn + thing->index) % game.recovery_frequency) == 0)
    {
        HitPoints recover;
        recover = compute_creature_max_health(crstat->sleep_recovery, cctrl->explevel);
        apply_health_to_thing_and_display_health(thing, recover);
    }
    anger_set_creature_anger(thing, 0, AngR_NoLair);
    anger_apply_anger_to_creature(thing, crstat->annoy_sleeping, AngR_Other, 1);
    if (cctrl->field_82 > 0) {
        cctrl->field_82--;
    }
    if (((game.play_gameturn + thing->index) & 0x3F) == 0)
    {
        if (ACTION_RANDOM(100) < 5) {
            struct Dungeon *dungeon;
            dungeon = get_dungeon(thing->owner);
            dungeon->lvstats.backs_stabbed++;
        }
    }
    if (crstat->sleep_exp_slab != SlbT_ROCK)
    {
        if (creature_can_gain_experience(thing) && room_has_slab_adjacent(room, crstat->sleep_exp_slab))
        {
            cctrl->exp_points += crstat->sleep_experience;
            check_experience_upgrade(thing);
        }
    }
    {
        HitPoints health_max;
        health_max = compute_creature_max_health(crstat->health, cctrl->explevel);
        if ((crstat->heal_threshold * health_max / 256 <= thing->health) && (!cctrl->field_82))
        {
            set_start_state(thing);
            return 1;
        }
    }
    process_lair_enemy(thing, room);
    return 0;
}
예제 #13
0
long instf_destroy(struct Thing *creatng, long *param)
{
    struct Dungeon *dungeon;
    struct Room *room;
    struct SlabMap *slb;
    MapSlabCoord slb_x,slb_y;
    long prev_owner;

    TRACE_THING(creatng);
    slb_x = subtile_slab_fast(creatng->mappos.x.stl.num);
    slb_y = subtile_slab_fast(creatng->mappos.y.stl.num);
    dungeon = get_dungeon(creatng->owner);
    slb = get_slabmap_block(slb_x, slb_y);
    room = room_get(slb->room_index);
    prev_owner = slabmap_owner(slb);

    if ( !room_is_invalid(room) && (prev_owner != creatng->owner) )
    {
        if (room->health > 1)
        {
            room->health--;
            return 0;
        }
        clear_dig_on_room_slabs(room, creatng->owner);
        if (room->owner == game.neutral_player_num)
        {
            claim_room(room, creatng);
        } else
        {
            MapCoord ccor_x,ccor_y;
            ccor_x = subtile_coord_center(room->central_stl_x);
            ccor_y = subtile_coord_center(room->central_stl_y);
            event_create_event_or_update_nearby_existing_event(ccor_x, ccor_y, EvKind_RoomLost, room->owner, 0);
            claim_enemy_room(room, creatng);
        }
        thing_play_sample(creatng, 76, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS);
        create_effects_on_room_slabs(room, imp_spangle_effects[creatng->owner], 0, creatng->owner);
        return 0;
    }
    if (slb->health > 1)
    {
        slb->health--;
        return 0;
    }
    if (prev_owner != game.neutral_player_num) {
        struct Dungeon *prev_dungeon;
        prev_dungeon = get_dungeon(prev_owner);
        prev_dungeon->lvstats.territory_lost++;
    }
    decrease_dungeon_area(prev_owner, 1);
    neutralise_enemy_block(creatng->mappos.x.stl.num, creatng->mappos.y.stl.num, creatng->owner);
    remove_traps_around_subtile(slab_subtile_center(slb_x), slab_subtile_center(slb_y), NULL);
    switch_owned_objects_on_destoyed_slab_to_neutral(slb_x, slb_y, prev_owner);
    dungeon->lvstats.territory_destroyed++;
    return 1;
}
예제 #14
0
struct Room * find_next_navigable_room_for_thing_with_capacity_and_closer_than(struct Thing *thing, int prev_room_idx, unsigned char nav_flags, long used, long *neardistance)
{
    long distance;
    struct Coord3d pos;

    struct Room *room;
    unsigned long k;
    int i;
    k = 0;
    i = prev_room_idx;
    while (i != 0)
    {
        room = room_get(i);
        if (room_is_invalid(room))
        {
            ERRORLOG("Jump to invalid room detected");
            break;
        }
        i = room->next_of_owner;
        // Per-room code
        // Compute simplified distance - without use of mul or div
        distance = abs(thing->mappos.x.stl.num - (int)room->central_stl_x)
                 + abs(thing->mappos.y.stl.num - (int)room->central_stl_y);
        if ((*neardistance > distance) && (room->used_capacity >= used))
        {
            if (find_first_valid_position_for_thing_anywhere_in_room(thing, room, &pos))
            {
                TbBool is_connected;
                switch (thing->class_id)
                {
                case TCls_Creature:
                    is_connected = creature_can_navigate_to(thing, &pos, nav_flags);
                    break;
                default:
                    is_connected = navigation_points_connected(&thing->mappos, &pos);
                    break;
                }
                if (is_connected)
                {
                    *neardistance = distance;
                    return room;
                }
            }
        }
        // Per-room code ends
        k++;
        if (k > ROOMS_COUNT)
        {
          ERRORLOG("Infinite loop detected when sweeping rooms list");
          break;
        }
    }
    return INVALID_ROOM;
}
예제 #15
0
long computer_check_neutral_places(struct Computer2 *comp, struct ComputerCheck * check)
{
    SYNCDBG(8,"Starting");
    //return _DK_computer_check_neutral_places(comp, check);
    struct Comp2_UnkStr1 *rel;
    rel = &comp->unkarr_A10[game.neutral_player_num];
    struct Room *near_room;
    struct Coord3d *near_pos;
    int near_dist;
    near_room = INVALID_ROOM;
    near_dist = 2147483647;
    near_pos = &rel->pos_A[0];
    int i;
    for (i=0; i < 64; i++)
    {
        struct Coord3d *place;
        place = &rel->pos_A[i];
        if ((place->x.val == 0) || (place->y.val == 0)) {
            continue;
        }
        struct Room *room;
        room = INVALID_ROOM;
        if (computer_finds_nearest_room_to_pos(comp, &room, place))
        {
            MapSubtlDelta dx,dy;
            dx = abs((int)room->central_stl_x - (MapSubtlDelta)place->x.stl.num);
            dy = abs((int)room->central_stl_y - (MapSubtlDelta)place->y.stl.num);
            if (near_dist > dx+dy)
            {
                near_room = room;
                near_pos = place;
                near_dist = dx+dy;
            }
        }
    }
    if (room_is_invalid(near_room)) {
        return 4;
    }
    struct Coord3d endpos;
    struct Coord3d startpos;
    endpos.x.val = near_pos->x.val;
    endpos.y.val = near_pos->y.val;
    endpos.z.val = near_pos->z.val;
    startpos.x.val = subtile_coord_center(stl_slab_center_subtile(near_room->central_stl_x));
    startpos.y.val = subtile_coord_center(stl_slab_center_subtile(near_room->central_stl_y));
    startpos.z.val = subtile_coord(1,0);
    if (!create_task_dig_to_neutral(comp, startpos, endpos)) {
        return 4;
    }
    near_pos->x.val = 0;
    near_pos->y.val = 0;
    near_pos->z.val = 0;
    return 1;
}
예제 #16
0
TbBool attempt_job_in_state_on_room_content_for_player(struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job)
{
    struct Room *room;
    RoomKind rkind;
    rkind = get_room_for_job(new_job);
    room = find_room_for_thing_with_used_capacity(creatng, creatng->owner, rkind, NavRtF_Default, 1);
    if (room_is_invalid(room)) {
        return false;
    }
    internal_set_thing_state(creatng, get_initial_state_for_job(new_job));
    return true;
}
예제 #17
0
long computer_check_move_creatures_to_room(struct Computer2 *comp, struct ComputerCheck * check)
{
    struct Dungeon *dungeon;
    struct Room *room;
    dungeon = comp->dungeon;
    SYNCDBG(8,"Checking player %d for move to %s", (int)dungeon->owner, room_code_name(check->param2));
    int num_to_move;
    num_to_move = check->param1 * dungeon->num_active_creatrs / 100;
    if (num_to_move <= 0) {
        SYNCDBG(8,"No creatures to move, active %d percentage %d", (int)dungeon->num_active_creatrs, (int)check->param1);
        return CTaskRet_Unk4;
    }
    if (computer_able_to_use_magic(comp, PwrK_HAND, 1, num_to_move) != 1) {
        return CTaskRet_Unk4;
    }
    // If there's already task in progress which uses hand, then don't add more
    // content of the hand could be used by wrong task by mistake
    if (is_task_in_progress_using_hand(comp)) {
        return CTaskRet_Unk4;
    }
    unsigned long k;
    long i;
    k = 0;
    i = dungeon->room_kind[check->param2];
    while (i != 0)
    {
        room = room_get(i);
        if (room_is_invalid(room))
        {
            ERRORLOG("Jump to invalid room detected");
            break;
        }
        i = room->next_of_owner;
        // Per-room code
        if (room->total_capacity > room->used_capacity)
        {
            int num_to_move_fit;
            num_to_move_fit = min(num_to_move, room->total_capacity - room->used_capacity);
            if (create_task_move_creatures_to_room(comp, room->index, num_to_move_fit)) {
                SYNCDBG(8,"Added task to move %d creatures to %s index %d", (int)num_to_move_fit,room_code_name(room->kind),(int)room->index);
                return CTaskRet_Unk1;
            }
        }
        // Per-room code ends
        k++;
        if (k > ROOMS_COUNT)
        {
            ERRORLOG("Infinite loop detected when sweeping rooms list");
            break;
        }
    }
    return CTaskRet_Unk4;
}
예제 #18
0
void init_dungeon_essential_position(struct Dungeon *dungeon)
{
    struct Room *room;
    room = room_get(dungeon->room_kind[RoK_DUNGHEART]);
    RoomKind rkind;
    for (rkind = 1; rkind < ROOM_TYPES_COUNT; rkind++)
    {
        if (!room_is_invalid(room))
            break;
        room = room_get(dungeon->room_kind[rkind]);
    }
    if (room_is_invalid(room)) {
        dungeon->essential_pos.x.val = subtile_coord_center(map_subtiles_x/2);
        dungeon->essential_pos.y.val = subtile_coord_center(map_subtiles_y/2);
        dungeon->essential_pos.z.val = subtile_coord(0,1);
        return;
    }
    dungeon->essential_pos.x.val = subtile_coord_center(room->central_stl_x);
    dungeon->essential_pos.y.val = subtile_coord_center(room->central_stl_y);
    dungeon->essential_pos.z.val = subtile_coord(0,1);
}
예제 #19
0
long computer_check_move_creatures_to_room(struct Computer2 *comp, struct ComputerCheck * check)
{
    struct Dungeon *dungeon;
    struct Room *room;
    dungeon = comp->dungeon;
    SYNCDBG(8,"Checking player %d for move to %s", (int)dungeon->owner, room_code_name(check->param2));
    //return _DK_computer_check_move_creatures_to_room(comp, check);
    //TODO check if should be changed to computer_able_to_use_magic()
    if (!is_power_available(dungeon->owner, PwrK_HAND)) {
        return 4;
    }
    int num_to_move;
    num_to_move = check->param1 * dungeon->num_active_creatrs / 100;
    if (num_to_move <= 0) {
        SYNCDBG(8,"No creatures to move, active %d percentage %d", (int)dungeon->num_active_creatrs, (int)check->param1);
        return 4;
    }
    if (is_task_in_progress(comp, CTT_MoveCreatureToRoom)) {
        return 4;
    }
    unsigned long k;
    long i;
    k = 0;
    i = dungeon->room_kind[check->param2];
    while (i != 0)
    {
        room = room_get(i);
        if (room_is_invalid(room))
        {
            ERRORLOG("Jump to invalid room detected");
            break;
        }
        i = room->next_of_owner;
        // Per-room code
        if (room->total_capacity > room->used_capacity)
        {
            if (create_task_move_creatures_to_room(comp, room->index, num_to_move)) {
                SYNCDBG(8,"Added task to move %d creatures to %s index %d", (int)num_to_move,room_code_name(room->kind),(int)room->index);
                return 1;
            }
        }
        // Per-room code ends
        k++;
        if (k > ROOMS_COUNT)
        {
            ERRORLOG("Infinite loop detected when sweeping rooms list");
            break;
        }
    }
    return 4;
}
예제 #20
0
struct Room * find_nearest_navigable_room_for_thing_with_capacity_and_closer_than(struct Thing *thing, PlayerNumber owner, RoomKind rkind, unsigned char nav_flags, long used, long *neardistance)
{
    struct Dungeon *dungeon;
    struct Room *nearoom;
    long distance;
    struct Coord3d pos;

    struct Room *room;
    unsigned long k;
    int i;
    SYNCDBG(18,"Searching for %s navigable by %s index %d",room_code_name(rkind),thing_model_name(thing),(int)thing->index);
    dungeon = get_dungeon(owner);
    nearoom = INVALID_ROOM;
    k = 0;
    i = dungeon->room_kind[rkind];
    while (i != 0)
    {
        room = room_get(i);
        if (room_is_invalid(room))
        {
            ERRORLOG("Jump to invalid room detected");
            break;
        }
        i = room->next_of_owner;
        // Per-room code
        // Compute simplified distance - without use of mul or div
        distance = abs(thing->mappos.x.stl.num - (int)room->central_stl_x)
                 + abs(thing->mappos.y.stl.num - (int)room->central_stl_y);
        if ((*neardistance > distance) && (room->used_capacity >= used))
        {
            if (find_first_valid_position_for_thing_anywhere_in_room(thing, room, &pos))
            {
                if ((thing->class_id != TCls_Creature)
                  || creature_can_navigate_to(thing, &pos, nav_flags))
                {
                    *neardistance = distance;
                    nearoom = room;
                }
            }
        }
        // Per-room code ends
        k++;
        if (k > ROOMS_COUNT)
        {
          ERRORLOG("Infinite loop detected when sweeping rooms list");
          break;
        }
    }
    return nearoom;
}
예제 #21
0
short creature_scavenged_disappear(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct Dungeon *dungeon;
    struct Room *room;
    struct Coord3d pos;
    long stl_x, stl_y;
    long i;
    //return _DK_creature_scavenged_disappear(thing);
    cctrl = creature_control_get_from_thing(thing);
    cctrl->byte_9A--;
    if (cctrl->byte_9A > 0)
    {
      if ((cctrl->byte_9A == 7) && (cctrl->byte_9B < PLAYERS_COUNT))
      {
        create_effect(&thing->mappos, get_scavenge_effect_element(cctrl->byte_9B), thing->owner);
      }
      return 0;
    }
    // We don't really have to convert coordinates into numbers and back to XY.
    i = get_subtile_number(cctrl->scavenge.stl_9D_x, cctrl->scavenge.stl_9D_y);
    stl_x = stl_num_decode_x(i);
    stl_y = stl_num_decode_y(i);
    room = subtile_room_get(stl_x, stl_y);
    if (room_is_invalid(room) || (room->kind != RoK_SCAVENGER))
    {
        ERRORLOG("Room %s at (%d,%d) disappeared.",room_code_name(RoK_SCAVENGER),(int)stl_x,(int)stl_y);
        kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects);
        return -1;
    }
    if (find_random_valid_position_for_thing_in_room(thing, room, &pos))
    {
        move_thing_in_map(thing, &pos);
        anger_set_creature_anger_all_types(thing, 0);
        dungeon = get_dungeon(cctrl->byte_9B);
        dungeon->creatures_scavenge_gain++;
        if (is_my_player_number(thing->owner))
          output_message(SMsg_MinionScanvenged, 0, true);
        cctrl->byte_9C = thing->owner;
        change_creature_owner(thing, cctrl->byte_9B);
        internal_set_thing_state(thing, CrSt_CreatureScavengedReappear);
        return 0;
    } else
    {
        ERRORLOG("No valid position inside %s room for %s.",room_code_name(room->kind),thing_model_name(thing));
        kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects);
        return -1;
    }
}
예제 #22
0
void find_nearest_rooms_for_ambient_sound(void)
{
    struct PlayerInfo *player;
    struct Room *room;
    struct MapOffset *sstep;
    struct Coord3d pos;
    long slb_x,slb_y;
    MapSubtlCoord stl_x,stl_y;
    long i,k;
    SYNCDBG(8,"Starting");
    if ((SoundDisabled) || (GetCurrentSoundMasterVolume() <= 0))
        return;
    player = get_my_player();
    struct Camera *cam;
    cam = player->acamera;
    if (cam == NULL)
    {
        ERRORLOG("No active camera");
        set_room_playing_ambient_sound(NULL, 0);
        return;
    }
    slb_x = subtile_slab(cam->mappos.x.stl.num);
    slb_y = subtile_slab(cam->mappos.y.stl.num);
    for (i = 0; i < 11*11; i++)
    {
        sstep = &spiral_step[i];
        stl_x = slab_subtile_center(slb_x + sstep->h);
        stl_y = slab_subtile_center(slb_y + sstep->v);
        if (subtile_is_player_room(player->id_number,stl_x,stl_y))
        {
            room = subtile_room_get(stl_x, stl_y);
            if (room_is_invalid(room))
                continue;
            struct RoomConfigStats *roomst;
            roomst = &slab_conf.room_cfgstats[room->kind];
            k = roomst->ambient_snd_smp_id;
            if (k > 0)
            {
                SYNCDBG(8,"Playing ambient for %s at (%d,%d)",room_code_name(room->kind),(int)stl_x,(int)stl_y);
                pos.x.val = subtile_coord_center(stl_x);
                pos.y.val = subtile_coord_center(stl_y);
                pos.z.val = subtile_coord(1,0);
                set_room_playing_ambient_sound(&pos, k);
                return;
            }
        }
    }
    set_room_playing_ambient_sound(NULL, 0);
}
예제 #23
0
long computer_check_for_expand_room_kind(struct Computer2 *comp, struct ComputerCheck * check, RoomKind rkind, long max_slabs, long around_start)
{
    struct Dungeon *dungeon;
    dungeon = comp->dungeon;
    {
        struct RoomStats *rstat;
        rstat = room_stats_get_for_kind(rkind);
        // If we don't have money for the room - don't even try
        // Check price for two slabs - after all, we don't want to end up having nothing
        if (2*rstat->cost >= dungeon->total_money_owned) {
            return 0;
        }
    }
    MapSubtlCoord max_radius;
    // Don't allow the room to be made into long, narrow shape
    max_radius = 3 * slab_subtile(LbSqrL(max_slabs),2) / 4;
    struct Room *room;
    long i;
    unsigned long k;
    i = dungeon->room_kind[rkind];
    k = 0;
    while (i != 0)
    {
        room = room_get(i);
        if (room_is_invalid(room))
        {
          ERRORLOG("Jump to invalid room detected");
          break;
        }
        i = room->next_of_owner;
        // Per-room code
        if ((room->slabs_count > 0) && (room->slabs_count < max_slabs)) {
            if (computer_check_for_expand_specific_room(comp, check, room, max_radius, around_start)) {
                SYNCDBG(6,"The %s index %d will be expanded",room_code_name(room->kind),(int)room->index);
                return 1;
            }
        }
        // Per-room code ends
        k++;
        if (k > ROOMS_COUNT)
        {
          ERRORLOG("Infinite loop detected when sweeping rooms list");
          break;
        }
    }
    return 0;
}
예제 #24
0
void find_nearest_rooms_for_ambient_sound(void)
{
    struct PlayerInfo *player;
    struct Room *room;
    struct MapOffset *sstep;
    struct Coord3d pos;
    long slb_x,slb_y;
    long stl_x,stl_y;
    long i,k;
    SYNCDBG(8,"Starting");
    //_DK_find_nearest_rooms_for_ambient_sound();
    if ((SoundDisabled) || (GetCurrentSoundMasterVolume() <= 0))
        return;
    player = get_my_player();
    if (player->acamera == NULL)
    {
        ERRORLOG("No active camera");
        set_room_playing_ambient_sound(NULL, 0);
        return;
    }
    slb_x = subtile_slab(player->acamera->mappos.x.stl.num);
    slb_y = subtile_slab(player->acamera->mappos.y.stl.num);
    for (i = 0; i < 120; i++)
    {
        sstep = &spiral_step[i];
        stl_x = 3 * (slb_x + sstep->h);
        stl_y = 3 * (slb_y + sstep->v);
        if (subtile_is_player_room(player->id_number,stl_x,stl_y))
        {
            room = subtile_room_get(stl_x, stl_y);
            if (room_is_invalid(room))
                continue;
            k = room_info[room->kind].field_4;
            if (k > 0)
            {
                pos.x.val = (stl_x << 8);
                pos.y.val = (stl_y << 8);
                pos.z.val = (1 << 8);
                set_room_playing_ambient_sound(&pos, k);
                return;
            }
        }
    }
    set_room_playing_ambient_sound(NULL, 0);
}
예제 #25
0
struct Room *get_player_room_of_kind_nearest_to(PlayerNumber plyr_idx, RoomKind rkind,
    MapSubtlCoord stl_x, MapSubtlCoord stl_y, long *retdist)
{
    struct Dungeon *dungeon;
    struct Room *room;
    long i;
    unsigned long k;
    dungeon = get_dungeon(plyr_idx);
    struct Room *nearest_room;
    long nearest_dist;
    nearest_dist = LONG_MAX;
    nearest_room = INVALID_ROOM;
    i = dungeon->room_kind[rkind];
    k = 0;
    while (i != 0)
    {
      room = room_get(i);
      if (room_is_invalid(room))
      {
          ERRORLOG("Jump to invalid room detected");
          break;
      }
      i = room->next_of_owner;
      // Per-room code
      long dist;
      dist = abs(room->central_stl_y - stl_y) + abs(room->central_stl_x - stl_x);
      if (dist < nearest_dist)
      {
          nearest_dist = dist;
          nearest_room = room;
      }
      // Per-room code ends
      k++;
      if (k > ROOMS_COUNT)
      {
          ERRORLOG("Infinite loop detected when sweeping rooms list");
          break;
      }
    }
    if (retdist != NULL)
        *retdist = nearest_dist;
    return nearest_room;
}
예제 #26
0
struct Thing *computer_check_creatures_in_dungeon_rooms_of_kind_for_accelerate(struct Computer2 *comp, RoomKind rkind)
{
    struct Dungeon *dungeon;
    struct Room *room;
    struct Thing *thing;
    long i;
    unsigned long k;
    if ((rkind < 1) || (rkind > ROOM_TYPES_COUNT))
    {
        ERRORLOG("Invalid room kind %d",(int)rkind);
        return INVALID_THING;
    }
    dungeon = comp->dungeon;
    if (dungeon_invalid(dungeon))
    {
        ERRORLOG("Invalid computer players dungeon");
        return INVALID_THING;
    }
    i = dungeon->room_kind[rkind];
    k = 0;
    while (i != 0)
    {
        room = room_get(i);
        if (room_is_invalid(room))
        {
          ERRORLOG("Jump to invalid room detected");
          break;
        }
        i = room->next_of_owner;
        // Per-room code
        thing = computer_check_creatures_in_room_for_accelerate(comp, room);
        if (!thing_is_invalid(thing))
            return thing;
        // Per-room code ends
        k++;
        if (k > ROOMS_COUNT)
        {
          ERRORLOG("Infinite loop detected when sweeping rooms list");
          break;
        }
    }
    return INVALID_THING;
}
예제 #27
0
TbBool attempt_anger_job_leave_dungeon(struct Thing *creatng)
{
    if (!can_change_from_state_to(creatng, creatng->active_state, CrSt_CreatureLeaves)) {
        return false;
    }
    struct Room *room;
    room = find_nearest_room_for_thing(creatng, creatng->owner, RoK_ENTRANCE, NavRtF_Default);
    if (room_is_invalid(room)) {
        return false;
    }
    if (!external_set_thing_state(creatng, CrSt_CreatureLeaves)) {
        return false;
    }
    if (!setup_random_head_for_room(creatng, room, NavRtF_Default)) {
        return false;
    }
    creatng->continue_state = CrSt_CreatureLeaves;
    return true;
}
예제 #28
0
short creature_choose_room_for_lair_site(struct Thing *thing)
{
    TRACE_THING(thing);
    //return _DK_creature_choose_room_for_lair_site(thing);
    struct Room *room;
    room = get_best_new_lair_for_creature(thing);
    if (room_is_invalid(room))
    {
        update_cannot_find_room_wth_spare_capacity_event(thing->owner, thing, RoK_LAIR);
        set_start_state(thing);
        return 0;
    }
    if (!setup_head_for_random_unused_lair_slab(thing, room))
    {
        ERRORLOG("Chosen lair is not valid, internal inconsistency.");
        set_start_state(thing);
        return 0;
    }
    thing->continue_state = CrSt_CreatureAtNewLair;
    return 1;
}
예제 #29
0
TbBool is_correct_position_to_perform_job(const struct Thing *creatng, MapSubtlCoord stl_x, MapSubtlCoord stl_y, CreatureJob new_job)
{
    const struct SlabMap *slb;
    slb = get_slabmap_for_subtile(stl_x, stl_y);
    const struct Room *room;
    room = subtile_room_get(stl_x, stl_y);
    RoomKind job_rkind;
    job_rkind = get_room_for_job(new_job);
    if (job_rkind != RoK_NONE)
    {
        if (room_is_invalid(room)) {
            return false;
        }
        if (room->kind != job_rkind) {
            return false;
        }
    }
    if (!is_correct_owner_to_perform_job(creatng, slabmap_owner(slb), new_job)) {
        return false;
    }
    return true;
}
예제 #30
0
struct Room *get_player_room_any_kind_nearest_to(PlayerNumber plyr_idx,
    MapSubtlCoord stl_x, MapSubtlCoord stl_y, long *retdist)
{
    struct Room *nearest_room;
    long nearest_dist;
    nearest_dist = LONG_MAX;
    nearest_room = INVALID_ROOM;
    RoomKind rkind;
    for (rkind = 1; rkind < ROOM_TYPES_COUNT; rkind++)
    {
        struct Room *room;
        long dist;
        room = get_player_room_of_kind_nearest_to(plyr_idx, rkind, stl_x, stl_y, &dist);
        if (!room_is_invalid(room) && (dist < nearest_dist)) {
            nearest_dist = dist;
            nearest_room = room;
        }
    }
    if (retdist != NULL)
        *retdist = nearest_dist;
    return nearest_room;
}