Beispiel #1
0
int main(int argc, char** argv) {
	srandom((argc <= 1)? time(NULL): atoi(argv[1]));

	#if 0
	const std::vector< std::vector<int> > costs = {
		{ 0, 0, 0, 0},
		{ 0, 2, 3, 3},
		{ 0, 3, 2, 3},
		{ 0, 3, 3, 2},
	};
	#else
	// const std::vector< std::vector<int> > costs = gen_cost_matrix<int>(6, 20);
	const std::vector< std::vector<int> > costs = {
		{0,  0,  0,  0,  0,  0},
		{0, 15, 16, 17, 18, 19}, 
		{0,  1,  1,  3,  1, 16}, 
		{0,  2,  8,  8,  6, 17},
		{0,  2,  2,  2,  8, 18},
		{0,  4,  6,  7,  8, 19},
	};
	#endif

	const std::vector<size_t>& pairs_ehm = solve_ap_ehm(costs);
	const std::vector<size_t>& pairs_rec = solve_ap_rec(costs);

	printf("[%s] cost=%d (%d)\n", __FUNCTION__, calc_cost(costs, pairs_ehm), calc_cost(costs, pairs_rec));
	return 0;
}
Beispiel #2
0
/*==========================================
 * 必要ならpathを追加/修正する
 *------------------------------------------
 */
