📄 route.c
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include "sokoban.h"static int dirlist[] = { Up, Down, Left, Right, Up, Down, Left, Right, };static int ndir = 4;static Pointdir2point(int dir){ switch(dir) { case Up: return Pt(0, -1); case Down: return Pt(0, 1); case Left: return Pt(-1, 0); case Right: return Pt(1, 0); } return Pt(0,0);}intvalidpush(Point g, Step *s, Point *t){ int i; Point m; if (s == nil) return 0; m = dir2point(s->dir); // first test for Cargo next to us (in direction dir) if (s->count > 0) { g = addpt(g, m); if (!ptinrect(g, Rpt(Pt(0,0), level.max))) return 0; switch (level.board[g.x][g.y]) { case Wall: case Empty: case Goal: return 0; } } // then test for enough free space for us _and_ Cargo for (i=0; i < s->count; i++) { g = addpt(g, m); if (!ptinrect(g, Rpt(Pt(0,0), level.max))) return 0; switch (level.board[g.x][g.y]) { case Wall: case Cargo: case GoalCargo: return 0; } } if (t != nil) *t = g; return 1;}intisvalid(Point s, Route* r, int (*isallowed)(Point, Step*, Point*)){ Point m; Step *p; if (r == nil) return 0; m = s; for (p=r->step; p < r->step +r->nstep; p++) if (! isallowed(m, p, &m)) return 0; return 1;}static Walk*newwalk(void){ Walk *w; w = malloc(sizeof(Walk)); if (w->route == nil) sysfatal("cannot allocate walk"); memset(w, 0, sizeof(Walk)); return w;}static voidresetwalk(Walk *w){ Route **p; if (w == nil || w->route == nil) return; for (p=w->route; p < w->route + w->nroute; p++) freeroute(*p); w->nroute = 0;}static voidfreewalk(Walk *w){ if (w == nil) return; resetwalk(w); if(w->route) free(w->route); free(w);}static voidaddroute(Walk *w, Route *r){ if (w == nil || r == nil) return; if (w->beyond < w->nroute+1) { w->beyond = w->nroute+1; w->route = realloc(w->route, sizeof(Route*)*w->beyond); } if (w->route == nil) sysfatal("cannot allocate route in addroute"); w->route[w->nroute] = r; w->nroute++;}voidfreeroute(Route *r){ if (r == nil) return; if (r->step != nil) free(r->step); free(r);}Route*extend(Route *rr, int dir, int count, Point dest){ Route *r; r = malloc(sizeof(Route)); if (r == nil) sysfatal("cannot allocate route in extend"); memset(r, 0, sizeof(Route)); r->dest = dest; if (count > 0) { r->nstep = 1; if (rr != nil) r->nstep += rr->nstep; r->step = malloc(sizeof(Step)*r->nstep); if (r->step == nil) sysfatal("cannot allocate step in extend"); if (rr != nil) memmove(r->step, rr->step, sizeof(Step)*rr->nstep); r->step[r->nstep-1].dir = dir; r->step[r->nstep-1].count = count; } return r;}static Step*laststep(Route*r){ if (r != nil && r->nstep > 0) { return &r->step[r->nstep-1]; } return nil;}static int*startwithdirfromroute(Route *r, int* dl, int n){ Step *s; int *p; if (r == nil || dl == nil) return dl; s = laststep(r); if (s == nil || s->count == 0) return dl; for (p=dl; p < dl + n; p++) if (*p == s->dir) break; return p;}static Route*bfstrydir(Route *r, int dir, Visited *v){ Point m, p, n; if (r == nil) return nil; m = r->dest; p = dir2point(dir); n = addpt(m, p); if (ptinrect(n, Rpt(Pt(0,0), level.max)) && v->board[n.x][n.y] == 0) { v->board[n.x][n.y] = 1; switch (level.board[n.x][n.y]) { case Empty: case Goal: return extend(r, dir, 1, n); } } return nil;}static Route*bfs(Point src, Point dst, Visited *v){ Walk *cur, *new, *tmp; Route *r, **p; int progress, *dirs, *dirp; Point n; if (v == nil) return nil; cur = newwalk(); new = newwalk(); v->board[src.x][src.y] = 1; r = extend(nil, 0, 0, src); if (eqpt(src, dst)) { freewalk(cur); freewalk(new); return r; } addroute(cur, r); progress = 1; while (progress) { progress = 0; for (p=cur->route; p < cur->route + cur->nroute; p++) { dirs = startwithdirfromroute(*p, dirlist, ndir); for (dirp=dirs; dirp < dirs + ndir; dirp++) { r = bfstrydir(*p, *dirp, v); if (r != nil) { progress = 1; n = r->dest; if (eqpt(n, dst)) { freewalk(cur); freewalk(new); return(r); } addroute(new, r); } } } resetwalk(cur); tmp = cur; cur = new; new = tmp; } freewalk(cur); freewalk(new); return nil;}Route*findroute(Point src, Point dst){ Visited v; Route* r; memset(&v, 0, sizeof(Visited)); r = bfs(src, dst, &v); return r;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -