Esempio n. 1
0
/**
 * Checks if given player is either friendly to origin player or defeated.
 * @param check_plyr_idx
 * @param origin_plyr_idx
 * @return
 */
TbBool player_is_friendly_or_defeated(PlayerNumber check_plyr_idx, PlayerNumber origin_plyr_idx)
{
    struct PlayerInfo *player;
    struct PlayerInfo *win_player;
    // Handle neutral player at first, because we can't get PlayerInfo nor Dungeon for it
    if ((origin_plyr_idx == game.neutral_player_num) || (check_plyr_idx == game.neutral_player_num))
        return true;
    player = get_player(check_plyr_idx);
    win_player = get_player(origin_plyr_idx);
    if (player_exists(player))
    {
        if ( (!player_allied_with(win_player, check_plyr_idx)) || (!player_allied_with(player, origin_plyr_idx)) )
        {
            if (player_has_heart(check_plyr_idx))
              return false;
        }
    }
    return true;
}
Esempio n. 2
0
/**
 * Returns if the trap can be manufactured by a player.
 * Checks only if it's set as buildable in level script.
 * Doesn't check if player has workshop or workforce for the task.
 */
TbBool is_trap_buildable(PlayerNumber plyr_idx, long tngmodel)
{
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon(plyr_idx);
    // Check if the player even have a dungeon
    if (dungeon_invalid(dungeon)) {
        return false;
    }
    // Player must have dungeon heart to build anything
    if (!player_has_heart(plyr_idx)) {
        return false;
    }
    if ((tngmodel <= 0) || (tngmodel >= TRAP_TYPES_COUNT)) {
        ERRORLOG("Incorrect trap %d (player %d)",(int)tngmodel, (int)plyr_idx);
        return false;
    }
    if ((dungeon->trap_build_flags[tngmodel] & MnfBldF_Manufacturable) != 0) {
        return true;
    }
    return false;
}
Esempio n. 3
0
/**
 * Returns if the trap can be placed by a player.
 * Checks only if it's available and if the player is 'alive'.
 * Doesn't check if map position is on correct spot.
 */
TbBool is_trap_placeable(PlayerNumber plyr_idx, long tngmodel)
{
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon(plyr_idx);
    // Check if the player even have a dungeon
    if (dungeon_invalid(dungeon)) {
        return false;
    }
    // Player must have dungeon heart to place traps
    if (!player_has_heart(plyr_idx)) {
        return false;
    }
    if ((tngmodel <= 0) || (tngmodel >= TRAP_TYPES_COUNT)) {
        ERRORLOG("Incorrect trap %d (player %d)",(int)tngmodel, (int)plyr_idx);
        return false;
    }
    if (dungeon->trap_amount_placeable[tngmodel] > 0) {
        return true;
    }
    return false;
}
Esempio n. 4
0
/**
 * Returns if the door was at least one built by a player.
 */
TbBool is_door_built(PlayerNumber plyr_idx, long door_idx)
{
    struct Dungeon *dungeon;
    dungeon = get_players_num_dungeon(plyr_idx);
    // Check if the player even have a dungeon
    if (dungeon_invalid(dungeon)) {
        return false;
    }
    // Player must have dungeon heart to build anything
    if (!player_has_heart(plyr_idx)) {
        return false;
    }
    if ((door_idx <= 0) || (door_idx >= DOOR_TYPES_COUNT)) {
        ERRORLOG("Incorrect door %d (player %d)",(int)door_idx, (int)plyr_idx);
        return false;
    }
    if ((dungeon->door_build_flags[door_idx] & MnfBldF_Built) != 0) {
        return true;
    }
    return false;
}
Esempio n. 5
0
long computer_check_for_expand_room(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;
    }
    long around_start;
    around_start = ACTION_RANDOM(119);
    // Don't work when placing rooms; we could place in an area for room by mistake
    if (is_task_in_progress(comp, CTT_PlaceRoom) || is_task_in_progress(comp, CTT_CheckRoomDug)) {
        SYNCDBG(8,"No rooms expansion - colliding task already in progress");
        return CTaskRet_Unk0;
    }
    if (computer_player_in_emergency_state(comp)) {
        SYNCDBG(8,"No rooms expansion - emergency state");
        return CTaskRet_Unk0;
    }
    if (get_computer_money_less_cost(comp) < dungeon->creatures_total_pay / 3) {
        SYNCDBG(8,"No rooms expansion - not enough money buffer");
        return CTaskRet_Unk0;
    }
    const struct ExpandRooms *expndroom;
    for (expndroom = &expand_rooms[0]; expndroom->rkind != RoK_NONE; expndroom++)
    {
        if (computer_check_for_expand_room_kind(comp, check, expndroom->rkind, expndroom->max_slabs, around_start)) {
            return CTaskRet_Unk1;
        }
    }
    SYNCDBG(8,"No rooms found for expansion");
    return CTaskRet_Unk0;
}
Esempio n. 6
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;
}
Esempio n. 7
0
/**
 * Checks if a computer player has not enough imps.
 * @param comp
 * @param check The check structure; param1 is preferred amount of imps, param2 is minimal amount.
 */