static int add_path(int *heap,struct tmp_path *tp,int x,int y,int dist,int dir,int before,int x1,int y1)
{
	int i;

	i=calc_index(x,y);

	if(tp[i].x==x && tp[i].y==y){
		if(tp[i].dist>dist){
			tp[i].dist=dist;
			tp[i].dir=dir;
			tp[i].before=before;
			tp[i].cost=calc_cost(&tp[i],x1,y1);
			if(tp[i].flag)
				push_heap_path(heap,tp,i);
			else
				update_heap_path(heap,tp,i);
			tp[i].flag=0;
		}
		return 0;
	}

	if(tp[i].x || tp[i].y)
		return 1;

	tp[i].x=x;
	tp[i].y=y;
	tp[i].dist=dist;
	tp[i].dir=dir;
	tp[i].before=before;
	tp[i].cost=calc_cost(&tp[i],x1,y1);
	tp[i].flag=0;
	push_heap_path(heap,tp,i);

	return 0;
}
int ast_register_translator(struct ast_translator *t)
{
	char tmp[80];
	t->srcfmt = powerof(t->srcfmt);
	t->dstfmt = powerof(t->dstfmt);
	if (t->srcfmt >= MAX_FORMAT) {
		ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
		return -1;
	}
	if (t->dstfmt >= MAX_FORMAT) {
		ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
		return -1;
	}
	calc_cost(t,1);
	if (option_verbose > 1)
		ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
	ast_mutex_lock(&list_lock);
	if (!added_cli) {
		ast_cli_register(&show_trans);
		added_cli++;
	}
	t->next = list;
	list = t;
	rebuild_matrix(0);
	ast_mutex_unlock(&list_lock);
	return 0;
}
Beispiel #4
0
int init_cost(int edge[][SIZE+1])
{
	int i=0;
	for (i=1; i<=N; i++)
		population[i]->cost = calc_cost(population[i], edge);

	return 1;
}
Beispiel #5
0
int local_optimization(int n, int edge[][SIZE+1])
{
	int i, j, k;
	int	improved		=	1;
	int	modify			=	0;
	int cost			=	(offsprings[n]->cost = calc_cost(offsprings[n], edge));
	int permutation[SIZE+1];

	Chromosome *c;
	init_chromosome(&c);
	
	for (i=0; i<=SIZE; i++)
		c->ch[i] = offsprings[n]->ch[i];

	int num = 0;

	init_permutation(permutation);

	while (improved)
	{
		improved	=	0;

		for (i=1; i<=SIZE; i++)
		{
			int tmp	=	0;
			c->ch[permutation[i]] = (1 - c->ch[permutation[i]]) % 2;
			
			tmp = calc_cost(c, edge);

			if (tmp > cost)
			{
				offsprings[n]->ch[permutation[i]] = c->ch[permutation[i]];
				improved = 1;
				cost = tmp;
				offsprings[n]->cost = tmp;
			}
			else
				c->ch[permutation[i]] = (1 - c->ch[permutation[i]]) % 2;
		}
	}

	free_chromosome(c);

	return 1;
}
Beispiel #6
0
v3s16 pathfinder::get_dir_heuristic(std::vector<v3s16>& directions,path_gridnode& g_pos) {
	int   minscore = -1;
	v3s16 retdir   = v3s16(0,0,0);
	v3s16 srcpos = g_pos.pos;
	DEBUG_OUT("Pathfinder: remaining dirs at beginning:"
				<< directions.size() << std::endl);

	for (std::vector<v3s16>::iterator iter = directions.begin();
			iter != directions.end();
			++iter) {

		v3s16 pos1 =  v3s16(srcpos.X + iter->X,0,srcpos.Z+iter->Z);

		int cur_manhattan = get_manhattandistance(pos1);
		path_cost cost    = g_pos.get_cost(*iter);

		if (!cost.updated) {
			cost = calc_cost(g_pos.pos,*iter);
			g_pos.set_cost(*iter,cost);
		}

		if (cost.valid) {
			int score = cost.value + cur_manhattan;

			if ((minscore < 0)|| (score < minscore)) {
				minscore = score;
				retdir = *iter;
			}
		}
	}

	if (retdir != v3s16(0,0,0)) {
		for (std::vector<v3s16>::iterator iter = directions.begin();
					iter != directions.end();
					++iter) {
			if(*iter == retdir) {
				DEBUG_OUT("Pathfinder: removing return direction" << std::endl);
				directions.erase(iter);
				break;
			}
		}
	}
	else {
		DEBUG_OUT("Pathfinder: didn't find any valid direction clearing"
					<< std::endl);
		directions.clear();
	}
	DEBUG_OUT("Pathfinder: remaining dirs at end:" << directions.size()
				<< std::endl);
	return retdir;
}
/*! \brief Use the list of translators to build a translation matrix */
static void rebuild_matrix(int samples)
{
	struct ast_translator *t;
	int changed;
	int x,y,z;

	if (option_debug)
		ast_log(LOG_DEBUG, "Resetting translation matrix\n");
	memset(tr_matrix, 0, sizeof(tr_matrix));
	t = list;
	while(t) {
		if(samples)
			calc_cost(t, samples);
	  
		if (!tr_matrix[t->srcfmt][t->dstfmt].step ||
		     tr_matrix[t->srcfmt][t->dstfmt].cost > t->cost) {
			tr_matrix[t->srcfmt][t->dstfmt].step = t;
			tr_matrix[t->srcfmt][t->dstfmt].cost = t->cost;
		}
		t = t->next;
	}
	do {
		changed = 0;
		/* Don't you just love O(N^3) operations? */
		for (x=0; x< MAX_FORMAT; x++)				/* For each source format */
			for (y=0; y < MAX_FORMAT; y++) 			/* And each destination format */
				if (x != y)				/* Except ourselves, of course */
					for (z=0; z < MAX_FORMAT; z++) 	/* And each format it might convert to */
						if ((x!=z) && (y!=z)) 		/* Don't ever convert back to us */
							if (tr_matrix[x][y].step && /* We can convert from x to y */
								tr_matrix[y][z].step && /* And from y to z and... */
								(!tr_matrix[x][z].step || 	/* Either there isn't an x->z conversion */
								(tr_matrix[x][y].cost + 
								 tr_matrix[y][z].cost <	/* Or we're cheaper than the existing */
								 tr_matrix[x][z].cost)  /* solution */
							     )) {
								 			/* We can get from x to z via y with a cost that
											   is the sum of the transition from x to y and
											   from y to z */
								 
								 	tr_matrix[x][z].step = tr_matrix[x][y].step;
									tr_matrix[x][z].cost = tr_matrix[x][y].cost + 
														   tr_matrix[y][z].cost;
									if (option_debug)
										ast_log(LOG_DEBUG, "Discovered %d cost path from %s to %s, via %d\n", tr_matrix[x][z].cost, ast_getformatname(x), ast_getformatname(z), y);
									changed++;
								 }
		
	} while (changed);
}
Beispiel #8
0
//---------------------------gen_match-----------------------------------------
void ArchDesc::gen_match(FILE *fp, MatchList &mList, ProductionState &status, Dict &operands_chained_from) {
    const char *spaces4 = "    ";
    const char *spaces6 = "      ";

    fprintf(fp, "%s", spaces4);
    // Only generate child tests if this is not a leaf node
    bool has_child_constraints = mList._lchild || mList._rchild;
    const char *predicate_test        = mList.get_pred();
    if( has_child_constraints || predicate_test ) {
        // Open the child-and-predicate-test braces
        fprintf(fp, "if( ");
        status.set_constraint(hasConstraint);
        child_test(fp, mList);
        // Only generate predicate test if one exists for this match
        if( predicate_test ) {
            if( has_child_constraints ) {
                fprintf(fp," &&\n");
            }
            fprintf(fp, "%s  %s", spaces6, predicate_test);
        }
        // End of outer tests
        fprintf(fp," ) ");
    } else {
        // No child or predicate test needed
        status.set_constraint(noConstraint);
    }

    // End of outer tests
    fprintf(fp,"{\n");

    // Calculate cost of this match
    const Expr *cost = calc_cost(fp, spaces6, mList, status);
    // Check against other match costs, and update cost & rule vectors
    cost_check(fp, spaces6, ArchDesc::getMachOperEnum(mList._resultStr), cost, mList._opcode, status);

    // If this is a member of an operand class, update the class cost & rule
    expand_opclass( fp, spaces6, cost, mList._resultStr, status);

    // Check if this rule should be used to generate the chains as well.
    const char *rule = /* set rule to "Invalid" for internal operands */
        strcmp(mList._opcode,mList._resultStr) ? mList._opcode : "Invalid";

    // If this rule produces an operand which has associated chain rules,
    // update the operands with the chain rule + this rule cost & this rule.
    chain_rule(fp, spaces6, mList._resultStr, cost, rule, operands_chained_from, status);

    // Close the child-and-predicate-test braces
    fprintf(fp, "    }\n");

}
Beispiel #9
0
int find_ans(){
	int dx,dy,cx,cy,i;
	
	/* enum each point to be destinaon */
	for(dx=0;dx<C;dx++)for(dy=0;dy<R;dy++){
		int mi = d_king[dx][dy];/* the king's minimal cost to get to destination */
		/* enum each point that king get touch with knight */
		for(cx=0;cx<C;cx++)for(cy=0;cy<R;cy++)if( d_king[cx][cy] < mi ){
			for(i=0;i<n_knight;i++){/* which knight to get touch with */
				int cost = calc_cost(dx,dy,cx,cy,i);
				if(cost<mi)mi=cost;
			}
		}
		if( (d_all[dx][dy] + mi) < mi_s )
			mi_s = d_all[dx][dy] + mi;
	}
	
	return 0;
}
int replacement(int edge[][SIZE+1])
{
	int i=0, r=0;

	for (i=1; i<=K; i++)
		offsprings[i]->cost = calc_cost(offsprings[i], edge);

	for (i=1; i<=K; i++)
	{
		if ((offsprings[i]->p1 < r) || (population[offsprings[i]->p1]->cost > offsprings[i]->cost))
		{
			r++;
			memcpy(population[r], offsprings[i], sizeof(Chromosome));
		} 
		else 
			memcpy(population[offsprings[i]->p1], offsprings[i], sizeof(Chromosome));
	}
	
	return 1;
}
Beispiel #11
0
Results* join_clusters2_restart
(double *x,//array/matrix of data
 SymNoDiag *W,//lower triangle of weight matrix
 unsigned int Px,//problem size
 double lambda,//starting point in regularization path
 double join_thresh, //tolerance for equality of points
 double opt_thresh, //tolerance for optimality
 double lambda_factor,//increase of lambda after optimality
 double smooth,//smoothing parameter
 int maxit,
 int linesearch_freq,//how often to do a linesearch? if 0, never. if
		     //n>0, do n-1 linesearch steps for every
		     //decreasing step size step. set this to 2 if
		     //unsure.
 int linesearch_points,//how many points to check along the gradient
		       //direction. set to 10 if unsure.
 int check_splits,
 int target_cluster,
 int verbose
 ){
  unsigned int N = W->N;
  //W->print();
  double old_lambda=0;
  std::vector<int> rows,rowsj;
  std::vector<int>::iterator rowit,ri,rj;
  std::list< std::vector<int> > clusters,tocheck;
  std::list< std::vector<int> >::iterator it,cj;
  unsigned int i,k,j;
  int tried_restart;
  for(i=0;i<N;i++){
    rows.assign(1,i);
    clusters.push_back(rows);
  }
  double *old_alpha = new double[N*Px];
  double *alpha = new double[N*Px];
  double *xbar = new double[N*Px];
  double *dir = new double[N*Px];
  for(i=0;i<N*Px;i++){
    alpha[i]=xbar[i]=x[i];
  }
  Matrix amat(alpha,N,Px),xmat(x,N,Px);
  SymNoDiag diffs(N);
  diffs.calc_diffs(clusters,amat,nrm2);
  //store initial trivial solution
  Results *results = new Results(N,Px,opt_thresh);
  if(target_cluster==0)results->add(alpha,0,0);
  double weight,diff,step;
  while(clusters.size()>1){
    double grad=opt_thresh;
    int iteration=1;
    tried_restart=0;
    //if we use the general (slower) algorithm for any weights, then
    //split the clusters to individual points
    if(check_splits){
      clusters.clear();
      //reassign original clusters
      for(i=0;i<N;i++){
	rows.assign(1,i);
	clusters.push_back(rows);
      }
      //recopy original xbar
      for(i=0;i<N*Px;i++){
	xbar[i]=x[i];
      }
    }
    while(grad>=opt_thresh){
      //first calc gradients
      grad = 0;
      for(it=clusters.begin();it!=clusters.end();it++){
	rows = *it;
	i = rows[0];
	for(k=0;k<Px;k++){
	  dir[i+k*N] = xbar[i+k*N] - alpha[i+k*N];
	}
	for(cj=clusters.begin();cj!=clusters.end();cj++){
	  if(it!=cj){
	    rowsj = *cj;
	    j=rowsj[0];
	    weight=0;
	    diff = *diffs(i,j);
	    if(diff!=0){
	      if(smooth!=0){
		diff *= diff; //now squared l2 norm
		diff += smooth; //add smoothing parameter under sqrt
		diff = sqrt(diff);//put sqrt back
	      }
	      for(ri=rows.begin();ri!=rows.end();ri++){
		for(rj=rowsj.begin();rj!=rowsj.end();rj++){
		  weight += W->getval(*ri,*rj);
		}
	      }
	      //weight *= lambda / diff / ((double)(N-1)) / ((double)rows.size());
	      weight *= lambda / diff / ((double)rows.size());
	      for(k=0;k<Px;k++){
		dir[i+k*N] += weight * (alpha[j+k*N]-alpha[i+k*N]);
	      }
	    }
	  }
	}
	grad += nrm2(Array(dir+i,N,Px));
      }
      //store this iteration
      //results->add(alpha,lambda,grad);
      //then take a step
      if(linesearch_freq==0 || (iteration % linesearch_freq)==0 ){
	//Decreasing step size
	//TDH and pierre 18 jan 2011 try sqrt dec step size
	step=1/((double)iteration);
	//step=1/sqrt((double)iteration);
	if(verbose>=2)printf("grad %f step %f it %d\n",grad,step,iteration);
	take_step(clusters,alpha,dir,N,Px,step);
      }else{
	double cost_here,cost_step;
	std::map<double,double> cost_steps;
	std::map<double,double>::iterator step1,step2;
	for(i=0;i<N*Px;i++)old_alpha[i]=alpha[i];//copy alpha
	//compare current cost to cost after stepping in gradient direction
	cost_here=cost_step=calc_cost(clusters,amat,xmat,W,diffs,lambda);
	step = 0;
	cost_steps.insert(std::pair<double,double>(cost_here,0));
	while(cost_step<=cost_here){
	  take_step(clusters,alpha,dir,N,Px,1);
	  step += 1;
	  diffs.calc_diffs(clusters,amat,nrm2);
	  cost_step=calc_cost(clusters,amat,xmat,W,diffs,lambda);
	  if(verbose>=2)
	printf("cost %.10f step %f cost_here %f\n",cost_step,step,cost_here);
	  cost_steps.insert(std::pair<double,double>(cost_step,step));
	}
	for(int cuts=0;cuts<linesearch_points;cuts++){
	  step1=step2=cost_steps.begin();
	  step2++;
	  step = (step1->second + step2->second)/2;
	  for(i=0;i<N*Px;i++){
	    alpha[i]=old_alpha[i];
	  }
	  take_step(clusters,alpha,dir,N,Px,step);
	  diffs.calc_diffs(clusters,amat,nrm2);
	  cost_step=calc_cost(clusters,amat,xmat,W,diffs,lambda);
	  if(verbose>=2)printf("cost %.10f step %f %d\n",cost_step,step,cuts);
	  cost_steps.insert(std::pair<double,double>(cost_step,step));
	}
	cost_steps.clear();
      }
      if(iteration++ > maxit){
	if(tried_restart){
	  printf("max iteration %d exit\n",maxit);
	  delete old_alpha;
	  delete alpha;
	  delete xbar;
	  delete dir;
	  return results;
	}else{
	  if(verbose>=1)printf("max iterations, trying restart from x\n");
	  tried_restart=1;
	  iteration=1;
	  for(i=0;i<N*Px;i++)alpha[i]=x[i];
	}
      }
      //calculate differences
      diffs.calc_diffs(clusters,amat,nrm2);
      //check for joins
      JoinPair tojoin;
      while(dojoin(tojoin=check_clusters_thresh(&clusters,diffs,join_thresh))){
	//if(verbose>=1)
	//  printf("join: %d %d\n",tojoin.first->front(),tojoin.second->front());
	int ni=tojoin.first->size();
	int nj=tojoin.second->size();
	i=tojoin.first->front();
	j=tojoin.second->front();
	tojoin.first->insert(tojoin.first->end(),
			    tojoin.second->begin(),
			    tojoin.second->end());
	for(k=0;k<Px;k++){
	  alpha[i+k*N] = (alpha[i+k*N]*ni + alpha[j+k*N]*nj)/(ni+nj);
	  xbar[i+k*N] = (xbar[i+k*N]*ni + xbar[j+k*N]*nj)/(ni+nj);
	}
	clusters.erase(tojoin.second);
	iteration=1;
	if(clusters.size()>1){
	  diffs.calc_diffs(clusters,amat,nrm2);//inefficient
	}else{
	  grad=0;//so we can escape from the last optimization loop
	}
      }
    }//while(grad>=opt_thresh)
    if(verbose>=1)
    printf("solution iteration %d lambda %f nclusters %d\n",
	   iteration,lambda,(int)clusters.size());
    
    if(target_cluster == 0){
      //for each cluster, there may be several points. we store the
      //alpha value just in the row of the first point. thus here we
      //copy this value to the other rows before copying the optimal
      //alpha to results.
      for(it=clusters.begin();it!=clusters.end();it++){
	rows = *it;
	if(rows.size()>1){
	  for(i=1;i<rows.size();i++){
	    for(k=0;k<Px;k++){
	      alpha[rows[i]+k*N] = alpha[rows[0]+k*N];
	    }
	  }
	}
      }
      results->add(alpha,lambda,grad);
    }
    //haven't yet reached the target number of clusters, multiply
    //lambda by lambda_factor and continue along the path
    if((int)clusters.size()>target_cluster){
      old_lambda=lambda;
      lambda *= lambda_factor;
    }
    //if we have passed the target cluster number then decrease
    //lambda and go look for it!
    if((int)clusters.size()<target_cluster){
      if(verbose>=1){
	printf("missed target %d, going back for it\n",target_cluster);
      }
      lambda = (lambda+old_lambda)/2;
      clusters.clear();
      //reassign original clusters
      for(i=0;i<N;i++){
	rows.assign(1,i);
	clusters.push_back(rows);
      }
      //recopy original xbar
      for(i=0;i<N*Px;i++){
	xbar[i]=x[i];
      }
    }
    //this is the number of clusters that we were looking for,
    //save and quit!
    if((int)clusters.size()==target_cluster){
      for(it=clusters.begin();it!=clusters.end();it++){
	rows = *it;
	if(rows.size()>1){
	  for(i=1;i<rows.size();i++){
	    for(k=0;k<Px;k++){
	      alpha[rows[i]+k*N] = alpha[rows[0]+k*N];
	    }
	  }
	}
      }
      results->add(alpha,lambda,grad);
      if(verbose>=1)printf("got target cluster %d exit\n",target_cluster);
      delete old_alpha;
      delete alpha;
      delete xbar;
      delete dir;
      return results;
    }
  }	
  //TODO: consolidate cleanup... just use data structures that
  //automatically clean themselves up when the function exits.
  delete old_alpha;
  delete alpha;
  delete xbar;
  delete dir;
  return results;
}
Beispiel #12
0
/*==========================================
 * path search (x0,y0)->(x1,y1)
 * wpd: path info will be written here
 * flag: &1 = easy path search only
 * cell: type of obstruction to check for
 *------------------------------------------*/
