예제 #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;
}
예제 #2
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;
}
예제 #3
0
struct Thing *computer_check_creatures_in_room_for_accelerate(struct Computer2 *comp, struct Room *room)
{
    struct Dungeon *dungeon;
    struct StateInfo *stati;
    struct CreatureControl *cctrl;
    struct Thing *thing;
    unsigned long k;
    long i,n;
    dungeon = comp->dungeon;
    i = room->creatures_list;
    k = 0;
    while (i != 0)
    {
      thing = thing_get(i);
      cctrl = creature_control_get_from_thing(thing);
      if (thing_is_invalid(thing) || creature_control_invalid(cctrl))
      {
        ERRORLOG("Jump to invalid creature %ld detected",i);
        break;
      }
      i = cctrl->next_in_room;
      // Per creature code
      if (!thing_affected_by_spell(thing, SplK_Speed))
      {
          n = get_creature_state_besides_move(thing);
          stati = get_thing_state_info_num(n);
          if (stati->state_type == 1)
          {
              if (try_game_action(comp, dungeon->owner, GA_UsePwrSpeedUp, SPELL_MAX_LEVEL, 0, 0, thing->index, 0) > Lb_OK)
              {
                  return thing;
              }
          }
      }
      // Per creature code ends
      k++;
      if (k > THINGS_COUNT)
      {
        ERRORLOG("Infinite loop detected when sweeping things list");
        break;
      }
    }
    return INVALID_THING;
}
예제 #4
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;
}
예제 #5
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;
}