예제 #1
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;
}
예제 #2
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);
}
예제 #3
0
TbBool tag_cursor_blocks_place_trap(PlayerNumber plyr_idx, MapSubtlCoord stl_x, MapSubtlCoord stl_y)
{
    SYNCDBG(7,"Starting");
    int floor_height;
    TbBool can_place;
    MapSlabCoord slb_x, slb_y;
    slb_x = subtile_slab_fast(stl_x);
    slb_y = subtile_slab_fast(stl_y);
    can_place = can_place_trap_on(plyr_idx, stl_x, stl_y);
    floor_height = floor_height_for_volume_box(plyr_idx, slb_x, slb_y);
    if (is_my_player_number(plyr_idx))
    {
        if (!game_is_busy_doing_gui() && (game.small_map_state != 2)) {
            // Move to first subtile on a slab
            stl_x = slab_subtile(slb_x,0);
            stl_y = slab_subtile(slb_y,0);
            draw_map_volume_box(subtile_coord(stl_x,0), subtile_coord(stl_y,0),
                subtile_coord(stl_x+STL_PER_SLB,0), subtile_coord(stl_y+STL_PER_SLB,0), floor_height, can_place);
        }
    }
    return can_place;
}
예제 #4
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);
}
예제 #5
0
void draw_god_lightning(struct Thing *shotng)
{
    //_DK_draw_god_lightning(shotng); return;
    struct PlayerInfo *player;
    player = get_player(shotng->owner);
    const struct Camera *cam;
    cam = player->acamera;
    if (cam == NULL) {
        return;
    }
    int i;
    for (i = LbFPMath_PI/4; i < 2*LbFPMath_PI; i += LbFPMath_PI/2)
    {
        struct Coord3d locpos;
        locpos.x.val = shotng->mappos.x.val;
        locpos.y.val = shotng->mappos.y.val;
        locpos.z.val = shotng->mappos.z.val;
        locpos.x.val +=  (LbSinL(i + cam->orient_a) >> (LbFPMath_TrigmBits - 10));
        locpos.y.val += -(LbCosL(i + cam->orient_a) >> (LbFPMath_TrigmBits - 10));
        locpos.z.val = subtile_coord(12,0);
        draw_lightning(&locpos, &shotng->mappos, 256, 60);
    }
}
예제 #6
0
/**
 * Quick attack is just putting CTA spell on enemy room.

 * @param comp
 * @param check
 */
