Example #1
0
void unfill_reinforced_corners(PlayerNumber keep_plyr_idx, MapSlabCoord base_slb_x, MapSlabCoord base_slb_y)
{
    //_DK_unfill_reinforced_corners(plyr_idx, base_slb_x, base_slb_y); return;
    int i;
    for (i = 0; i < SMALL_AROUND_SLAB_LENGTH; i++)
    {
        MapSlabCoord slb_x, slb_y;
        slb_x = base_slb_x + small_around[i].delta_x;
        slb_y = base_slb_y + small_around[i].delta_y;
        struct SlabMap *slb;
        slb = get_slabmap_block(slb_x, slb_y);
        struct SlabAttr *slbattr;
        slbattr = get_slab_attrs(slb);
        if ((slbattr->category == SlbAtCtg_FortifiedWall) && (slabmap_owner(slb) != keep_plyr_idx))
        {
            int num_owned_around;
            num_owned_around = count_owned_ground_around(slabmap_owner(slb), slb_x, slb_y);
            if (num_owned_around < 2)
            {
                SlabKind slbkind;
                slbkind = alter_rock_style(SlbT_EARTH, slb_x, slb_y, game.neutral_player_num);
                place_slab_type_on_map(slbkind, slab_subtile_center(slb_x), slab_subtile_center(slb_y), game.neutral_player_num, 0);
                do_slab_efficiency_alteration(slb_x, slb_y);
            }
        }
    }
}
Example #2
0
struct Thing *get_trap_for_slab_position(MapSlabCoord slb_x, MapSlabCoord slb_y)
{
    MapCoord pos_x,pos_y;
    pos_x = subtile_coord_center(slab_subtile_center(slb_x));
    pos_y = subtile_coord_center(slab_subtile_center(slb_y));
    return get_trap_around_of_model_and_owned_by(pos_x, pos_y, -1, -1);
}
Example #3
0
TbBool can_build_room_at_slab(PlayerNumber plyr_idx, RoomKind rkind,
    MapSlabCoord slb_x, MapSlabCoord slb_y)
{
    if (!subtile_revealed(slab_subtile_center(slb_x), slab_subtile_center(slb_y), plyr_idx)) {
        SYNCDBG(7,"Cannot place %s owner %d as slab (%d,%d) is not revealed",room_code_name(rkind),(int)plyr_idx,(int)slb_x,(int)slb_y);
        return false;
    }
    struct SlabMap *slb;
    slb = get_slabmap_block(slb_x, slb_y);
    if (slb->room_index > 0) {
        SYNCDBG(7,"Cannot place %s owner %d as slab (%d,%d) has room index %d",room_code_name(rkind),(int)plyr_idx,(int)slb_x,(int)slb_y,(int)slb->room_index);
        return false;
    }
    if (slab_has_trap_on(slb_x, slb_y) || slab_has_door_thing_on(slb_x, slb_y)) {
        SYNCDBG(7,"Cannot place %s owner %d as slab (%d,%d) has blocking thing on it",room_code_name(rkind),(int)plyr_idx,(int)slb_x,(int)slb_y);
        return false;
    }
    if (rkind == RoK_BRIDGE) {
        return slab_kind_is_liquid(slb->kind) && slab_by_players_land(plyr_idx, slb_x, slb_y);
    }
    if (slabmap_owner(slb) != plyr_idx) {
        return false;
    }
    return (slb->kind == SlbT_CLAIMED);
}
Example #4
0
/**
 * Removes reinforces walls from tiles around given slab, except given owner.
 * @param keep_plyr_idx The owning player whose walls are not to be affected.
 * @param slb_x Central slab for the unprettying effect, X coord.
 * @param slb_y Central slab for the unprettying effect, Y coord.
 */