bool path_search (struct walkpath_data *wpd, int m, int x0, int y0, int x1, int y1, int flag, cell_chk cell)
{
	int heap[MAX_HEAP + 1];
	struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH];
	register int i, j, len, x, y, dx, dy;
	int rp, xs, ys;
	struct map_data *md;
	struct walkpath_data s_wpd;

	if (wpd == NULL)
		wpd = &s_wpd; // use dummy output variable

	if (!map[m].cell)
		return false;

	md = &map[m];
#ifdef CELL_NOSTACK

	//Do not check starting cell as that would get you stuck.
	if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys)
#else
	if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| map_getcellp(md,x0,y0,cell)*/)
#endif
		return false;

	if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || map_getcellp (md, x1, y1, cell))
		return false;

	// calculate (sgn(x1-x0), sgn(y1-y0))
	dx = ( (dx = x1 - x0)) ? ( (dx < 0) ? -1 : 1) : 0;
	dy = ( (dy = y1 - y0)) ? ( (dy < 0) ? -1 : 1) : 0;
	// try finding direct path to target
	x = x0;
	y = y0;
	i = 0;

	while (i < ARRAYLENGTH (wpd->path))
	{
		wpd->path[i] = walk_choices[-dy + 1][dx + 1];
		i++;
		x += dx;
		y += dy;

		if (x == x1) dx = 0;

		if (y == y1) dy = 0;

		if (dx == 0 && dy == 0)
			break; // success

		if (map_getcellp (md, x, y, cell))
			break; // obstacle = failure
	}

	if (x == x1 && y == y1)
	{
		//easy path successful.
		wpd->path_len = i;
		wpd->path_pos = 0;
		return true;
	}

	if (flag & 1)
		return false;

	memset (tp, 0, sizeof (tp));
	i = calc_index (x0, y0);
	tp[i].x = x0;
	tp[i].y = y0;
	tp[i].dist = 0;
	tp[i].before = 0;
	tp[i].cost = calc_cost (&tp[i], x1, y1);
	tp[i].flag = 0;
	heap[0] = 0;
	push_heap_path (heap, tp, calc_index (x0, y0));
	xs = md->xs - 1; // あらかじめ1減算しておく
	ys = md->ys - 1;

	for (;;)
	{
		int e = 0, f = 0, dist, cost, dc[4] = {0, 0, 0, 0};

		if (heap[0] == 0)
			return false;

		rp   = pop_heap_path (heap, tp);
		x    = tp[rp].x;
		y    = tp[rp].y;
		dist = tp[rp].dist + 10;
		cost = tp[rp].cost;

		if (x == x1 && y == y1)
			break;

		// dc[0] : y++ の時のコスト増分
		// dc[1] : x-- の時のコスト増分
		// dc[2] : y-- の時のコスト増分
		// dc[3] : x++ の時のコスト増分

		if (y < ys && !map_getcellp (md, x  , y + 1, cell))
		{
			f |= 1; dc[0] = (y >= y1 ? 20 : 0);
			e += add_path (heap, tp, x  , y + 1, dist, rp, cost + dc[0]); // (x,   y+1)
		}

		if (x > 0  && !map_getcellp (md, x - 1, y  , cell))
		{
			f |= 2; dc[1] = (x <= x1 ? 20 : 0);
			e += add_path (heap, tp, x - 1, y  , dist, rp, cost + dc[1]); // (x-1, y  )
		}

		if (y > 0  && !map_getcellp (md, x  , y - 1, cell))
		{
			f |= 4; dc[2] = (y <= y1 ? 20 : 0);
			e += add_path (heap, tp, x  , y - 1, dist, rp, cost + dc[2]); // (x  , y-1)
		}

		if (x < xs && !map_getcellp (md, x + 1, y  , cell))
		{
			f |= 8; dc[3] = (x >= x1 ? 20 : 0);
			e += add_path (heap, tp, x + 1, y  , dist, rp, cost + dc[3]); // (x+1, y  )
		}

		if ( (f & (2 + 1)) == (2 + 1) && !map_getcellp (md, x - 1, y + 1, cell))
			e += add_path (heap, tp, x - 1, y + 1, dist + 4, rp, cost + dc[1] + dc[0] - 6);		// (x-1, y+1)

		if ( (f & (2 + 4)) == (2 + 4) && !map_getcellp (md, x - 1, y - 1, cell))
			e += add_path (heap, tp, x - 1, y - 1, dist + 4, rp, cost + dc[1] + dc[2] - 6);		// (x-1, y-1)

		if ( (f & (8 + 4)) == (8 + 4) && !map_getcellp (md, x + 1, y - 1, cell))
			e += add_path (heap, tp, x + 1, y - 1, dist + 4, rp, cost + dc[3] + dc[2] - 6);		// (x+1, y-1)

		if ( (f & (8 + 1)) == (8 + 1) && !map_getcellp (md, x + 1, y + 1, cell))
			e += add_path (heap, tp, x + 1, y + 1, dist + 4, rp, cost + dc[3] + dc[0] - 6);		// (x+1, y+1)

		tp[rp].flag = 1;

		if (e || heap[0] >= MAX_HEAP - 5)
			return false;
	}

	if (! (x == x1 && y == y1)) // will never happen...
		return false;

	for (len = 0, i = rp; len < 100 && i != calc_index (x0, y0); i = tp[i].before, len++);

	if (len == 100 || len >= sizeof (wpd->path))
		return false;

	wpd->path_len = len;
	wpd->path_pos = 0;

	for (i = rp, j = len - 1; j >= 0; i = tp[i].before, j--)
	{
		int dx  = tp[i].x - tp[tp[i].before].x;
		int dy  = tp[i].y - tp[tp[i].before].y;
		int dir;

		if (dx == 0)
		{
			dir = (dy > 0 ? 0 : 4);
		}
		else if (dx > 0)
		{
			dir = (dy == 0 ? 6 : (dy < 0 ? 5 : 7));
		}
		else
		{
			dir = (dy == 0 ? 2 : (dy > 0 ? 1 : 3));
		}

		wpd->path[j] = dir;
	}

	return true;
}
Beispiel #13
0
/*==========================================
 * path探索 (x0,y0)->(x1,y1)
 *------------------------------------------
 */
