ref: f2a1c2c13ea8f9e0ece5500dd7783754362c3099
dir: /map.c/
#include <u.h> #include <libc.h> #include <draw.h> #include "dat.h" #include "fns.h" Tile *tilemap; int tilemapwidth, tilemapheight; Node *map; int mapwidth, mapheight; void setpos(Mobj *mo, Point p) { assert(p.x < mapwidth && p.y < mapheight); mo->Point = p; mo->sub.x = mo->x << Subshift; mo->sub.y = mo->y << Subshift; } void setsubpos(Mobj *mo, Point p) { mo->sub = p; mo->x = p.x >> Subshift; mo->y = p.y >> Subshift; } void snaptomapgrid(Mobj *mo) { markmobj(mo, 0); setpos(mo, mo->Point); markmobj(mo, 1); } int isnextto(Mobj *mo, Mobj *tgt) { Rectangle r1, r2; if(tgt == nil) return 0; r1.min = mo->Point; r1.max = addpt(r1.min, Pt(mo->o->w, mo->o->h)); r2.min = tgt->Point; r2.max = addpt(r2.min, Pt(tgt->o->w, tgt->o->h)); return rectXrect(insetrect(r1, -1), r2); } Mobj * unitat(Point p) { Point mp; Rectangle r, mr; Tile *t; Mobjl *ml; Mobj *mo; mp = divpt(p, Node2Tile); r = Rpt(subpt(mp, Pt(4, 4)), mp); for(; mp.y>=r.min.y; mp.y--){ mp.x = r.max.x; t = tilemap + mp.y * tilemapwidth + mp.x; for(; mp.x>=r.min.x; mp.x--, t--) for(ml=t->ml.l; ml!=&t->ml; ml=ml->l){ mo = ml->mo; mr = Rect(mo->x, mo->y, mo->x+mo->o->w, mo->y+mo->o->h); if(ptinrect(p, mr)) return mo; } } return nil; } Tile * tilepos(Point p) { p = divpt(p, Node2Tile); return tilemap + p.y * tilemapwidth + p.x; } void linktomap(Mobj *mo) { Tile *t; t = tilepos(mo->Point); mo->mapl = linkmobj(mo->o->f & Fair ? t->ml.lp : &t->ml, mo, mo->mapl); } static void updatemap(Mobj *mo) { Mobj *bmo; if(isblocked(mo->Point, mo->o)){ bmo = unitat(mo->Point); sysfatal("markmobj: attempt to place %s at %P, non-free block having %s at %P", mo->o->name, mo->Point, bmo->o->name, bmo->Point); } linktomap(mo); markmobj(mo, 1); } static int findspawn(Point *pp, int ofs, Obj *o, Obj *spawn) { Rectangle r; Point p; p = *pp; r.min.x = p.x - (ofs+1) * o->w; r.min.y = p.y - (ofs+1) * o->h; r.max.x = p.x + spawn->w + ofs * o->w; r.max.y = p.y + spawn->h + ofs * o->h; for(p.x=r.min.x+o->w, p.y=r.max.y; p.x<r.max.x; p.x++) if(!isblocked(p, o)) goto found; for(p.x=r.max.x, p.y=r.max.y; p.y>r.min.y; p.y--) if(!isblocked(p, o)) goto found; for(p.x=r.max.x, p.y=r.min.y; p.x>r.min.x; p.x--) if(!isblocked(p, o)) goto found; for(p.x=r.min.x, p.y=r.min.y; p.y<=r.max.y; p.y++) if(!isblocked(p, o)) goto found; return -1; found: *pp = p; return 0; } static int getspawn(Point *pp, Obj *o) { int n; Point p; Tile *t; Mobjl *ml; Mobj *mo; Obj **os; p = *pp; if(o->f & (Fbuild|Fimmutable)){ if((p.x & Node2Tile - 1) || (p.y & Node2Tile - 1)){ werrstr("getspawn: unaligned building placement %P", p); return -1; } if(isblocked(p, o)){ werrstr("getspawn: building placement at %P blocked", p); return -1; } }else{ t = tilepos(p); for(mo=nil, ml=t->ml.l; ml!=&t->ml; ml=ml->l){ mo = ml->mo; for(os=mo->o->spawn, n=mo->o->nspawn; n>0; n--, os++) if(*os == o) break; if(n > 0) break; } if(ml == &t->ml){ werrstr("getspawn: no spawn object at %P", p); return -1; } for(n=0; n<3; n++) if(findspawn(&p, n, o, mo->o) >= 0) break; if(n == 3){ werrstr("getspawn: no free spot for %s at %P", o->name, p); return -1; } } *pp = p; return 0; } Mobj * mapspawn(Obj *o, Point p) { Mobj *mo; if(getspawn(&p, o) < 0) return nil; mo = emalloc(sizeof *mo); mo->uuid = lrand(); setpos(mo, p); mo->o = o; newvec(&mo->path.moves, 32, sizeof(Point)); updatemap(mo); return mo; } void initmap(void) { mapwidth = tilemapwidth * Node2Tile; mapheight = tilemapheight * Node2Tile; map = emalloc(mapwidth * mapheight * sizeof *map); initbmap(); }