/* make md run through the cave */ static void mdrush(struct monst *md, bool away) { int uroom = inroom(u.ux, u.uy); if (uroom >= 0) { int tmp = rooms[uroom].fdoor; int cnt = rooms[uroom].doorct; int fx = u.ux, fy = u.uy; while (cnt--) { if (dist(fx, fy) < dist(doors[tmp].x, doors[tmp].y)) { fx = doors[tmp].x; fy = doors[tmp].y; } tmp++; } tmp_at(-1, md->data->mlet); /* open call */ if (away) { /* interchange origin and destination */ unpmon(md); tmp = fx; fx = md->mx; md->mx = tmp; tmp = fy; fy = md->my; md->my = tmp; } while (fx != md->mx || fy != md->my) { int dx, dy, nfx = fx, nfy = fy, d1, d2; tmp_at(fx, fy); d1 = DIST(fx, fy, md->mx, md->my); for (dx = -1; dx <= 1; dx++) for (dy = -1; dy <= 1; dy++) if (dx || dy) { d2 = DIST(fx + dx, fy + dy, md->mx, md->my); if (d2 < d1) { d1 = d2; nfx = fx + dx; nfy = fy + dy; } } if (nfx != fx || nfy != fy) { fx = nfx; fy = nfy; } else { if (!away) { md->mx = fx; md->my = fy; } break; } } tmp_at(-1, -1); /* close call */ } if (!away) pmon(md); }
/* ddx, ddy, range: direction and range * sym: symbol displayed on path * fhitm, fhito: fns called when mon/obj hit * obj: 2nd arg to fhitm/fhito */ struct monst * bhit(int ddx, int ddy, int range, char sym, void (*fhitm)(struct monst *, struct obj *), bool (*fhito)(struct obj *, struct obj *), struct obj *obj) { struct monst *mtmp; struct obj *otmp; int typ; bhitpos.x = u.ux; bhitpos.y = u.uy; if (sym) /* open call */ tmp_at(-1, sym); while (range-- > 0) { bhitpos.x += ddx; bhitpos.y += ddy; typ = levl[bhitpos.x][bhitpos.y].typ; if ((mtmp = m_at(bhitpos.x, bhitpos.y))) { if (sym) { tmp_at(-1, -1); /* close call */ return (mtmp); } (*fhitm)(mtmp, obj); range -= 3; } if (fhito && (otmp = o_at(bhitpos.x, bhitpos.y))) { if ((*fhito)(otmp, obj)) range--; } if (!ZAP_POS(typ)) { bhitpos.x -= ddx; bhitpos.y -= ddy; break; } if (sym) tmp_at(bhitpos.x, bhitpos.y); } /* leave last symbol unless in a pool */ if (sym) tmp_at(-1, (levl[bhitpos.x][bhitpos.y].typ == POOL) ? -1 : 0); return (0); }
struct monst * boomhit(int dx, int dy) { int i, ct; struct monst *mtmp; char sym = ')'; bhitpos.x = u.ux; bhitpos.y = u.uy; for (i = 0; i < 8; i++) if (xdir[i] == dx && ydir[i] == dy) break; tmp_at(-1, sym); /* open call */ for (ct = 0; ct < 10; ct++) { if (i == 8) i = 0; sym = ')' + '(' - sym; tmp_at(-2, sym); /* change let call */ dx = xdir[i]; dy = ydir[i]; bhitpos.x += dx; bhitpos.y += dy; if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != NULL) { tmp_at(-1, -1); return (mtmp); } if (!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)) { bhitpos.x -= dx; bhitpos.y -= dy; break; } if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */ if (rn2(20) >= 10 + u.ulevel) { /* we hit ourselves */ thitu(10, rnd(10), "boomerang"); break; } else { /* we catch it */ tmp_at(-1, -1); pline("Skillfully, you catch the boomerang."); return (&youmonst); } } tmp_at(bhitpos.x, bhitpos.y); if (ct % 5 != 0) i++; } tmp_at(-1, -1); /* do not leave last symbol */ return (0); }
void freedynamicdata(void) { int i; struct level *lev; if (!objects) return; /* no cleanup necessary */ unload_qtlist(); free_invbuf(); /* let_to_name (invent.c) */ free_youbuf(); /* You_buf,&c (pline.c) */ tmp_at(DISP_FREEMEM, 0); /* temporary display effects */ # define free_animals() mon_animal_list(FALSE) for (i = 0; i < MAXLINFO; i++) { lev = levels[i]; levels[i] = NULL; if (!lev) continue; /* level-specific data */ dmonsfree(lev); /* release dead monsters */ free_timers(lev); free_light_sources(lev); free_monchn(lev->monlist); free_worm(lev); /* release worm segment information */ freetrapchn(lev->lev_traps); free_objchn(lev->objlist); free_objchn(lev->buriedobjlist); free_objchn(lev->billobjs); free_engravings(lev); freedamage(lev); free(lev); } /* game-state data */ free_objchn(invent); free_objchn(migrating_objs); free_monchn(migrating_mons); free_monchn(mydogs); /* ascension or dungeon escape */ free_animals(); free_oracles(); freefruitchn(); freenames(); free_waterlevel(); free_dungeon(); free_history(); if (iflags.ap_rules) { free(iflags.ap_rules->rules); iflags.ap_rules->rules = NULL; free(iflags.ap_rules); } iflags.ap_rules = NULL; free(artilist); free(objects); objects = NULL; artilist = NULL; if (active_birth_options) free_optlist(active_birth_options); active_birth_options = NULL; return; }