long room_has_slab_adjacent(const struct Room *room, long slbkind) { long i; unsigned long k; k = 0; i = room->slabs_list; while (i > 0) { // Per room tile code long n; for (n=0; n < AROUND_SLAB_LENGTH; n++) { long slab_num; slab_num = i + around_slab[n]; struct SlabMap *slb; slb = get_slabmap_direct(slab_num); if (!slabmap_block_invalid(slb)) { if (slb->kind == slbkind) { return true; } } } // Per room tile code ends i = get_next_slab_number_in_room(i); k++; if (k > room->slabs_count) { ERRORLOG("Room slabs list length exceeded when sweeping"); break; } } return 0; }
TbBool jailbreak_possible(struct Room *room, long plyr_idx) { unsigned long i; unsigned long k; struct SlabMap *slb; if (room->owner == plyr_idx) { return false; } k = 0; i = room->slabs_list; while (i > 0) { slb = get_slabmap_direct(i); if (slabmap_block_invalid(slb)) { ERRORLOG("Jump to invalid room slab detected"); break; } if (slab_by_players_land(plyr_idx, slb_num_decode_x(i), slb_num_decode_y(i))) return true; i = get_next_slab_number_in_room(i); k++; if (k > map_tiles_x * map_tiles_y) { ERRORLOG("Infinite loop detected when sweeping room slabs"); break; } } return false; }
/** * Finds a creature passing by a room and having job different than given one, which has direct combat sight for given creature. * If such creature is not found, the function returns false and gives closest creature passing by a room and having job different than given one. * @param creatng The creature which should have combat sight of the target. * @param job_kind The job target should'n be performing. * @param room The room on which target creature is searched. * @param found_dist Distance to the target creature found. * @param found_thing The target creature found, either closest one or one with combat sight. * @return True if a target with combat sight was found. False if closest creature was found, or no creature met the conditions. * @note If no creature met the conditions, output variables are not initialized. Therefore, they should be initialized before calling this function. */ TbBool find_combat_target_passing_by_room_but_having_unrelated_job(const struct Thing *creatng, CreatureJob job_kind, const struct Room *room, unsigned long *found_dist, struct Thing **found_thing) { unsigned long i; unsigned long k; k = 0; i = room->slabs_list; while (i > 0) { MapSubtlCoord slb_x,slb_y; slb_x = slb_num_decode_x(i); slb_y = slb_num_decode_y(i); // Per-slab code if (find_combat_target_passing_by_slab_but_having_unrelated_job(creatng, job_kind, slb_x, slb_y, found_dist, found_thing)) { return true; } // Per-slab code ends i = get_next_slab_number_in_room(i); k++; if (k > room->slabs_count) { ERRORLOG("Infinite loop detected when sweeping room slabs"); break; } } // If found a creature, but it's not on sight return false; }
void setup_workshop_search_for_post(struct Thing *creatng) { struct Room *room; struct Thing *postng; postng = INVALID_THING; room = get_room_thing_is_on(creatng); // Find a random slab in the room to be used as our starting point long i; unsigned long n; i = ACTION_RANDOM(room->slabs_count); n = room->slabs_list; while (i > 0) { n = get_next_slab_number_in_room(n); i--; } i = room->slabs_count; while (i > 0) { // Loop the slabs list if (n <= 0) { n = room->slabs_list; } MapSlabCoord slb_x, slb_y; slb_x = subtile_slab_fast(stl_num_decode_x(n)); slb_y = subtile_slab_fast(stl_num_decode_y(n)); struct Thing *objtng; objtng = get_workshop_equipment_to_work_with_on_subtile(creatng->owner, slab_subtile_center(slb_x), slab_subtile_center(slb_y)); if (!thing_is_invalid(objtng)) { postng = objtng; } n = get_next_slab_number_in_room(n); i--; } if (thing_is_invalid(postng)) { SYNCDBG(9,"Work in %s, the %s moves to new pos",room_code_name(room->kind),thing_model_name(creatng)); setup_move_to_new_workshop_position(creatng, room, 1); } else { SYNCDBG(9,"Work in %s, the %s found a post",room_code_name(room->kind),thing_model_name(creatng)); setup_workshop_move(creatng, get_subtile_number(postng->mappos.x.stl.num, postng->mappos.y.stl.num)); } }
TbBool setup_head_for_random_unused_lair_slab(struct Thing *creatng, struct Room *room) { SlabCodedCoords slbnum; long n; unsigned long k; n = ACTION_RANDOM(room->slabs_count); slbnum = room->slabs_list; for (k = n; k > 0; k--) { if (slbnum == 0) break; slbnum = get_next_slab_number_in_room(slbnum); } if (slbnum == 0) { ERRORLOG("Taking random slab (%d/%d) in %s index %d failed - internal inconsistency.",(int)n,(int)room->slabs_count,room_code_name(room->kind),(int)room->index); slbnum = room->slabs_list; } k = 0; while (1) { MapSlabCoord slb_x,slb_y; slb_x = slb_num_decode_x(slbnum); slb_y = slb_num_decode_y(slbnum); struct Thing *lairtng; lairtng = find_creature_lair_at_subtile(slab_subtile_center(slb_x), slab_subtile_center(slb_y), 0); if (thing_is_invalid(lairtng)) { if (setup_person_move_to_position(creatng, slab_subtile_center(slb_x), slab_subtile_center(slb_y), NavRtF_Default)) { return true; } WARNLOG("Cannot get somewhere in room"); } slbnum = get_next_slab_number_in_room(slbnum); if (slbnum == 0) { slbnum = room->slabs_list; } k++; if (k >= room->slabs_count) { break; } } return false; }
/** * Finds a random training post near to the current position of given creature. * Used when finding a training post seems to be taking too long; in that case, creature should start training with a nearest post. * Note that this routine does not always select the nearest post - it is enough if it's 3 subtiles away. * * @param creatng The creature who wish to train with training post. */ void setup_training_search_for_post(struct Thing *creatng) { struct Room *room; struct Thing *traintng; struct Thing *thing; long start_slab; long min_distance,dist; long slb_x,slb_y; long i,k; room = get_room_thing_is_on(creatng); // Let's start from a random slab slb_x = -1; slb_y = -1; min_distance = LONG_MAX; traintng = INVALID_THING; start_slab = ACTION_RANDOM(room->slabs_count); k = start_slab; i = room->slabs_list; while (i != 0) { slb_x = slb_num_decode_x(i); slb_y = slb_num_decode_y(i); i = get_next_slab_number_in_room(i); if (k <= 0) break; k--; } // Got random starting slab, now sweep room slabs from it thing = INVALID_THING; k = room->slabs_count; i = get_slab_number(slb_x,slb_y); while (k > 0) { slb_x = slb_num_decode_x(i); slb_y = slb_num_decode_y(i); i = get_next_slab_number_in_room(i); if (i == 0) i = room->slabs_list; // Per room tile code - find a nearest training post thing = get_object_at_subtile_of_model_and_owned_by(slab_subtile_center(slb_x), slab_subtile_center(slb_y), 31, creatng->owner); if (!thing_is_invalid(thing)) { dist = get_2d_distance(&creatng->mappos, &thing->mappos); if (dist < min_distance) { traintng = thing; min_distance = dist; if (min_distance < (3<<8)) break; } } // Per room tile code ends k--; } // Got trainer (or not...), now do the correct action if (thing_is_invalid(traintng)) { SYNCDBG(6,"Room no longer have training post, moving somewhere else."); setup_move_to_new_training_position(creatng, room, true); } else { i = get_subtile_number(traintng->mappos.x.stl.num,traintng->mappos.y.stl.num); setup_training_move_near(creatng, i); } }
/** * 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; }