Exemple #1
0
void remove_child(Agraph_t * graph, Agnode_t * node)
{
    Agedge_t *edge;
    Agedge_t *nexte;

    /* Avoid cycles */
    if MARKED
	(node) return;
    MARK(node);

    /* Skip nodes with more than one parent */
    edge = agfstin(node);
    if (edge && (agnxtin(edge) != NULL)) {
	UNMARK(node);
	return;
    }

    /* recursively remove children */
    for (edge = agfstout(node); edge; edge = nexte) {
	nexte = agnxtout(edge);
	if (aghead(edge) != node) {
	    if (verbose)
		fprintf(stderr, "Processing descendant: %s\n",
			agnameof(aghead(edge)));
	    remove_child(graph, aghead(edge));
	    agdeledge(edge);
	}
    }

    agdelnode(node);
    return;
}
Exemple #2
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;
}
Exemple #3
0
/* ********************************************************************
   This routines sorts a[0] ... a[n-1] using the fact that
   in their common prefix, after offset characters, there is a 
   suffix whose rank is known. In this routine we call this suffix anchor
   (and we denote its position and rank with anchor_pos and anchor_rank 
   respectively) but it is not necessarily an anchor (=does not necessarily 
   starts at position multiple of Anchor_dist) since this function is
   called by pseudo_anchor_sort().
   The routine works by scanning the suffixes before and after the anchor
   in order to find (and mark) those which are suffixes of a[0] ... a[n-1].
   After that, the ordering of a[0] ... a[n-1] is derived with a sigle
   scan of the marked suffixes.
   ******************************************************************** */
