int find_first_step(sh_int src, sh_int target, int stay_zone) { int curr_dir; sh_int curr_room; int src_zone = ((src - (src % 100)) / 100); int target_zone = ((target - (target % 100)) / 100); if (src < 0 || src > top_of_world || target < 0 || target > top_of_world) { stderr_log("Illegal value passed to find_first_step (graph.c)"); return BFS_ERROR; } /* dez 19980805 if ((src_zone != target_zone && stay_zone == 1) || stay_zone == 2) { return BFS_NO_PATH; } */ if (src_zone != target_zone && stay_zone == 1) { return BFS_NO_PATH; } if (src == target) { return BFS_ALREADY_THERE; } /* clear marks first */ for (curr_room = 0; curr_room <= top_of_world; curr_room++) { UNMARK(curr_room); } MARK(src); /* first, enqueue the first steps, saving which direction we're going. */ for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) { if (VALID_EDGE(src, curr_dir)) { MARK(TOROOM(src, curr_dir)); bfs_enqueue(TOROOM(src, curr_dir), curr_dir); } } /* now, do the classic BFS. */ while (queue_head) { if (queue_head->room == target) { curr_dir = queue_head->dir; bfs_clear_queue(); return curr_dir; } else { for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) { if (VALID_EDGE(queue_head->room, curr_dir)) { MARK(TOROOM(queue_head->room, curr_dir)); bfs_enqueue(TOROOM(queue_head->room, curr_dir), queue_head->dir); } } bfs_dequeue(); } } return BFS_NO_PATH; }
/* * find_first_step: given a source room and a target room, find the first * step on the shortest path from the source to the target. * * Intended usage: in mobile_activity, give a mob a dir to go if they're * tracking another mob or a PC. Or, a 'track' skill for PCs. */ int find_first_step(room_rnum src, room_rnum target) { int curr_dir; room_rnum curr_room; if (src == NOWHERE || target == NOWHERE || src > top_of_world || target > top_of_world) { extended_mudlog(NRM, SYSL_BUGS, TRUE, "Illegal value %d or %d passed to find_first_step. (%s)", src, target, __FILE__); return (BFS_ERROR); } if (src == target) return (BFS_ALREADY_THERE); /* clear marks first, some OLC systems will save the mark. */ for (curr_room = 0; curr_room <= top_of_world; curr_room++) UNMARK(curr_room); MARK(src); /* first, enqueue the first steps, saving which direction we're going. */ for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) if (VALID_EDGE(src, curr_dir)) { MARK(TOROOM(src, curr_dir)); bfs_enqueue(TOROOM(src, curr_dir), curr_dir); } /* now, do the classic BFS. */ while (queue_head) { if (queue_head->room == target) { curr_dir = queue_head->dir; bfs_clear_queue(); return (curr_dir); } else { for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) if (VALID_EDGE(queue_head->room, curr_dir)) { MARK(TOROOM(queue_head->room, curr_dir)); bfs_enqueue(TOROOM(queue_head->room, curr_dir), queue_head->dir); } bfs_dequeue(); } } return (BFS_NO_PATH); }
/* * find_first_step: given a source room and a target room, find the first * step on the shortest path from the source to the target. * * Intended usage: in mobile_activity, give a mob a dir to go if they're * tracking another mob or a PC. Or, a 'track' skill for PCs. */ int find_first_step(room_rnum src, room_rnum target, CHAR_DATA * ch) { int curr_dir, edge, through_doors; room_rnum curr_room, rnum_start = FIRST_ROOM, rnum_stop = top_of_world; if (src < FIRST_ROOM || src > top_of_world || target < FIRST_ROOM || target > top_of_world) { log("SYSERR: Illegal value %d or %d passed to find_first_step. (%s)", src, target, __FILE__); return (BFS_ERROR); } if (src == target) return (BFS_ALREADY_THERE); // clear marks first, some OLC systems will save the mark. if (IS_NPC(ch)) { // Запрещаем искать мобам в другой зоне ... if (world[src]->zone != world[target]->zone) return (BFS_ERROR); get_zone_rooms(world[src]->zone, &rnum_start, &rnum_stop); // Запрещаем мобам искать через двери ... through_doors = FALSE; edge = EDGE_ZONE; } else { // Игроки полноценно ищут в мире. through_doors = TRUE; edge = EDGE_WORLD; } for (curr_room = rnum_start; curr_room <= rnum_stop; curr_room++) UNMARK(curr_room); MARK(src); // переписано на вектор без реального очищения, чтобы не заниматься сотнями аллокаций памяти в секунду зря -- Krodo static std::vector<bfs_queue_struct> bfs_queue; static struct bfs_queue_struct temp_queue; // first, enqueue the first steps, saving which direction we're going. for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) if (VALID_EDGE(src, curr_dir, edge, through_doors)) { MARK(TOROOM(src, curr_dir)); temp_queue.room = TOROOM(src, curr_dir); temp_queue.dir = curr_dir; bfs_queue.push_back(temp_queue); } // now, do the classic BFS. for (unsigned int i = 0; i < bfs_queue.size(); ++i) { if (bfs_queue[i].room == target) { curr_dir = bfs_queue[i].dir; bfs_queue.clear(); return curr_dir; } else { for (curr_dir = 0; curr_dir < NUM_OF_DIRS; curr_dir++) { if (VALID_EDGE(bfs_queue[i].room, curr_dir, edge, through_doors)) { MARK(TOROOM(bfs_queue[i].room, curr_dir)); temp_queue.room = TOROOM(bfs_queue[i].room, curr_dir); temp_queue.dir = bfs_queue[i].dir; bfs_queue.push_back(temp_queue); } } } } bfs_queue.clear(); sprintf(buf, "Mob (mob: %s vnum: %d) can't find path.", GET_NAME(ch), GET_MOB_VNUM(ch)); mudlog(buf, NRM, -1, ERRLOG, TRUE); return (BFS_NO_PATH); }