void do_unprettying(PlayerNumber keep_plyr_idx, MapSlabCoord slb_x, MapSlabCoord slb_y)
{
    long n;
    for (n=0; n < SMALL_AROUND_SLAB_LENGTH; n++)
    {
        long sslb_x,sslb_y;
        struct SlabMap *slb;
        sslb_x = slb_x + (long)small_around[n].delta_x;
        sslb_y = slb_y + (long)small_around[n].delta_y;
        slb = get_slabmap_block(sslb_x, sslb_y);
        struct SlabAttr *slbattr;
        slbattr = get_slab_attrs(slb);
        if ((slbattr->category == SlbAtCtg_FortifiedWall) && (slabmap_owner(slb) != keep_plyr_idx))
        {
            if (!slab_by_players_land(slabmap_owner(slb), sslb_x, sslb_y))
            {
                SlabKind newslab;
                newslab = choose_rock_type(keep_plyr_idx, sslb_x, sslb_y);
                place_slab_type_on_map(newslab, slab_subtile_center(sslb_x), slab_subtile_center(sslb_y), game.neutral_player_num, 0);
                unfill_reinforced_corners(keep_plyr_idx, sslb_x, sslb_y);
                do_slab_efficiency_alteration(sslb_x, sslb_y);
            }
        }
    }
}
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;
}
Example #6
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);
}
Example #7
0
/**
 * Finds a safe and unused, adjacent position in room for a creature.
 *
 * @param pos Position of the creature to be moved.
 * @param owner Room owner to keep.
 * @return Coded subtiles of the new position, or 0 on failure.
 * @see person_get_somewhere_adjacent_in_room()
 */