long computer_check_no_imps(struct Computer2 *comp, struct ComputerCheck * check)
{
	if (is_newdig_enabled(comp))
	{
		//workaround for interval seeming to be ignored by from my reconfiguration.
		//modern computers can handle interval 1 and interval 200 is awfully passive and easy to kill
		//interval 20 means player-like imp swarms will form while not being excessive
		//consider making configurable again if *properly* reconfiguring to 20 for all levels except easy beginner levels

		if (check->turns_interval > 20)
			check->turns_interval = 20;
		if (check->param2 < 8)
			check->param2 = 8;
	}

    struct Dungeon *dungeon;
    SYNCDBG(8,"Starting");
    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;
    }

	long power_price, lowest_price;
	TbBool diggers_are_cheap;
	power_price = compute_power_price(dungeon->owner, PwrK_MKDIGGER, 0);
	lowest_price = compute_lowest_digger_price(dungeon->owner);
	diggers_are_cheap = power_price <= lowest_price;

	//see if we can sacrifice imps to reduce price
	if (gameadd.sacrifice_info.classic_imp_sacrifice)
	{
		SYNCDBG(18, "Imp creation power price: %d, lowest: %d", power_price, lowest_price);

		if (!diggers_are_cheap
			&& dungeon->total_money_owned > power_price //TODO: might need to multiply for safety factor
			&& dungeon_has_room(dungeon, RoK_TEMPLE))
		{
			struct Thing* imp;
			imp = find_imp_for_sacrifice(comp->dungeon);
			if (!thing_is_invalid(imp))
			{
				long dist;
				struct Room* room;
				room = find_room_nearest_to_position(dungeon->owner, RoK_TEMPLE, &imp->mappos, &dist);
				if (!room_is_invalid(room))
				{
					if (create_task_move_creature_to_subtile(comp, imp, room->central_stl_x, room->central_stl_y, CrSt_CreatureSacrifice))
						return CTaskRet_Unk4;
				}
			}
		}
	}

	//regular old imp check after this point
    long controlled_diggers;
	TbBool digging_gems;
	long limit;
	digging_gems = is_digging_any_gems(dungeon);
    controlled_diggers = dungeon->num_active_diggers - count_player_diggers_not_counting_to_total(dungeon->owner);
	//SYNCLOG("controlled diggers of %d = %d, params = %d %d", (int)dungeon->owner, controlled_diggers, check->param1, check->param2);
	limit = check->param1;
	if (digging_gems)
	{
		if (diggers_are_cheap)
			limit = max(limit, 50);
		else
			limit = max(limit, 20);
	}
    if (controlled_diggers >= limit) {
        return CTaskRet_Unk4;
    }
    long able;
	if ((controlled_diggers == 0 || (controlled_diggers < 3 && (digging_gems || diggers_are_cheap))) && is_power_available(dungeon->owner, PwrK_MKDIGGER))
	{
		//ignore payday and everything else, we need at least 3 imp to play the game
		able = dungeon->total_money_owned >= compute_power_price(dungeon->owner, PwrK_MKDIGGER, 0);
		//TODO: recovery could be improved further by looking at length to payday and time it takes to get more money to increase lower bound
	} else if (controlled_diggers >= check->param2 && !digging_gems) {
        // We have less than preferred amount, but higher than minimal; allow building if we've got spare money
        able = computer_able_to_use_magic(comp, PwrK_MKDIGGER, 0, 3 + (controlled_diggers - check->param2)/4);
    } else {
        able = computer_able_to_use_magic(comp, PwrK_MKDIGGER, 0, 1);
    }
    if (able == CTaskRet_Unk1)
    {
        struct Thing *heartng;
        MapSubtlCoord stl_x, stl_y;
        heartng = get_player_soul_container(dungeon->owner);
        stl_x = heartng->mappos.x.stl.num;
        stl_y = heartng->mappos.y.stl.num;
        if (xy_walkable(stl_x, stl_y, dungeon->owner))
        {
            if (try_game_action(comp, dungeon->owner, GA_UseMkDigger, 0, stl_x, stl_y, 1, 1) > Lb_OK) {
                return CTaskRet_Unk1;
            }
        }
        return CTaskRet_Unk1;
    }
    return CTaskRet_Unk0;
}