/*========================================== * (x,y)が移動不可能地帯かどうか * flag 0x10000 遠距離攻撃判定 *------------------------------------------ */ static bool can_place(struct map_local *m, int x, int y) { nullpo_ret(m); return !bool(read_gatp(m, x, y) & MapCell::UNWALKABLE); }
/*========================================== * (x,y)が移動不可能地帯かどうか * flag 0x10000 遠距離攻撃判定 *------------------------------------------ */ static inline int can_place(struct map_data *m,int x,int y,int flag) { int c=read_gatp(m,x,y); if(c==1) return 0; if(!(flag&0x10000) && c==5) return 0; return 1; }
/*========================================== * 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; } }
/*========================================== * 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; }