int path_search(struct walkpath_data *wpd, map_local *m, int x0, int y0, int x1, int y1, int flag)
{
    int heap[MAX_HEAP + 1];
    int i, rp, x, y;
    int dx, dy;

    nullpo_ret(wpd);

    assert (m->gat);
    map_local *md = m;
    if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys
        || bool(read_gatp(md, x1, y1) & MapCell::UNWALKABLE))
        return -1;

    // easy
    dx = (x1 - x0 < 0) ? -1 : 1;
    dy = (y1 - y0 < 0) ? -1 : 1;
    for (x = x0, y = y0, i = 0; x != x1 || y != y1;)
    {
        if (i >= sizeof(wpd->path))
            return -1;
        if (x != x1 && y != y1)
        {
            if (!can_move(md, x, y, x + dx, y + dy))
                break;
            x += dx;
            y += dy;
            wpd->path[i++] = (dx < 0)
                ? ((dy > 0) ? DIR::SW : DIR::NW)
                : ((dy < 0) ? DIR::NE : DIR::SE);
        }
        else if (x != x1)
        {
            if (!can_move(md, x, y, x + dx, y))
                break;
            x += dx;
            wpd->path[i++] = (dx < 0) ? DIR::W : DIR::E;
        }
        else
        {                       // y!=y1
            if (!can_move(md, x, y, x, y + dy))
                break;
            y += dy;
            wpd->path[i++] = (dy > 0) ? DIR::S : DIR::N;
        }
        if (x == x1 && y == y1)
        {
            wpd->path_len = i;
            wpd->path_pos = 0;
            wpd->path_half = 0;
            return 0;
        }
    }
    if (flag & 1)
        return -1;

    struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH] {};

    i = calc_index(x0, y0);
    tp[i].x = x0;
    tp[i].y = y0;
    tp[i].dist = 0;
    tp[i].dir = DIR::S;
    tp[i].before = 0;
    tp[i].cost = calc_cost(&tp[i], x1, y1);
    tp[i].flag = 0;
    heap[0] = 0;
    push_heap_path(heap, tp, calc_index(x0, y0));
    while (1)
    {
        int e = 0;

        if (heap[0] == 0)
            return -1;
        rp = pop_heap_path(heap, tp);
        x = tp[rp].x;
        y = tp[rp].y;
        if (x == x1 && y == y1)
        {
            int len, j;

            for (len = 0, i = rp; len < 100 && i != calc_index(x0, y0);
                 i = tp[i].before, len++);
            if (len == 100 || len >= sizeof(wpd->path))
                return -1;
            wpd->path_len = len;
            wpd->path_pos = 0;
            wpd->path_half = 0;
            for (i = rp, j = len - 1; j >= 0; i = tp[i].before, j--)
                wpd->path[j] = tp[i].dir;

            return 0;
        }
        if (can_move(md, x, y, x + 1, y - 1))
            e += add_path(heap, tp, x + 1, y - 1, tp[rp].dist + 14, DIR::NE, rp, x1, y1);
        if (can_move(md, x, y, x + 1, y))
            e += add_path(heap, tp, x + 1, y, tp[rp].dist + 10, DIR::E, rp, x1, y1);
        if (can_move(md, x, y, x + 1, y + 1))
            e += add_path(heap, tp, x + 1, y + 1, tp[rp].dist + 14, DIR::SE, rp, x1, y1);
        if (can_move(md, x, y, x, y + 1))
            e += add_path(heap, tp, x, y + 1, tp[rp].dist + 10, DIR::S, rp, x1, y1);
        if (can_move(md, x, y, x - 1, y + 1))
            e += add_path(heap, tp, x - 1, y + 1, tp[rp].dist + 14, DIR::SW, rp, x1, y1);
        if (can_move(md, x, y, x - 1, y))
            e += add_path(heap, tp, x - 1, y, tp[rp].dist + 10, DIR::W, rp, x1, y1);
        if (can_move(md, x, y, x - 1, y - 1))
            e += add_path(heap, tp, x - 1, y - 1, tp[rp].dist + 14, DIR::NW, rp, x1, y1);
        if (can_move(md, x, y, x, y - 1))
            e += add_path(heap, tp, x, y - 1, tp[rp].dist + 10, DIR::N, rp, x1, y1);
        tp[rp].flag = 1;
        if (e || heap[0] >= MAX_HEAP - 5)
            return -1;
    }
}
Beispiel #14
0
bool pathfinder::build_costmap()
{
	INFO_TARGET << "Pathfinder build costmap: (" << m_limits.X.min << ","
												<< m_limits.Z.min << ") ("
												<< m_limits.X.max << ","
												<< m_limits.Z.max << ")"
												<< std::endl;
	m_data.resize(m_max_index_x);
	for (int x = 0; x < m_max_index_x; x++) {
		m_data[x].resize(m_max_index_z);
		for (int z = 0; z < m_max_index_z; z++) {
			m_data[x][z].resize(m_max_index_y);

			int surfaces = 0;
			for (int y = 0; y < m_max_index_y; y++) {
				v3s16 ipos(x,y,z);

				v3s16 realpos = getRealPos(ipos);

				MapNode current = m_env->getMap().getNodeNoEx(realpos);
				MapNode below   = m_env->getMap().getNodeNoEx(realpos + v3s16(0,-1,0));


				if ((current.param0 == CONTENT_IGNORE) ||
						(below.param0 == CONTENT_IGNORE)) {
					DEBUG_OUT("Pathfinder: " << PPOS(realpos) <<
							" current or below is invalid element" << std::endl);
					if (current.param0 == CONTENT_IGNORE) {
						m_data[x][z][y].type = 'i';
						DEBUG_OUT(x << "," << y << "," << z << ": " << 'i' << std::endl);
					}
					continue;
				}

				//don't add anything if it isn't an air node
				if ((current.param0 != CONTENT_AIR) ||
						(below.param0 == CONTENT_AIR )) {
						DEBUG_OUT("Pathfinder: " << PPOS(realpos)
								<< " not on surface" << std::endl);
						if (current.param0 != CONTENT_AIR) {
							m_data[x][z][y].type = 's';
							DEBUG_OUT(x << "," << y << "," << z << ": " << 's' << std::endl);
						}
						else {
							m_data[x][z][y].type   = '-';
							DEBUG_OUT(x << "," << y << "," << z << ": " << '-' << std::endl);
						}
						continue;
				}

				surfaces++;

				m_data[x][z][y].valid  = true;
				m_data[x][z][y].pos    = realpos;
				m_data[x][z][y].type   = 'g';
				DEBUG_OUT(x << "," << y << "," << z << ": " << 'a' << std::endl);

				if (m_prefetch) {
				m_data[x][z][y].directions[DIR_XP] =
											calc_cost(realpos,v3s16( 1,0, 0));
				m_data[x][z][y].directions[DIR_XM] =
											calc_cost(realpos,v3s16(-1,0, 0));
				m_data[x][z][y].directions[DIR_ZP] =
											calc_cost(realpos,v3s16( 0,0, 1));
				m_data[x][z][y].directions[DIR_ZM] =
											calc_cost(realpos,v3s16( 0,0,-1));
				}

			}

			if (surfaces >= 1 ) {
				for (int y = 0; y < m_max_index_y; y++) {
					if (m_data[x][z][y].valid) {
						m_data[x][z][y].surfaces = surfaces;
					}
				}
			}
		}
	}
	return true;
}
Beispiel #15
0
int local_optimization(int n, int edge[][SIZE+1])
{
	int i, j, k;
	int loop			=	0;
	int	improved		=	1;
	int	modify			=	0;
	int cost, num;
	int idx				=	-1;
	unsigned long seed	=	get_nano_seconds();
	srand(seed);

	Chromosome *tmp;
	init_chromosome(&tmp, edge);

	for (i=0; i<=SIZE; i++)
		tmp->ch[i] = offsprings[n]->ch[i];

	for (num=0; num<HUBS; num++)
	{

		int r				=	rand() % N + 1;
		int neighbors[SIZE+1];
		int n_count			=	0;

		for (i=1; i<= SIZE; i++)
		{
			if (edge[r][i] != 0)
				neighbors[++n_count] = i;
		}
		neighbors[0] = r;

		while (improved)
		{
			improved = 0;
			cost = calc_cost(offsprings[n], edge);
			for (i=0; i<= n_count; i++)
			{
				tmp->ch[neighbors[i]] = (1 - (tmp->ch[neighbors[i]])) % 2;
				calc_cost(tmp, edge);

				if (tmp->cost > cost)
				{
					cost = tmp->cost;
					idx = i;
					improved = 1;
				}
			
				tmp->ch[neighbors[i]] = (1 - (tmp->ch[neighbors[i]])) % 2;
			}

			if (improved)
			{
				offsprings[n]->ch[neighbors[idx]] = (1 - (offsprings[n]->ch[neighbors[idx]])) % 2;
				tmp->ch[neighbors[idx]] = (1 - (tmp->ch[neighbors[idx]])) % 2;
			}
		}
	}

	free_chromosome(tmp);

	return 1;
}
Beispiel #16
0
ERL_NIF_TERM pathfind(ErlNifEnv *env, int argc, ERL_NIF_TERM argv[]) {
    /*debug("----------------------------\n");*/

    int id, x0, y0, x1, y1;

    ERL_NIF_TERM eid, from, to, head, tail;

    eid = argv[0];
    from = argv[1];
    to = argv[2];

    // Get the map ID
    enif_get_int(env, eid, &id);

    // Get the From X, Y
    enif_get_list_cell(env, from, &head, &tail);
    enif_get_int(env, head, &x0);
    enif_get_int(env, tail, &y0);

    // Get the To X, Y
    enif_get_list_cell(env, to, &head, &tail);
    enif_get_int(env, head, &x1);
    enif_get_int(env, tail, &y1);

    struct map_data map = maps[id];
    struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH];

    int heap[151];
    int rp, xs, ys;

    ERL_NIF_TERM *path;
    ERL_NIF_TERM *step;

    register int
    i = 0,
    j = 0,
    len,
    x = x0,
    y = y0,
    dx = ((dx = x1 - x0) ? ((dx < 0) ? -1 : 1) : 0),
    dy = ((dy = y1 - y0) ? ((dy < 0) ? -1 : 1) : 0);

    /* printmap(map); */

    /* debug("Pathfinding.\n"); */
    /* debug("\tMap: %d (%d x %d)\n", id, map.width, map.height); */
    /* debug("\tFrom: (%d, %d)\n", x0, y0); */
    /* debug("\tTo: (%d, %d)\n", x1, y1); */
    /* debug("\tFirst step: %d\n", at(map, x + dx, y + dy)); */

    step = (ERL_NIF_TERM *)malloc(3 * sizeof(ERL_NIF_TERM));
    path = (ERL_NIF_TERM *)malloc(MAX_WALKPATH * sizeof(ERL_NIF_TERM));

    for (i = 0;
            i < MAX_WALKPATH &&
            (x != x1 || y != y1) &&
            at(map, x + dx, y + dy) == 0;
            i++) {
        x += dx;
        y += dy;

        /* debug("OK: (%d, %d)\n", x, y); */

        step[0] = enif_make_int(env, x);
        step[1] = enif_make_int(env, y);
        step[2] = enif_make_int(env, walk_choices[-dy + 1][dx + 1]);

        path[i] = enif_make_tuple(env, 3, step[0], step[1], step[2]);

        if (x == x1)
            dx = 0;
        if (y == y1)
            dy = 0;

        /* debug("Next cell? %d (Done: %d)\n", at(map, x + dx, y + dy), dx == 0 && dy == 0); */
    }

    // Simple pathfinding was successful
    if (x == x1 && y == y1)
        return finish(env, path, step, i);

    memset(tp, 0, sizeof(tp));

    i = calc_index(x0,y0);
    tp[i].x = x0;
    tp[i].y = y0;
    tp[i].dist = 0;
    tp[i].before = 0;
    tp[i].cost = calc_cost(&tp[i], x1, y1);
    tp[i].flag = 0;
    heap[0] = 0;
    push_heap_path(heap, tp, calc_index(x0,y0));
    xs = map.width - 1; // あらかじめ1減算しておく
    ys = map.height - 1;


    while (1) {
        int e = 0,
            f = 0,
            dist,
            cost,
            dc[4] = {0, 0, 0, 0};

        if(heap[0] == 0)
            return finish(env, path, step, 0);

        rp = pop_heap_path(heap,tp);
        x = tp[rp].x;
        y = tp[rp].y;
        dist = tp[rp].dist + 10;
        cost = tp[rp].cost;

        if (x == x1 && y == y1)
            break;

        // dc[0] : y++ の時のコスト増分
        // dc[1] : x-- の時のコスト増分
        // dc[2] : y-- の時のコスト増分
        // dc[3] : x++ の時のコスト増分

        if (y < ys && !at(map, x, y + 1)) {
            f |= 1;
            dc[0] = (y >= y1 ? 20 : 0);
            e += add_path(heap, tp, x, y + 1, dist, rp, cost + dc[0]); // (x,   y+1)
        }
        if (x > 0 && !at(map, x - 1, y)) {
            f |= 2;
            dc[1] = (x <= x1 ? 20 : 0);
            e += add_path(heap, tp, x - 1, y, dist, rp, cost + dc[1]); // (x-1, y  )
        }
        if (y > 0 && !at(map, x, y - 1)) {
            f |= 4;
            dc[2] = (y <= y1 ? 20 : 0);
            e += add_path(heap, tp, x, y - 1, dist, rp, cost + dc[2]); // (x  , y-1)
        }
        if (x < xs && !at(map, x + 1, y)) {
            f |= 8;
            dc[3] = (x >= x1 ? 20 : 0);
            e += add_path(heap, tp, x + 1, y, dist, rp, cost + dc[3]); // (x+1, y  )
        }

        if((f & (2+1)) == (2+1) && !at(map, x - 1, y + 1))
            e += add_path(heap, tp, x - 1, y + 1, dist + 4, rp, cost + dc[1] + dc[0] - 6); // (x-1, y+1)

        if((f & (2+4)) == (2+4) && !at(map, x - 1, y - 1))
            e += add_path(heap, tp, x - 1, y - 1, dist + 4, rp, cost + dc[1] + dc[2] - 6); // (x-1, y-1)

        if((f & (8+4)) == (8+4) && !at(map, x + 1, y - 1))
            e += add_path(heap, tp, x + 1, y - 1, dist + 4, rp, cost + dc[3] + dc[2] - 6); // (x+1, y-1)

        if((f & (8+1)) == (8+1) && !at(map, x + 1, y + 1))
            e += add_path(heap, tp, x + 1, y + 1, dist + 4, rp, cost + dc[3] + dc[0] - 6); // (x+1, y+1)

        tp[rp].flag = 1;

        if (e || heap[0] >= 150 - 5)
            return finish(env, path, step, 0);
    }

    for (len = 0, i = rp; len < 100 && i != calc_index(x0, y0); i = tp[i].before, len++);

    if (len == 100 || len >= MAX_WALKPATH)
        return finish(env, path, step, 0);

    for (i = rp, j = len - 1; j >= 0; i = tp[i].before, j--) {
        int dx = tp[i].x - tp[tp[i].before].x;
        int dy = tp[i].y - tp[tp[i].before].y;
        /* int dir; */

        step[0] = enif_make_int(env, tp[i].x);
        step[1] = enif_make_int(env, tp[i].y);

        /* if (dx == 0) */
        /*     dir = (dy > 0 ? 0 : 4); */
        /* else if (dx > 0) */
        /*     dir = (dy == 0 ? 6 : (dy < 0 ? 5 : 7)); */
        /* else */
        /*     dir = (dy == 0 ? 2 : (dy > 0 ? 1 : 3)); */

        step[2] = enif_make_int(env, walk_choices[-dy + 1][dx + 1]);

        path[j] = enif_make_tuple(env, 3, step[0], step[1], step[2]);
    }

    return finish(env, path, step, len);
}
Beispiel #17
0
/*==========================================
 * path探索 (x0,y0)->(x1,y1)
 *------------------------------------------
 */
