Beispiel #1
0
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;
}
Beispiel #2
0
/* 
 * 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);
}
Beispiel #3
0
/*
 * 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);
}