SubtlCodedCoords find_unused_adjacent_position_in_workshop(const struct Coord3d *pos, long owner)
{
    static const struct Around corners[] = { {1,2}, {0,1}, {1,0}, {2,1} };
    long i;
    for (i=0; i < SMALL_AROUND_LENGTH; i++)
    {
        MapSlabCoord slb_x, slb_y;
        slb_x = subtile_slab_fast(pos->x.stl.num) + (long)small_around[i].delta_x;
        slb_y = subtile_slab_fast(pos->y.stl.num) + (long)small_around[i].delta_y;
        struct SlabMap *slb;
        slb = get_slabmap_block(slb_x, slb_y);
        if ((slb->kind == SlbT_WORKSHOP) && (slabmap_owner(slb) == owner))
        {
            struct Thing *mnfc_creatng;
            MapSubtlCoord stl_x, stl_y;
            stl_x = slab_subtile(slb_x, corners[i].delta_x);
            stl_y = slab_subtile(slb_y, corners[i].delta_y);
            mnfc_creatng = get_other_creature_manufacturing_on_subtile(owner, stl_x, stl_y, INVALID_THING);
            if (!thing_is_invalid(mnfc_creatng)) {
                // Position used by another manufacturer
                continue;
            }
            struct Thing *objtng;
            objtng = get_workshop_equipment_to_work_with_on_subtile(owner, slab_subtile_center(slb_x), slab_subtile_center(slb_y));
            if (thing_is_invalid(objtng)) {
                // Position has no work equipment nearby
                continue;
            }
            // Found an acceptable position
            return get_subtile_number(stl_x, stl_y);
        }
    }
    return 0;
}
Example #8
0
int floor_height_for_volume_box(PlayerNumber plyr_idx, MapSlabCoord slb_x, MapSlabCoord slb_y)
{
    struct SlabMap *slb;
    slb = get_slabmap_block(slb_x, slb_y);
    struct SlabAttr *slbattr;
    slbattr = get_slab_attrs(slb);
    if (!subtile_revealed(slab_subtile_center(slb_x), slab_subtile_center(slb_y), plyr_idx) || ((slbattr->block_flags & (SlbAtFlg_Filled|SlbAtFlg_Digable|SlbAtFlg_Valuable)) != 0))
    {
        return temp_cluedo_mode < 1u ? 5 : 2;
    }
    if (slab_kind_is_liquid(slb->kind))
    {
        return 0;
    }
    return 1;
}
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;
}
Example #10
0
long instf_pretty_path(struct Thing *creatng, long *param)
{
    struct Dungeon *dungeon;
    TRACE_THING(creatng);
    SYNCDBG(16,"Starting");
    dungeon = get_dungeon(creatng->owner);
    MapSlabCoord slb_x,slb_y;
    slb_x = subtile_slab_fast(creatng->mappos.x.stl.num);
    slb_y = subtile_slab_fast(creatng->mappos.y.stl.num);
    create_effect(&creatng->mappos, imp_spangle_effects[creatng->owner], creatng->owner);
    thing_play_sample(creatng, 76, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS);
    place_slab_type_on_map(SlbT_CLAIMED, slab_subtile_center(slb_x), slab_subtile_center(slb_y), creatng->owner, 1);
    do_unprettying(creatng->owner, slb_x, slb_y);
    do_slab_efficiency_alteration(slb_x, slb_y);
    increase_dungeon_area(creatng->owner, 1);
    dungeon->lvstats.area_claimed++;
    remove_traps_around_subtile(slab_subtile_center(slb_x), slab_subtile_center(slb_y), NULL);
    return 1;
}
Example #11
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));
    }
}
Example #12
0
TbBool find_place_to_put_door_around_room(const struct Room *room, struct Coord3d *pos)
{
    long m,n;
    m = ACTION_RANDOM(SMALL_AROUND_SLAB_LENGTH);
    for (n = 0; n < SMALL_AROUND_SLAB_LENGTH; n++)
    {
        // Get position containing room center
        MapSlabCoord slb_x,slb_y;
        slb_x = subtile_slab_fast(room->central_stl_x);
        slb_y = subtile_slab_fast(room->central_stl_y);
        // Move the position to edge of the room
        struct Room *sibroom;
        sibroom = slab_room_get(slb_x, slb_y);
        while (!room_is_invalid(sibroom) && (sibroom->index == room->index))
        {
            slb_x += small_around[m].delta_x;
            slb_y += small_around[m].delta_y;
            sibroom = slab_room_get(slb_x, slb_y);
        }
        // Move the position a few tiles further in that direction searching for a place to put door
        //TODO COMPUTER_PLAYER Why we can only have doors if corridor is at center of the room? This should be fixed to allow doors everywhere around room.
        int i;
        for (i = 4; i > 0; i--)
        {
            struct SlabMap *slb;
            slb = get_slabmap_block(slb_x, slb_y);
            if ((slabmap_owner(slb) != room->owner) || (slb->kind != SlbT_CLAIMED)) {
                i = 0;
                break;
            }
            if (tag_cursor_blocks_place_door(room->owner, slab_subtile_center(slb_x), slab_subtile_center(slb_y))) {
                break;
            }
            if (!subtile_has_door_thing_on(slab_subtile_center(slb_x), slab_subtile_center(slb_y))) {
                // No door - the position looks ok
                break;
            }
            slb_x += small_around[m].delta_x;
            slb_y += small_around[m].delta_y;
        }
        // Now if we were able to move, then the position seem ok. One last check - make sure the corridor is not dead end and doesn't already have a door
        if (i > 0)
        {
            MapSlabCoord nxslb_x,nxslb_y;
            nxslb_x = slb_x + small_around[m].delta_x;
            nxslb_y = slb_y + small_around[m].delta_y;
            struct SlabMap *nxslb;
            nxslb = get_slabmap_block(nxslb_x, nxslb_y);
            if ((slabmap_owner(nxslb) == room->owner) && (nxslb->kind == SlbT_CLAIMED))
            {
                if (!subtile_has_door_thing_on(slab_subtile_center(nxslb_x), slab_subtile_center(nxslb_y))) {
                    pos->x.val = subtile_coord_center(slab_subtile_center(slb_x));
                    pos->y.val = subtile_coord_center(slab_subtile_center(slb_y));
                    pos->z.val = subtile_coord(1,0);
                    return true;
                }
            }
        }
        m = (m + 1) % SMALL_AROUND_SLAB_LENGTH;
    }
    return false;
}
Example #13
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);
    }
}
Example #14
0
void process_creature_in_training_room(struct Thing *thing, struct Room *room)
{
    static const struct Around corners[] = {
        {1, 2},
        {0, 1},
        {1, 0},
        {2, 1},
    };
    struct CreatureControl *cctrl;
    struct CreatureStats *crstat;
    struct Thing *traintng;
    struct Thing *crtng;
    struct CreatureControl *cctrl2;
    struct Coord3d pos;
    long speed,dist;
    long i;
    cctrl = creature_control_get_from_thing(thing);
    SYNCDBG(8,"Starting %s mode %d",thing_model_name(thing),(int)cctrl->training.mode);
    //_DK_process_creature_in_training_room(thing, room); return;
    cctrl->field_4A = 0;
    switch (cctrl->training.mode)
    {
    case CrTrMd_SearchForTrainPost:
        // While we're in an instance, just wait
        if (cctrl->instance_id != CrInst_NULL)
            break;
        // On timeout, search for nearby training posts to start training ASAP
        if (cctrl->training.search_timeout < 1)
        {
            SYNCDBG(6,"Search timeout - selecting post nearest to (%d,%d)",(int)thing->mappos.x.stl.num, (int)thing->mappos.y.stl.num);
            setup_training_search_for_post(thing);
            cctrl->training.search_timeout = 100;
            break;
        }
        // Do a moving step
        cctrl->training.search_timeout--;
        speed = get_creature_speed(thing);
        i = creature_move_to(thing, &cctrl->moveto_pos, speed, 0, 0);
        if (i == 1)
        {
            // Move target is reached - find a training post which is supposed to be around here
            traintng = find_training_post_just_next_to_creature(thing);
            if (thing_is_invalid(traintng))
            {
                SYNCDBG(6,"Reached (%d,%d) but there's no training post there",(int)thing->mappos.x.stl.num, (int)thing->mappos.y.stl.num);
                setup_move_to_new_training_position(thing, room, false);
                break;
            }
            // Found - go to next mode
            cctrl->training.mode = CrTrMd_SelectPositionNearTrainPost;
            cctrl->training.search_timeout = 50;
        } else
        if (i == -1)
        {
            ERRORLOG("Cannot get to (%d,%d) in the training room",(int)cctrl->moveto_pos.x.stl.num,(int)cctrl->moveto_pos.y.stl.num);
            set_start_state(thing);
        }
        break;
    case CrTrMd_SelectPositionNearTrainPost:
        for (i=0; i < 4; i++)
        {
            long slb_x,slb_y;
            long stl_x,stl_y;
            struct SlabMap *slb;
            slb_x = subtile_slab_fast(thing->mappos.x.stl.num) + (long)small_around[i].delta_x;
            slb_y = subtile_slab_fast(thing->mappos.y.stl.num) + (long)small_around[i].delta_y;
            slb = get_slabmap_block(slb_x,slb_y);
            if ((slb->kind != SlbT_TRAINING) || (slabmap_owner(slb) != thing->owner))
                continue;
            stl_x = slab_subtile(slb_x,corners[i].delta_x);
            stl_y = slab_subtile(slb_y,corners[i].delta_y);
            traintng = INVALID_THING;
            // Check if any other creature is using that post; allow only unused posts
            crtng = get_creature_of_model_training_at_subtile_and_owned_by(stl_x, stl_y, -1, thing->owner, thing->index);
            if (thing_is_invalid(crtng))
            {
                traintng = get_object_at_subtile_of_model_and_owned_by(slab_subtile_center(slb_x), slab_subtile_center(slb_y), 31, thing->owner);
            }
            if (!thing_is_invalid(traintng))
            {
                cctrl->training.pole_stl_x = slab_subtile_center(subtile_slab_fast(thing->mappos.x.stl.num));
                cctrl->training.pole_stl_y = slab_subtile_center(subtile_slab_fast(thing->mappos.y.stl.num));
                cctrl->moveto_pos.x.stl.num = stl_x;
                cctrl->moveto_pos.y.stl.num = stl_y;
                cctrl->moveto_pos.x.stl.pos = 128;
                cctrl->moveto_pos.y.stl.pos = 128;
                cctrl->moveto_pos.z.val = get_thing_height_at(thing, &cctrl->moveto_pos);
                if (thing_in_wall_at(thing, &cctrl->moveto_pos))
                {
                    ERRORLOG("Illegal setup to (%d,%d)", (int)cctrl->moveto_pos.x.stl.num, (int)cctrl->moveto_pos.y.stl.num);
                    break;
                }
                cctrl->training.mode = CrTrMd_MoveToTrainPost;
                break;
            }
        }
        if (cctrl->training.mode == CrTrMd_SelectPositionNearTrainPost)
          setup_move_to_new_training_position(thing, room, 1);
        break;
    case CrTrMd_MoveToTrainPost:
        speed = get_creature_speed(thing);
        i = creature_move_to(thing, &cctrl->moveto_pos, speed, 0, 0);
        if (i == 1)
        {
            // If there's already someone training at that position, go somewhere else
            crtng = get_creature_of_model_training_at_subtile_and_owned_by(thing->mappos.x.stl.num, thing->mappos.y.stl.num, -1, thing->owner, thing->index);
            if (!thing_is_invalid(crtng))
            {
                setup_move_to_new_training_position(thing, room, 1);
                break;
            }
            // Otherwise, train at this position
            cctrl->training.mode = CrTrMd_TurnToTrainPost;
        } else
        if (i == -1)
        {
            ERRORLOG("Cannot get where we're going in the training room.");
            set_start_state(thing);
        }
        break;
    case CrTrMd_TurnToTrainPost:
        pos.x.val = subtile_coord_center(cctrl->training.pole_stl_x);
        pos.y.val = subtile_coord_center(cctrl->training.pole_stl_y);
        if (creature_turn_to_face(thing, &pos) < 56)
        {
          cctrl->training.mode = CrTrMd_DoTrainWithTrainPost;
          cctrl->training.train_timeout = 75;
        }
        break;
    case CrTrMd_PartnerTraining:
        if (cctrl->training.partner_idx == 0)
        {
            setup_move_to_new_training_position(thing, room, false);
            return;
        }
        crtng = thing_get(cctrl->training.partner_idx);
        TRACE_THING(crtng);
        if (!thing_exists(crtng) || (get_creature_state_besides_move(crtng) != CrSt_Training) || (crtng->creation_turn != cctrl->training.partner_creation))
        {
            SYNCDBG(8,"The %s cannot start partner training - creature to train with is gone.",thing_model_name(thing));
            setup_move_to_new_training_position(thing, room, false);
            return;
        }
        cctrl2 = creature_control_get_from_thing(crtng);
        if (cctrl2->training.partner_idx != thing->index)
        {
            SYNCDBG(6,"The %s cannot start partner training - %s changed the partner.",thing_model_name(thing),thing_model_name(crtng));
            cctrl->training.partner_idx = 0;
            setup_move_to_new_training_position(thing, room, false);
            break;
        }
        if (get_room_thing_is_on(crtng) != room)
        {
            SYNCDBG(8,"The %s cannot start partner training - partner has left the room.",thing_model_name(thing));
            cctrl->training.partner_idx = 0;
            cctrl2->training.partner_idx = 0;
            setup_move_to_new_training_position(thing, room, false);
            break;
        }
        crstat = creature_stats_get_from_thing(thing);
        dist = get_combat_distance(thing, crtng);
        if (dist > 284)
        {
            if (creature_move_to(thing, &crtng->mappos, get_creature_speed(thing), 0, 0) == -1)
            {
              WARNLOG("The %s cannot navigate to training partner",thing_model_name(thing));
              setup_move_to_new_training_position(thing, room, false);
              cctrl->training.partner_idx = 0;
            }
        } else
        if (dist >= 156)
        {
            if (creature_turn_to_face(thing, &crtng->mappos) < 56)
            {
              cctrl->training.train_timeout--;
              if (cctrl->training.train_timeout > 0)
              {
                if ((cctrl->instance_id == CrInst_NULL) && ((cctrl->training.train_timeout % 8) == 0))
                {
                    set_creature_instance(thing, CrInst_SWING_WEAPON_SWORD, 1, 0, 0);
                }
              } else
              {
                if (cctrl->instance_id == CrInst_NULL)
                {
                    setup_move_to_new_training_position(thing, room, false);
                    cctrl->training.partner_idx = 0;
                } else
                {
                    cctrl->training.train_timeout = 1;
                }
                cctrl->exp_points += (room->efficiency * crstat->training_value);
              }
            }
        } else
        {
            creature_retreat_from_combat(thing, crtng, 33, 0);
        }
        break;
    case CrTrMd_DoTrainWithTrainPost:
        if (cctrl->training.train_timeout > 0)
        {
            // While training timeout is positive, continue initiating the train instances
            cctrl->training.train_timeout--;
            if ((cctrl->instance_id == CrInst_NULL) && ((cctrl->training.train_timeout % 8) == 0))
            {
                set_creature_instance(thing, CrInst_SWING_WEAPON_SWORD, 1, 0, 0);
            }
        } else
        {
            // Wait for the instance to end, then select new move position
            if (cctrl->instance_id != CrInst_NULL)
            {
                cctrl->training.train_timeout = 0;
            } else
            {
                cctrl->training.train_timeout = 0;
                setup_move_to_new_training_position(thing, room, true);
            }
        }
        break;
    default:
        WARNLOG("Invalid %s training mode %d; reset",thing_model_name(thing),(int)cctrl->training.mode);
        cctrl->training.mode = CrTrMd_SearchForTrainPost;
        cctrl->training.search_timeout = 0;
        break;
    }
    SYNCDBG(18,"End");
}
Example #15
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);
    }
}
Example #16
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;
}
Example #17
0
long process_creature_in_workshop(struct Thing *creatng, struct Room *room)
{
    //return _DK_process_creature_in_workshop(creatng, room);
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    struct Dungeon *dungeon;
    dungeon = get_dungeon(creatng->owner);
    if ((game.play_gameturn - dungeon->field_118B < 50) && ((game.play_gameturn + creatng->index) & 3) == 0)
    {
        if (cctrl->instance_id == CrInst_NULL) {
            set_creature_instance(creatng, CrInst_CELEBRATE_SHORT, 1, 0, 0);
        }
        return 1;
    }
    if (cctrl->instance_id != CrInst_NULL) {
        return 1;
    }
    long mvret;
    MapSlabCoord slb_x, slb_y;
    SYNCDBG(19,"Work in %s, the %s in state %d",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A);
    switch (cctrl->byte_9A)
    {
    case 1:
        cctrl->byte_9E--;
        if (cctrl->byte_9E <= 0)
        {
            setup_workshop_search_for_post(creatng);
            cctrl->byte_9E = 100;
            break;
        }
        mvret = creature_move_to(creatng, &cctrl->moveto_pos, get_creature_speed(creatng), 0, 0);
        if (mvret != 1)
        {
            if (mvret == -1) {
                SYNCDBG(9,"Room %s move problem, the %s goes from %d to start state",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A);
                set_start_state(creatng);
            }
            break;
        }
        slb_x = subtile_slab_fast(creatng->mappos.x.stl.num);
        slb_y = subtile_slab_fast(creatng->mappos.y.stl.num);
        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))
        {
            SYNCDBG(19,"Got %s post, the %s goes from %d to 2",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A);
            cctrl->byte_9A = 2;
            cctrl->byte_9E = 100;
            break;
        }
        SYNCDBG(19,"No %s post at current pos, the %s goes from %d to search position",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A);
        setup_move_to_new_workshop_position(creatng, room, 0);
        break;
    case 2:
    {
        SubtlCodedCoords stl_num;
        stl_num = find_unused_adjacent_position_in_workshop(&creatng->mappos, creatng->owner);
        if (stl_num != 0) {
            slb_x = subtile_slab_fast(stl_num_decode_x(stl_num));
            slb_y = subtile_slab_fast(stl_num_decode_y(stl_num));
            cctrl->byte_9C = slab_subtile_center(slb_x);
            cctrl->byte_9D = slab_subtile_center(slb_y);
            setup_workshop_move(creatng, stl_num);
            cctrl->byte_9A = 3;
            break;
        }
        SYNCDBG(9,"No free adjacent %s post, the %s goes from %d to search position",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A);
        setup_move_to_new_workshop_position(creatng, room, 1);
        break;
    }
    case 3:
    {
        mvret = creature_move_to(creatng, &cctrl->moveto_pos, get_creature_speed(creatng), 0, 0);
        if (mvret != 1)
        {
            if (mvret == -1) {
                SYNCDBG(9,"Room %s move problem, the %s goes from %d to start state",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A);
                set_start_state(creatng);
            }
            break;
        }
        struct Thing *mnfc_creatng;
        mnfc_creatng = get_other_creature_manufacturing_on_subtile(creatng->owner, creatng->mappos.x.stl.num, creatng->mappos.y.stl.num, creatng);
        if (thing_is_invalid(mnfc_creatng)) {
            cctrl->byte_9A = 4;
            break;
        }
        // Position used by another manufacturer
        SYNCDBG(9,"The %s post already in use, the %s goes from %d to search position",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A);
        setup_move_to_new_workshop_position(creatng, room, 1);
        break;
    }
    case 4:
    {
        struct Coord3d pos;
        pos.x.val = subtile_coord_center(cctrl->byte_9C);
        pos.y.val = subtile_coord_center(cctrl->byte_9D);
        if (creature_turn_to_face(creatng, &pos) < 56)
        {
            cctrl->byte_9A = 5;
            cctrl->byte_9B = 75;
        }
        break;
    }
    case 5:
    default:
        cctrl->byte_9B--;
        if (cctrl->byte_9B <= 0)
        {
            SYNCDBG(9,"Room %s move counter %d, the %s keeps moving in state %d",room_code_name(room->kind),(int)cctrl->byte_9B,thing_model_name(creatng),(int)cctrl->byte_9A);
            setup_move_to_new_workshop_position(creatng, room, 1);
        } else
        if ((cctrl->byte_9B % 8) == 0) {
            set_creature_instance(creatng, CrInst_SWING_WEAPON_SWORD, 1, 0, 0);
        }
        break;
    }
    return 1;
}