Exemple #1
0
long computer_check_no_imps(struct Computer2 *comp, struct ComputerCheck * check)
{
    struct Dungeon *dungeon;
    SYNCDBG(8,"Starting");
    //return _DK_computer_check_no_imps(comp, check);
    dungeon = comp->dungeon;
    if (dungeon->num_active_diggers >= check->param1) {
        return 4;
    }
    long able;
    able = computer_able_to_use_magic(comp, PwrK_MKDIGGER, 0, 1);
    if (able == 1)
    {
        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) {
                able = 1;
            }
        }
    }
    return able;
}
Exemple #2
0
long computer_check_for_accelerate(struct Computer2 *comp, struct ComputerCheck * check)
{
    static RoomKind workers_in_rooms[] = {RoK_LIBRARY,RoK_LIBRARY,RoK_WORKSHOP,RoK_TRAINING,RoK_SCAVENGER};
    struct Thing *thing;
    long i,n;
    SYNCDBG(8,"Starting");
    //return _DK_computer_check_for_accelerate(comp, check);
    if (computer_able_to_use_magic(comp, PwrK_SPEEDCRTR, 8, 3) != 1)
    {
        return 4;
    }
    n = check->param1 % (sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0]));
    if (n <= 0)
        n = ACTION_RANDOM(sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0]));
    for (i=0; i < sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0]); i++)
    {
        thing = computer_check_creatures_in_dungeon_rooms_of_kind_for_accelerate(comp, workers_in_rooms[n]);
        if (!thing_is_invalid(thing))
        {
            SYNCDBG(8,"Cast on thing %d",(int)thing->index);
            return 1;
        }
        n = (n+1) % (sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0]));
    }
    return 4;
}
Exemple #3
0
long computer_check_for_pretty(struct Computer2 *comp, struct ComputerCheck * check)
{
    struct Dungeon *dungeon;
    SYNCDBG(8,"Starting");
    dungeon = comp->dungeon;
    MapSubtlCoord stl_x, stl_y;
    if (computer_able_to_use_magic(comp, PwrK_HAND, 1, 1) != CTaskRet_Unk1) {
        return CTaskRet_Unk4;
    }
    {
        long stack_len;
        stack_len = dungeon->digger_stack_length;
        if (stack_len <= check->param1 * dungeon->total_area / 100) {
            return CTaskRet_Unk4;
        }
        long n;
        n = find_in_imp_stack_starting_at(DigTsk_ImproveDungeon, ACTION_RANDOM(stack_len), dungeon);
        if (n < 0) {
            return CTaskRet_Unk4;
        }
        const struct DiggerStack *dstack;
        dstack = &dungeon->digger_stack[n];
        stl_x = stl_num_decode_x(dstack->stl_num);
        stl_y = stl_num_decode_y(dstack->stl_num);
    }
    struct Thing * creatng;
    creatng = find_imp_for_pickup(comp, stl_x, stl_y);
    if (thing_is_invalid(creatng)) {
        return CTaskRet_Unk4;
    }
    if (!create_task_move_creature_to_subtile(comp, creatng, stl_x, stl_y, CrSt_ImpImprovesDungeon)) {
        return CTaskRet_Unk4;
    }
    return CTaskRet_Unk1;
}
Exemple #4
0
long computer_check_move_creatures_to_best_room(struct Computer2 *comp, struct ComputerCheck * check)
{
    struct Dungeon *dungeon;
    dungeon = comp->dungeon;
    SYNCDBG(8,"Starting for player %d",(int)dungeon->owner);
    int num_to_move;
    num_to_move = check->param1 * dungeon->num_active_creatrs / 100;
    if (num_to_move <= 0) {
        SYNCDBG(8,"No player %d creatures to move, active %d percentage %d",
            (int)dungeon->owner,(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;
    }
    if (!create_task_move_creatures_to_room(comp, 0, num_to_move)) {
        return CTaskRet_Unk4;
    }
    SYNCDBG(8,"Added player %d task to move %d creatures to best room",(int)dungeon->owner,(int)num_to_move);
    return CTaskRet_Unk1;
}
Exemple #5
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;
}
Exemple #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;
}
Exemple #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;
}