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; }
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; }
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; }
/** * 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; }
/** * 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; }