static void general_anchor_sort(Int32 *a, Int32 n, 
                         Int32 anchor_pos, Int32 anchor_rank, Int32 offset)
{
  int integer_cmp(const void *, const void *);
  Int32 sb, lo, hi;
  Int32 curr_lo, curr_hi, to_be_found, i,j;
  Int32 item; 
  void *ris;

  assert(Sa[anchor_rank]==anchor_pos);
  /* ---------- get bucket of anchor ---------- */
  sb = Get_small_bucket(anchor_pos);
  lo = BUCKET_FIRST(sb);
  hi = BUCKET_LAST(sb);
  assert(sb==Get_small_bucket(a[0]+offset));
  // ------ sort pointers a[0] ... a[n-1] as plain integers
  qsort(a,n, sizeof(Int32), integer_cmp);

  // ------------------------------------------------------------------
  // now we scan the bucket containing the anchor in search of suffixes
  // corresponding to the ones we have to sort. When we find one of
  // such suffixes we mark it. We go on untill n sfx's have been marked 
  // ------------------------------------------------------------------
  curr_hi = curr_lo = anchor_rank;

  // the anchor must correspond to a suffix to be sorted
  #if DEBUG
  item = anchor_pos-offset;
  assert(bsearch(&item,a,n,sizeof(Int32), integer_cmp));
  #endif

  MARK(curr_lo);
  // scan suffixes preceeding and following the anchor
  for(to_be_found=n-1;to_be_found>0; ) {
    // invariant: the next positions to check are curr_lo-1 and curr_hi+1
    assert(curr_lo > lo || curr_hi < hi);
    while (curr_lo > lo) {
      item = Sa[--curr_lo]-offset;
      ris = bsearch(&item,a,n,sizeof(Int32), integer_cmp);
      if(ris)	{MARK(curr_lo); to_be_found--;}
      else	break;
    }
    while (curr_hi < hi) {
      item = Sa[++curr_hi]-offset;
      ris = bsearch(&item,a,n,sizeof(Int32), integer_cmp);
      if(ris)	{MARK(curr_hi); to_be_found--;}
      else      break;
    }
  }
  // sort a[] using the marked suffixes
  for(j=0, i=curr_lo;i<=curr_hi;i++) 
    if(ISMARKED(i)) {
      UNMARK(i);
      a[j++] = Sa[i] - offset;
    }
  assert(j==n);  // make sure n items have been sorted
}
Exemple #4
0
void clean_room_queue( void )
{
    BFS_DATA *curr, *curr_next;

    for( curr = room_queue; curr; curr = curr_next )
    {
        UNMARK( curr->room );
        curr_next = curr->next;
        free( curr );
    }
    room_queue = NULL;
}
Exemple #5
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);
}
Exemple #6
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);
}
Exemple #7
0
int main(int argc, char **argv)
{
    int c;
    char *progname;

    ingraph_state ig;

    Agraph_t *graph;
    Agnode_t *node;
    Agedge_t *edge;
    Agedge_t *nexte;
    Agsym_t *attr;

    char **files;

    generic_list_t *attr_list;
    generic_list_t *node_list;

    unsigned long i, j;

    opterr = 0;

    progname = strrchr(argv[0], '/');
    if (progname == NULL) {
	progname = argv[0];
    } else {
	progname++;		/* character after last '/' */
    }

    attr_list = new_generic_list(16);
    node_list = new_generic_list(16);

    while ((c = getopt(argc, argv, "hvn:N:")) != -1) {
	switch (c) {
	case 'N':
	    {
		attr_list = addattr(attr_list, optarg);
		break;
	    }
	case 'n':
	    {
		node_list = addnode(node_list, optarg);
		break;
	    }
	case 'h':
	    {
		help_message(progname);
		exit(EXIT_SUCCESS);
		break;
	    }
	case 'v':
	    {
		verbose = 1;
		break;
	    }
	case '?':
	    if (isprint(optopt)) {
		fprintf(stderr, "Unknown option `-%c'.\n", optopt);
	    } else {
		fprintf(stderr, "Unknown option character `\\x%X'.\n",
			optopt);
	    }
	    exit(EXIT_FAILURE);
	    break;

	default:
	    help_message(progname);
	    exit(EXIT_FAILURE);
	    break;
	}
    }

    /* Any arguments left? */
    if (optind < argc) {
	files = &argv[optind];
    } else {
	files = NULL;
    }

    newIngraph(&ig, files, gread);
    while ((graph = nextGraph(&ig)) != NULL) {
	if (agisdirected(graph) == 0) {
	    fprintf(stderr,
		    "*** Error: Graph is undirected! Pruning works only with directed graphs!\n");
	    exit(EXIT_FAILURE);
	}

	/* attach node data for marking to all nodes */
	aginit(graph, AGNODE, NDNAME, sizeof(ndata), 1);

	/* prune all nodes specified on the commandline */
	for (i = 0; i < node_list->used; i++) {
	    if (verbose == 1)
		fprintf(stderr, "Pruning node %s\n",
			(char *) node_list->data[i]);

	    /* check whether a node of that name exists at all */
	    node = agnode(graph, (char *) node_list->data[i], 0);
	    if (node == NULL) {
		fprintf(stderr,
			"*** Warning: No such node: %s -- gracefully skipping this one\n",
			(char *) node_list->data[i]);
	    } else {
		MARK(node);	/* Avoid cycles */
		/* Iterate over all outgoing edges */
		for (edge = agfstout(node); edge; edge = nexte) {
		    nexte = agnxtout(edge);
		    if (aghead(edge) != node) {	/* non-loop edges */
			if (verbose == 1)
			    fprintf(stderr, "Processing descendant: %s\n",
				    agnameof(aghead(edge)));
			remove_child(graph, aghead(edge));
			agdelete(graph, edge);
		    }
		}
		UNMARK(node);	/* Unmark so that it can be removed in later passes */

		/* Change attribute (e.g. border style) to show that node has been pruneed */
		for (j = 0; j < attr_list->used; j++) {
		    /* create attribute if it doesn't exist and set it */
		    attr =
			agattr(graph, AGNODE,
			       ((strattr_t *) attr_list->data[j])->n, "");
		    if (attr == NULL) {
			fprintf(stderr, "Couldn't create attribute: %s\n",
				((strattr_t *) attr_list->data[j])->n);
			exit(EXIT_FAILURE);
		    }
		    agxset(node, attr,
			   ((strattr_t *) attr_list->data[j])->v);
		}
	    }
	}
	agwrite(graph, stdout);
	agclose(graph);
    }
    free(attr_list);
    free(node_list);
    exit(EXIT_SUCCESS);
}