long computer_check_for_quick_attack(struct Computer2 *comp, struct ComputerCheck * check)
{
    struct Dungeon *dungeon;
    SYNCDBG(8,"Starting");
    //return _DK_computer_check_for_quick_attack(comp, check);
    dungeon = comp->dungeon;
    int creatrs_num;
    creatrs_num = check->param1 * dungeon->num_active_creatrs / 100;
    if (check->param3 >= creatrs_num) {
        return 4;
    }
    if (computer_able_to_use_magic(comp, PwrK_CALL2ARMS, 1, 3) != 1) {
        return 4;
    }
    if ((check_call_to_arms(comp) != 1) || is_there_an_attack_task(comp)) {
        return 4;
    }
    struct Room *room;
    room = get_hated_room_for_quick_attack(comp, check->param3);
    if (room_is_invalid(room)) {
        return 4;
    }
    struct Coord3d pos;
    // TODO COMPUTER_PLAYER We should make sure the place of cast is accessible for creatures
    pos.x.val = subtile_coord_center(room->central_stl_x);
    pos.y.val = subtile_coord_center(room->central_stl_y);
    pos.z.val = subtile_coord(1,0);
    if (check->param3 >= count_creatures_availiable_for_fight(comp, &pos)) {
        return 4;
    }
    if (!create_task_magic_support_call_to_arms(comp, &pos, check->param2, 0, creatrs_num)) {
        return 4;
    }
    output_message(SMsg_EnemyHarassments+ACTION_RANDOM(8), 500, 1);
    return 1;
}
예제 #7
0
TbBool sibling_line_of_sight_3d_including_lava_check_ignoring_own_door(const struct Coord3d *prevpos,
    const struct Coord3d *nextpos, PlayerNumber plyr_idx)
{
    // Check for door at central subtile
    if (subtile_is_door(stl_slab_center_subtile(nextpos->x.stl.num), stl_slab_center_subtile(nextpos->y.stl.num))) {
        return false;
    }
    // If only one dimensions changed, allow the pass
    // (in that case the outcome has been decided before this call)
    if ((nextpos->x.stl.num == prevpos->x.stl.num)
     || (nextpos->y.stl.num == prevpos->y.stl.num)) {
        // change is (x,0) or (0,x)
        return true;
    }
    struct Coord3d posmvy;
    struct Coord3d posmvx;
    int subdelta_x, subdelta_y;
    subdelta_x = (nextpos->x.stl.num - (MapSubtlDelta)prevpos->x.stl.num);
    subdelta_y = (nextpos->y.stl.num - (MapSubtlDelta)prevpos->y.stl.num);
    switch (subdelta_x + 2 * subdelta_y)
    {
    case -3: // change is (-1,-1)
        posmvx.x.val = prevpos->x.val - subtile_coord(1,0);
        posmvx.y.val = prevpos->y.val;
        posmvx.z.val = prevpos->z.val;
        posmvy.x.val = prevpos->x.val;
        posmvy.y.val = prevpos->y.val - subtile_coord(1,0);
        posmvy.z.val = prevpos->z.val;
        if (get_point_in_map_solid_flags_ignoring_own_door(&posmvy, plyr_idx) & 0x01) {
            return false;
        }
        if (get_point_in_map_solid_flags_ignoring_own_door(&posmvx, plyr_idx) & 0x01) {
            return false;
        }
        break;

    case -1: // change is (1,-1) as (-1,0) was eliminated earlier
        posmvx.x.val = prevpos->x.val + subtile_coord(1,0);
        posmvx.y.val = prevpos->y.val;
        posmvx.z.val = prevpos->z.val;
        posmvy.x.val = prevpos->x.val;
        posmvy.y.val = prevpos->y.val - subtile_coord(1,0);
        posmvy.z.val = prevpos->z.val;
        if (get_point_in_map_solid_flags_ignoring_own_door(&posmvy, plyr_idx) & 0x01) {
            return false;
        }
        if (get_point_in_map_solid_flags_ignoring_own_door(&posmvx, plyr_idx) & 0x01) {
            return false;
        }
        break;

    case 1: // change is (-1,1) as (1,0) was eliminated earlier
        posmvx.x.val = prevpos->x.val - subtile_coord(1,0);
        posmvx.y.val = prevpos->y.val;
        posmvx.z.val = prevpos->z.val;
        posmvy.x.val = prevpos->x.val;
        posmvy.y.val = prevpos->y.val + subtile_coord(1,0);
        posmvy.z.val = prevpos->z.val;
        if (get_point_in_map_solid_flags_ignoring_own_door(&posmvy, plyr_idx) & 0x01) {
            return false;
        }
        if (get_point_in_map_solid_flags_ignoring_own_door(&posmvx, plyr_idx) & 0x01) {
            return false;
        }
        break;

    case 3: // change is (1,1)
        posmvx.x.val = prevpos->x.val + subtile_coord(1,0);
        posmvx.y.val = prevpos->y.val;
        posmvx.z.val = prevpos->z.val;
        posmvy.x.val = prevpos->x.val;
        posmvy.y.val = prevpos->y.val + subtile_coord(1,0);
        posmvy.z.val = prevpos->z.val;
        if (get_point_in_map_solid_flags_ignoring_own_door(&posmvy, plyr_idx) & 0x01) {
            return false;
        }
        if (get_point_in_map_solid_flags_ignoring_own_door(&posmvx, plyr_idx) & 0x01) {
            return false;
        }
        break;

    default:
        ERRORDBG(8,"Invalid use of sibling function, delta (%d,%d)",(int)subdelta_x,(int)subdelta_y);
        break;
    }
    return true;
}
예제 #8
0
void god_lightning_choose_next_creature(struct Thing *shotng)
{
    SYNCDBG(16,"Starting for %s index %d owner %d",thing_model_name(shotng),(int)shotng->index,(int)shotng->owner);
    //_DK_god_lightning_choose_next_creature(shotng); return;
    long best_dist;
    struct Thing *best_thing;
    best_dist = LONG_MAX;
    best_thing = INVALID_THING;

    unsigned long k;
    int i;
    const struct StructureList *slist;
    slist = get_list_for_thing_class(TCls_Creature);
    k = 0;
    i = slist->index;
    while (i != 0)
    {
        struct Thing *thing;
        thing = thing_get(i);
        if (thing_is_invalid(thing))
        {
            ERRORLOG("Jump to invalid thing detected");
            break;
        }
        i = thing->next_of_class;
        // Per-thing code
        //TODO use hit_type instead of hard coded conditions
        if ((shotng->owner != thing->owner) && !thing_is_picked_up(thing)
            && !creature_is_being_unconscious(thing) && !creature_is_dying(thing))
        {
            long dist;
            dist = get_2d_distance(&shotng->mappos, &thing->mappos);
            if (dist < best_dist)
            {
                const struct MagicStats *pwrdynst;
                pwrdynst = get_power_dynamic_stats(PwrK_LIGHTNING);
                int spell_lev;
                spell_lev = shotng->shot.byte_19;
                if (spell_lev > SPELL_MAX_LEVEL)
                    spell_lev = SPELL_MAX_LEVEL;
                if (subtile_coord(pwrdynst->strength[spell_lev],0) > dist)
                {
                    if (line_of_sight_2d(&shotng->mappos, &thing->mappos)) {
                        best_dist = dist;
                        best_thing = thing;
                    }
                }
            }
        }
        // Per-thing code ends
        k++;
        if (k > slist->count)
        {
            ERRORLOG("Infinite loop detected when sweeping things list");
            erstat_inc(ESE_InfChainTngPerClass);
            break;
        }
    }
    SYNCDBG(8,"The best target for %s index %d owner %d is %s index %d owner %d",
        thing_model_name(shotng),(int)shotng->index,(int)shotng->owner,
        thing_model_name(best_thing),(int)best_thing->index,(int)best_thing->owner);
    if (!thing_is_invalid(best_thing)) {
        shotng->shot.target_idx = best_thing->index;
    } else {
        shotng->shot.target_idx = 0;
    }
}
예제 #9
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;
}
예제 #10
0
long computer_check_enemy_entrances(struct Computer2 *comp, struct ComputerCheck * check)
{
    SYNCDBG(8,"Starting");
    //return _DK_computer_check_enemy_entrances(comp, check);
    long result;
    result = 4;
    PlayerNumber plyr_idx;
    for (plyr_idx=0; plyr_idx < PLAYERS_COUNT; plyr_idx++)
    {
        if (comp->dungeon->owner == plyr_idx) {
            continue;
        }
        if (players_are_mutual_allies(comp->dungeon->owner, plyr_idx)) {
            continue;
        }
        struct PlayerInfo *player;
        struct Dungeon *dungeon;
        player = get_player(plyr_idx);
        dungeon = get_players_dungeon(player);
        long i;
        unsigned long k;
        i = dungeon->room_kind[RoK_ENTRANCE];
        k = 0;
        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 Comp2_UnkStr1 *unkptr;
            unkptr = &comp->unkarr_A10[(int)plyr_idx];
            long n;
            for (n = 0; n < 64; n++)
            {
                struct Coord3d *pos;
                pos = &unkptr->pos_A[n];
                if ((pos->x.val == subtile_coord(room->central_stl_x,0)) && (pos->y.val == subtile_coord(room->central_stl_y,0))) {
                    break;
                }
            }
            if (n == 64)
            {
                struct Coord3d *pos;
                n = unkptr->field_4;
                unkptr->field_4 = (n + 1) % 64;
                unkptr->field_0 = game.play_gameturn;
                pos = &unkptr->pos_A[n];
                pos->x.val = subtile_coord(room->central_stl_x,0);
                pos->y.val = subtile_coord(room->central_stl_y,0);
                pos->z.val = subtile_coord(1,0);
                result = 2;
            }
            // Per-room code ends
            k++;
            if (k > ROOMS_COUNT)
            {
                ERRORLOG("Infinite loop detected when sweeping rooms list");
                break;
            }
        }
    }
    return result;
}
예제 #11
0
long computer_check_neutral_places(struct Computer2 *comp, struct ComputerCheck * check)
{
	if (is_newdig_enabled(comp))
		return 4;

    SYNCDBG(8,"Starting");
    struct Dungeon *dungeon;
    dungeon = comp->dungeon;
    if (dungeon_invalid(dungeon) || !player_has_heart(dungeon->owner)) {
        SYNCDBG(7,"Computer players %d dungeon in invalid or has no heart",(int)dungeon->owner);
        return CTaskRet_Unk4;
    }
    struct OpponentRelation *oprel;
    oprel = &comp->opponent_relations[game.neutral_player_num];
    struct Room *near_room;
    struct Coord3d *near_pos;
    int near_dist;
    near_room = INVALID_ROOM;
    near_dist = LONG_MAX;
    near_pos = &oprel->pos_A[0];
    int i;
    for (i=0; i < COMPUTER_SPARK_POSITIONS_COUNT; i++)
    {
        struct Coord3d *place;
        place = &oprel->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 CTaskRet_Unk4;
    }
    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 CTaskRet_Unk4;
    }
    near_pos->x.val = 0;
    near_pos->y.val = 0;
    near_pos->z.val = 0;
    return CTaskRet_Unk1;
}