123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- #include <u.h>
- #include <libc.h>
- #include <draw.h>
- #include "sokoban.h"
- static int trydir(int, Point, Point, Route*, Visited*);
- static int dofind(Point, Point, Route*, Visited*);
- static Point
- dir2point(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);
- }
- Route*
- newroute(void)
- {
- Route *r = malloc(sizeof(Route));
- memset(r, 0, sizeof(Route));
- return r;
- }
- void
- freeroute(Route *r)
- {
- if (r->step != nil) {
- free(r->step);
- memset(r, 0, sizeof(Route));
- }
- free(r);
- }
- void
- reverseroute(Route *r)
- {
- int i;
- Step tmp;
- for (i=1; i< r->nstep; i++) {
- tmp = r->step[i];
- r->step[i] = r->step[i-1];
- r->step[i-1] = tmp;
- }
- }
- void
- pushstep(Route *r, int dir, int count)
- {
- if (r->beyond < r->nstep+1) {
- r->beyond = r->nstep+1;
- r->step = realloc(r->step, sizeof(Step)*r->beyond);
- }
- if (r->step == nil)
- exits("pushstep out of memory");
- r->step[r->nstep].dir = dir;
- r->step[r->nstep].count = count;
- r->nstep++;
- }
- void
- popstep(Route*r)
- {
- if (r->nstep > 0) {
- r->nstep--;
- r->step[r->nstep].dir = 0;
- r->step[r->nstep].count = 0;
- }
- }
- int
- validpush(Point g, Step s, Point *t)
- {
- int i;
- Point 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;
- }
- int
- validwalk(Point g, Step s, Point *t)
- {
- int i;
- Point m = dir2point(s.dir);
- 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;
- }
- int
- isvalid(Point s, Route* r, int (*isallowed)(Point, Step, Point*))
- {
- int i;
- Point m = s;
- for (i=0; i< r->nstep; i++)
- if (! isallowed(m, r->step[i], &m))
- return 0;
- return 1;
- }
- static int
- trydir(int dir, Point m, Point d, Route *r, Visited *v)
- {
- Point p = dir2point(dir);
- Point 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:
- pushstep(r, dir, 1);
- if (dofind(n, d, r, v))
- return 1;
- else
- popstep(r);
- }
- }
- return 0;
- }
- static int
- dofind(Point m, Point d, Route *r, Visited *v)
- {
- if (eqpt(m, d))
- return 1;
- v->board[m.x][m.y] = 1;
- return trydir(Left, m, d, r, v) ||
- trydir(Up, m, d, r, v) ||
- trydir(Right, m, d, r, v) ||
- trydir(Down, m, d, r, v);
- }
- static int
- dobfs(Point m, Point d, Route *r, Visited *v)
- {
- if (eqpt(m, d))
- return 1;
- v->board[m.x][m.y] = 1;
- return trydir(Left, m, d, r, v) ||
- trydir(Up, m, d, r, v) ||
- trydir(Right, m, d, r, v) ||
- trydir(Down, m, d, r, v);
- }
- int
- findwalk(Point src, Point dst, Route *r)
- {
- Visited* v;
- int found;
- v = malloc(sizeof(Visited));
- memset(v, 0, sizeof(Visited));
- found = dofind(src, dst, r, v);
- free(v);
-
- return found;
- }
- void
- applyroute(Route *r)
- {
- int j, i;
-
- for (i=0; i< r->nstep; i++) {
- j = r->step[i].count;
- while (j > 0) {
- move(r->step[i].dir);
- if (animate) {
- drawscreen();
- sleep(200);
- }
- j--;
- }
- }
- }
|