int path_search(struct walkpath_data *wpd,int m,int x0,int y0,int x1,int y1,int flag)
{
	int heap[MAX_HEAP+1];
	struct tmp_path tp[MAX_WALKPATH*MAX_WALKPATH];
	int i,rp,x,y;
	struct map_data *md;
	int dx,dy;

	if(!map[m].gat)
		return -1;
	md=&map[m];
	if(x1<0 || x1>=md->xs || y1<0 || y1>=md->ys || (i=read_gatp(md,x1,y1))==1 || i==5)
		return -1;

	// easy
	dx = (x1-x0<0) ? -1 : 1;
	dy = (y1-y0<0) ? -1 : 1;
	for(x=x0,y=y0,i=0;x!=x1 || y!=y1;){
		if(i>=sizeof(wpd->path))
			return -1;
		if(x!=x1 && y!=y1){
			if(!can_move(md,x,y,x+dx,y+dy,flag))
				break;
			x+=dx;
			y+=dy;
			wpd->path[i++]=(dx<0) ? ((dy>0)? 1 : 3) : ((dy<0)? 5 : 7);
		} else if(x!=x1){
			if(!can_move(md,x,y,x+dx,y   ,flag))
				break;
			x+=dx;
			wpd->path[i++]=(dx<0) ? 2 : 6;
		} else { // y!=y1
			if(!can_move(md,x,y,x   ,y+dy,flag))
				break;
			y+=dy;
			wpd->path[i++]=(dy>0) ? 0 : 4;
		}
		if(x==x1 && y==y1){
			wpd->path_len=i;
			wpd->path_pos=0;
			wpd->path_half=0;
			return 0;
		}
	}
	if(flag&1)
		return -1;

	memset(tp,0,sizeof(tp));

	i=calc_index(x0,y0);
	tp[i].x=x0;
	tp[i].y=y0;
	tp[i].dist=0;
	tp[i].dir=0;
	tp[i].before=0;
	tp[i].cost=calc_cost(&tp[i],x1,y1);
	tp[i].flag=0;
	heap[0]=0;
	push_heap_path(heap,tp,calc_index(x0,y0));
	while(1){
		int e=0,fromdir;

		if(heap[0]==0)
			return -1;
		rp=pop_heap_path(heap,tp);
		x=tp[rp].x;
		y=tp[rp].y;
		if(x==x1 && y==y1){
			int len,j;

			for(len=0,i=rp;len<100 && i!=calc_index(x0,y0);i=tp[i].before,len++);
			if(len==100 || len>=sizeof(wpd->path))
				return -1;
			wpd->path_len=len;
			wpd->path_pos=0;
			wpd->path_half=0;
			for(i=rp,j=len-1;j>=0;i=tp[i].before,j--)
				wpd->path[j]=tp[i].dir;

			return 0;
		}
		fromdir=tp[rp].dir;
		if(can_move(md,x,y,x+1,y-1,flag))
			e+=add_path(heap,tp,x+1,y-1,tp[rp].dist+14,5,rp,x1,y1);
		if(can_move(md,x,y,x+1,y  ,flag))
			e+=add_path(heap,tp,x+1,y  ,tp[rp].dist+10,6,rp,x1,y1);
		if(can_move(md,x,y,x+1,y+1,flag))
			e+=add_path(heap,tp,x+1,y+1,tp[rp].dist+14,7,rp,x1,y1);
		if(can_move(md,x,y,x  ,y+1,flag))
			e+=add_path(heap,tp,x  ,y+1,tp[rp].dist+10,0,rp,x1,y1);
		if(can_move(md,x,y,x-1,y+1,flag))
			e+=add_path(heap,tp,x-1,y+1,tp[rp].dist+14,1,rp,x1,y1);
		if(can_move(md,x,y,x-1,y  ,flag))
			e+=add_path(heap,tp,x-1,y  ,tp[rp].dist+10,2,rp,x1,y1);
		if(can_move(md,x,y,x-1,y-1,flag))
			e+=add_path(heap,tp,x-1,y-1,tp[rp].dist+14,3,rp,x1,y1);
		if(can_move(md,x,y,x  ,y-1,flag))
			e+=add_path(heap,tp,x  ,y-1,tp[rp].dist+10,4,rp,x1,y1);
		tp[rp].flag=1;
		if(e || heap[0]>=MAX_HEAP-5)
			return -1;
	}
	return -1;
}
Beispiel #18
0
/*==========================================
 * path探索 (x0,y0)->(x1,y1)
 *------------------------------------------
 */
int path_search_real(struct walkpath_data *wpd,int m,int x0,int y0,int x1,int y1,int easy,cell_t flag)
{
	int x, y, i = 0;
	int dx, dy;
	struct map_data *md = &map[m];

	if(!map[m].gat)
		return -1;

	// path_search2() の場合map_getcellp() の返り値は常に0
	if(x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys || map_getcellp(md,x0,y0,flag))
		return -1;
	if(x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || map_getcellp(md,x1,y1,flag))
		return -1;

	// easy
	// この内部では、0 <= x+dx < sx, 0 <= y+dy < sy は保証されている
	dx = (x1 - x0 < 0) ? -1 : 1;
	dy = (y1 - y0 < 0) ? -1 : 1;

	x = x0;
	y = y0;
	while(x != x1 || y != y1) {
		if(i >= MAX_WALKPATH)
			return -1;
		if(x != x1 && y != y1) {
			if(map_getcellp(md,x+dx,y   ,flag))
				break;
			if(map_getcellp(md,x   ,y+dy,flag))
				break;
			if(map_getcellp(md,x+dx,y+dy,flag))
				break;
			x += dx;
			y += dy;
			if(wpd)
				wpd->path[i++] = walk_choice[-dy+1][dx+1];
		} else if(x != x1) {
			if(map_getcellp(md,x+dx,y,flag))
				break;
			x += dx;
			if(wpd)
				wpd->path[i++] = walk_choice[1][dx+1];
		} else { // y!=y1
			if(map_getcellp(md,x,y+dy,flag))
				break;
			y += dy;
			if(wpd)
				wpd->path[i++] = walk_choice[-dy+1][1];
		}
		if(x == x1 && y == y1) {
			if(wpd) {
				wpd->path_len = i;
				wpd->path_pos = 0;
			}
			return 0;
		}
	}

	if(!easy) {
		int xs, ys, rp;
		int len, j;
		int heap[MAX_HEAP+1];
		struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH];

		memset(tp, 0, sizeof(tp));

		i            = calc_index(x0,y0);
		tp[i].x      = x0;
		tp[i].y      = y0;
		tp[i].dist   = 0;
		tp[i].before = 0;
		tp[i].cost   = calc_cost(&tp[i],x1,y1);
		tp[i].flag   = 0;
		heap[0]      = 0;
		push_heap_path(heap,tp,calc_index(x0,y0));

		// あらかじめ1減算しておく
		xs = md->xs - 1;
		ys = md->ys - 1;

		while(1) {
			int e = 0, f = 0;
			int dist, cost;
			int dc[4] = { 0, 0, 0, 0 };

			if(heap[0] == 0)
				return -1;

			rp = pop_heap_path(heap,tp);
			x  = tp[rp].x;
			y  = tp[rp].y;
			if(x == x1 && y == y1)
				break;

			dist = tp[rp].dist + 10;
			cost = tp[rp].cost;

			// dc[0] : y++ の時のコスト増分
			// dc[1] : x-- の時のコスト増分
			// dc[2] : y-- の時のコスト増分
			// dc[3] : x++ の時のコスト増分

			if(y < ys && !map_getcellp(md,x  ,y+1,flag)) {
				f |= 1;
				dc[0] = (y >= y1 ? 20 : 0);
				e += add_path(heap,tp,x  ,y+1,dist,rp,cost+dc[0]);	// (x,   y+1)
			}
			if(x > 0  && !map_getcellp(md,x-1,y  ,flag)) {
				f |= 2;
				dc[1] = (x <= x1 ? 20 : 0);
				e += add_path(heap,tp,x-1,y  ,dist,rp,cost+dc[1]);	// (x-1, y  )
			}
			if(y > 0  && !map_getcellp(md,x  ,y-1,flag)) {
				f |= 4;
				dc[2] = (y <= y1 ? 20 : 0);
				e += add_path(heap,tp,x  ,y-1,dist,rp,cost+dc[2]);	// (x  , y-1)
			}
			if(x < xs && !map_getcellp(md,x+1,y  ,flag)) {
				f |= 8;
				dc[3] = (x >= x1 ? 20 : 0);
				e += add_path(heap,tp,x+1,y  ,dist,rp,cost+dc[3]);	// (x+1, y  )
			}
			if( (f & (2+1)) == (2+1) && !map_getcellp(md,x-1,y+1,flag))
				e += add_path(heap,tp,x-1,y+1,dist+4,rp,cost+dc[1]+dc[0]-6);	// (x-1, y+1)
			if( (f & (2+4)) == (2+4) && !map_getcellp(md,x-1,y-1,flag))
				e += add_path(heap,tp,x-1,y-1,dist+4,rp,cost+dc[1]+dc[2]-6);	// (x-1, y-1)
			if( (f & (8+4)) == (8+4) && !map_getcellp(md,x+1,y-1,flag))
				e += add_path(heap,tp,x+1,y-1,dist+4,rp,cost+dc[3]+dc[2]-6);	// (x+1, y-1)
			if( (f & (8+1)) == (8+1) && !map_getcellp(md,x+1,y+1,flag))
				e += add_path(heap,tp,x+1,y+1,dist+4,rp,cost+dc[3]+dc[0]-6);	// (x+1, y+1)

			tp[rp].flag = 1;
			if(e || heap[0] >= MAX_HEAP - 5)
				return -1;
		}

		for(len = 0, i = rp; len < MAX_WALKPATH && i != calc_index(x0,y0); i = tp[i].before, len++);
		if(len >= MAX_WALKPATH)
			return -1;

		if(wpd == NULL)
			return 0;

		wpd->path_len = len;
		wpd->path_pos = 0;
		for(i = rp, j = len-1; j >= 0; i = tp[i].before, j--) {
			int tx = tp[i].x - tp[tp[i].before].x;
			int ty = tp[i].y - tp[tp[i].before].y;
			wpd->path[j] = walk_choice[-ty+1][tx+1];
		}
#if 0
		// test
		{
			x = x0; y = y0;
			for(i = 0; i < wpd->path_len; i++) {
				x += dirx[ wpd->path[i] ];
				y += diry[ wpd->path[i] ];
				if( map_getcellp(md,x,y,flag) ) {
					printf("path_search_real: cannot move(%d, %d)\n", x, y);
					return -1;
				}
			}
			if( x != x1 || y != y1 ) {
				printf("path_search_real: dest position is wrong. ok:(%d, %d) ng:(%d,%d)\n", x1, y1, x, y);
				return -1;
			}
		}
#endif
		return 0;
	}

	return -1;
}