static long botl_score(void) { long umoney = money_cnt(invent) + hidden_gold(); return calc_score(DIED, FALSE, umoney); }
static void fill_topten_entry(struct toptenentry *newtt, int how) { int uid = getuid(); memset(newtt, 0, sizeof (struct toptenentry)); /* deepest_lev_reached() is in terms of depth(), and reporting the deepest level reached in the dungeon death occurred in doesn't seem right, so we have to report the death level in depth() terms as well (which also seems reasonable since that's all the player sees on the screen anyway) */ newtt->ver_major = VERSION_MAJOR; newtt->ver_minor = VERSION_MINOR; newtt->patchlevel = PATCHLEVEL; newtt->points = u.urexp > -1 ? /* u.urexp stores score once invent is invalid */ u.urexp : calc_score(how, FALSE, money_cnt(invent) + hidden_gold()); newtt->deathdnum = u.uz.dnum; newtt->deathlev = depth(&u.uz); newtt->maxlvl = deepest_lev_reached(TRUE); newtt->hp = u.uhp; newtt->maxhp = u.uhpmax; newtt->deaths = u.umortality; newtt->uid = uid; newtt->moves = moves; newtt->how = how; strncpy(newtt->plrole, urole.filecode, ROLESZ); newtt->plrole[ROLESZ] = '\0'; strncpy(newtt->plrace, urace.filecode, ROLESZ); newtt->plrace[ROLESZ] = '\0'; strncpy(newtt->plgend, genders[flags.female].filecode, ROLESZ); newtt->plgend[ROLESZ] = '\0'; strncpy(newtt->plalign, aligns[1 - u.ualign.type].filecode, ROLESZ); newtt->plalign[ROLESZ] = '\0'; strncpy(newtt->name, plname, NAMSZ); newtt->name[NAMSZ] = '\0'; newtt->death[0] = '\0'; switch (killer_format) { default: impossible("bad killer format?"); case KILLED_BY_AN: strcat(newtt->death, killed_by_prefix[how]); strncat(newtt->death, an(killer), DTHSZ - strlen(newtt->death)); break; case KILLED_BY: strcat(newtt->death, killed_by_prefix[how]); strncat(newtt->death, killer, DTHSZ - strlen(newtt->death)); break; case NO_KILLER_PREFIX: strncat(newtt->death, killer, DTHSZ); break; } newtt->birthdate = yyyymmdd(u.ubirthday); newtt->deathdate = yyyymmdd((time_t) 0L); time(&deathtime_internal); }
/* look for gold, on the floor or in monsters' possession */ int gold_detect(struct obj *sobj, boolean *scr_known) { struct obj *obj; struct monst *mtmp; int uw = u.uinwater; struct obj *temp; boolean stale; *scr_known = stale = clear_stale_map(COIN_CLASS, sobj->blessed ? GOLD : 0); /* look for gold carried by monsters (might be in a container) */ for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; /* probably not needed in this case but... */ if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { *scr_known = TRUE; goto outgoldmap; /* skip further searching */ } else for (obj = mtmp->minvent; obj; obj = obj->nobj) if (sobj->blessed && o_material(obj, GOLD)) { *scr_known = TRUE; goto outgoldmap; } else if (o_in(obj, COIN_CLASS)) { *scr_known = TRUE; goto outgoldmap; /* skip further searching */ } } /* look for gold objects */ for (obj = level->objlist; obj; obj = obj->nobj) { if (sobj->blessed && o_material(obj, GOLD)) { *scr_known = TRUE; if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap; } else if (o_in(obj, COIN_CLASS)) { *scr_known = TRUE; if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap; } } if (!*scr_known) { /* no gold found on floor or monster's inventory. adjust message if you have gold in your inventory */ char buf[BUFSZ]; if (youmonst.data == &mons[PM_GOLD_GOLEM]) { sprintf(buf, "You feel like a million %s!", currency(2L)); } else if (hidden_gold() || money_cnt(invent)) strcpy(buf, "You feel worried about your future financial situation."); else strcpy(buf, "You feel materially poor."); strange_feeling(sobj, buf); return 1; } /* only under me - no separate display required */ if (stale) doredraw(); pline("You notice some gold between your %s.", makeplural(body_part(FOOT))); return 0; outgoldmap: cls(); u.uinwater = 0; /* Discover gold locations. */ for (obj = level->objlist; obj; obj = obj->nobj) { if (sobj->blessed && (temp = o_material(obj, GOLD))) { if (temp != obj) { temp->ox = obj->ox; temp->oy = obj->oy; } map_object(temp,1); } else if ((temp = o_in(obj, COIN_CLASS))) { if (temp != obj) { temp->ox = obj->ox; temp->oy = obj->oy; } map_object(temp,1); } } for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; /* probably overkill here */ if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { struct obj gold; gold.otyp = GOLD_PIECE; gold.ox = mtmp->mx; gold.oy = mtmp->my; map_object(&gold,1); } else for (obj = mtmp->minvent; obj; obj = obj->nobj) if (sobj->blessed && (temp = o_material(obj, GOLD))) { temp->ox = mtmp->mx; temp->oy = mtmp->my; map_object(temp,1); break; } else if ((temp = o_in(obj, COIN_CLASS))) { temp->ox = mtmp->mx; temp->oy = mtmp->my; map_object(temp,1); break; } } newsym(u.ux,u.uy); pline("You feel very greedy, and sense gold!"); exercise(A_WIS, TRUE); win_pause_output(P_MAP); doredraw(); u.uinwater = uw; if (Underwater) under_water(2); if (u.uburied) under_ground(2); return 0; }
/* make sure the inventory is fully identified, even if DYWYPI = n */ for (obj = invent; obj; obj = obj->nobj) { discover_object(obj->otyp, TRUE, FALSE, TRUE); obj->known = obj->bknown = obj->dknown = obj->rknown = 1; } display_inventory(NULL, TRUE); container_contents(invent, TRUE, TRUE); dump_spells(); dump_skills(); enlighten_mon(&youmonst, how > LAST_KILLER ? 1 : 2, 1); /* final */ list_vanquished('y', FALSE); list_genocided('y', FALSE); show_conduct(how > LAST_KILLER ? 1 : 2); dooverview(&(struct nh_cmd_arg){.argtype = 0}); dohistory(&(struct nh_cmd_arg){.argtype = 0}); calc_score(how, TRUE, money_cnt(invent) + hidden_gold()); /* make menus work normally again */ dump_catch_menus(FALSE); } /* try to get the player back in a viable state after being killed */ static void savelife(int how) { /* just swallow any --More--s that were waiting until we died; if the player has a force-more on msgc_fatalavoid, they'll get a --More-- anyway, and if they don't, they probably don't want one */ turnstate.force_more_pending_until_done = FALSE; u.uswldtim = 0;
/* * return 1: guard moved, 0: guard didn't, -1: let m_move do it, -2: died */ int gd_move(struct monst *grd) { int x, y, nx, ny, m, n; int dx, dy, gx, gy, fci; unsigned char typ; struct fakecorridor *fcp; struct egd *egrd = EGD(grd); struct rm *crm; bool goldincorridor = false, u_in_vault = vault_occupied(u.urooms) ? true : false, grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT) ? true : false; bool disappear_msg_seen = false, semi_dead = (grd->mhp <= 0); bool u_carry_gold = ((u.ugold + hidden_gold()) > 0L); bool see_guard; if (!on_level(&(egrd->gdlevel), &u.uz)) return (-1); nx = ny = m = n = 0; if (!u_in_vault && !grd_in_vault) wallify_vault(grd); if (!grd->mpeaceful) { if (semi_dead) { egrd->gddone = 1; goto newpos; } if (!u_in_vault && (grd_in_vault || (in_fcorridor(grd, grd->mx, grd->my) && !in_fcorridor(grd, u.ux, u.uy)))) { (void)rloc(grd, false); wallify_vault(grd); (void)clear_fcorr(grd, true); goto letknow; } if (!in_fcorridor(grd, grd->mx, grd->my)) (void)clear_fcorr(grd, true); return (-1); } if (abs(egrd->ogx - grd->mx) > 1 || abs(egrd->ogy - grd->my) > 1) return (-1); /* teleported guard - treat as monster */ if (egrd->fcend == 1) { if (u_in_vault && (u_carry_gold || um_dist(grd->mx, grd->my, 1))) { if (egrd->warncnt == 3) verbalize("I repeat, %sfollow me!", u_carry_gold ? (!u.ugold ? "drop that hidden gold and " : "drop that gold and ") : ""); if (egrd->warncnt == 7) { m = grd->mx; n = grd->my; verbalize("You've been warned, knave!"); mnexto(grd); levl[m][n].typ = egrd->fakecorr[0].ftyp; newsym(m, n); grd->mpeaceful = 0; return (-1); } /* not fair to get mad when (s)he's fainted or paralyzed */ if (!is_fainted() && multi >= 0) egrd->warncnt++; return (0); } if (!u_in_vault) { if (u_carry_gold) { /* player teleported */ m = grd->mx; n = grd->my; (void)rloc(grd, false); levl[m][n].typ = egrd->fakecorr[0].ftyp; newsym(m, n); grd->mpeaceful = 0; letknow: if (!cansee(grd->mx, grd->my) || !mon_visible(grd)) { You_hear("the shrill sound of a guard's whistle."); } else { const char * fmt = um_dist(grd->mx, grd->my, 2) ? "see an angry %s approaching." : "are confronted by an angry %s."; char name[BUFSZ]; g_monnam(name, BUFSZ, grd); You(fmt, name); } return (-1); } else { verbalize("Well, begone."); wallify_vault(grd); egrd->gddone = 1; goto cleanup; } } } if (egrd->fcend > 1) { if (egrd->fcend > 2 && in_fcorridor(grd, grd->mx, grd->my) && !egrd->gddone && !in_fcorridor(grd, u.ux, u.uy) && levl[egrd->fakecorr[0].fx][egrd->fakecorr[0].fy].typ == egrd->fakecorr[0].ftyp) { char name[BUFSZ]; g_monnam(name, BUFSZ, grd); pline_The("%s, confused, disappears.", name); disappear_msg_seen = true; goto cleanup; } if (u_carry_gold && (in_fcorridor(grd, u.ux, u.uy) || /* cover a 'blind' spot */ (egrd->fcend > 1 && u_in_vault))) { if (!grd->mx) { restfakecorr(grd); return (-2); } if (egrd->warncnt < 6) { egrd->warncnt = 6; verbalize("Drop all your gold, scoundrel!"); return (0); } else { verbalize("So be it, rogue!"); grd->mpeaceful = 0; return (-1); } } } for (fci = egrd->fcbeg; fci < egrd->fcend; fci++) if (g_at(egrd->fakecorr[fci].fx, egrd->fakecorr[fci].fy)) { m = egrd->fakecorr[fci].fx; n = egrd->fakecorr[fci].fy; goldincorridor = true; } if (goldincorridor && !egrd->gddone) { x = grd->mx; y = grd->my; if (m == u.ux && n == u.uy) { struct obj *gold = g_at(m, n); /* Grab the gold from between the hero's feet. */ grd->mgold += gold->quan; delobj(gold); newsym(m, n); } else if (m == x && n == y) { mpickgold(grd); /* does a newsym */ } else { /* just for insurance... */ if (MON_AT(m, n) && m != grd->mx && n != grd->my) { verbalize("Out of my way, scum!"); (void)rloc(m_at(m, n), false); } remove_monster(grd->mx, grd->my); newsym(grd->mx, grd->my); place_monster(grd, m, n); mpickgold(grd); /* does a newsym */ } if (cansee(m, n)) { char name[BUFSZ]; Monnam(name, BUFSZ, grd); pline("%s%s picks up the gold.", name, grd->mpeaceful ? " calms down and" : ""); } if (x != grd->mx || y != grd->my) { remove_monster(grd->mx, grd->my); newsym(grd->mx, grd->my); place_monster(grd, x, y); newsym(x, y); } if (!grd->mpeaceful) return (-1); else { egrd->warncnt = 5; return (0); } } if (um_dist(grd->mx, grd->my, 1) || egrd->gddone) { if (!egrd->gddone && !rn2(10)) verbalize("Move along!"); restfakecorr(grd); return (0); /* didn't move */ } x = grd->mx; y = grd->my; if (u_in_vault) goto nextpos; /* look around (hor & vert only) for accessible places */ for (nx = x - 1; nx <= x + 1; nx++) { for (ny = y - 1; ny <= y + 1; ny++) { if ((nx == x || ny == y) && (nx != x || ny != y) && isok(nx, ny)) { typ = (crm = &levl[nx][ny])->typ; if (!IS_STWALL(typ) && !IS_POOL(typ)) { if (in_fcorridor(grd, nx, ny)) goto nextnxy; if (*in_rooms(nx, ny, VAULT)) continue; /* seems we found a good place to leave him alone */ egrd->gddone = 1; if (ACCESSIBLE(typ)) goto newpos; crm->typ = (typ == SCORR) ? CORR : DOOR; if (crm->typ == DOOR) crm->flags = D_NODOOR; goto proceed; } } nextnxy: ; } } nextpos: nx = x; ny = y; gx = egrd->gdx; gy = egrd->gdy; dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; if (abs(gx - x) >= abs(gy - y)) nx += dx; else ny += dy; while ((typ = (crm = &levl[nx][ny])->typ) != 0) { /* in view of the above we must have IS_WALL(typ) or typ == POOL */ /* must be a wall here */ if (isok(nx + nx - x, ny + ny - y) && !IS_POOL(typ) && IS_ROOM(levl[nx+nx-x][ny+ny-y].typ)) { crm->typ = DOOR; crm->flags = D_NODOOR; goto proceed; } if (dy && nx != x) { nx = x; ny = y + dy; continue; } if (dx && ny != y) { ny = y; nx = x + dx; dy = 0; continue; } /* I don't like this, but ... */ if (IS_ROOM(typ)) { crm->typ = DOOR; crm->flags = D_NODOOR; goto proceed; } break; } crm->typ = CORR; proceed: unblock_point(nx, ny); /* doesn't block light */ if (cansee(nx, ny)) newsym(nx, ny); fcp = &(egrd->fakecorr[egrd->fcend]); if (egrd->fcend++ == FCSIZ) impossible("fakecorr overflow"); fcp->fx = nx; fcp->fy = ny; fcp->ftyp = typ; newpos: if (egrd->gddone) { /* The following is a kludge. We need to keep */ /* the guard around in order to be able to make */ /* the fake corridor disappear as the player */ /* moves out of it, but we also need the guard */ /* out of the way. We send the guard to never- */ /* never land. We set ogx ogy to mx my in order */ /* to avoid a check at the top of this function. */ /* At the end of the process, the guard is killed */ /* in restfakecorr(). */ cleanup: x = grd->mx; y = grd->my; see_guard = canspotmon(grd); wallify_vault(grd); remove_monster(grd->mx, grd->my); newsym(grd->mx, grd->my); place_monster(grd, 0, 0); egrd->ogx = grd->mx; egrd->ogy = grd->my; restfakecorr(grd); if (!semi_dead && (in_fcorridor(grd, u.ux, u.uy) || cansee(x, y))) { if (!disappear_msg_seen && see_guard) { char name[BUFSZ]; g_monnam(name, BUFSZ, grd); pline("Suddenly, the %s disappears.", name); } return (1); } return (-2); } egrd->ogx = grd->mx; /* update old positions */ egrd->ogy = grd->my; remove_monster(grd->mx, grd->my); place_monster(grd, nx, ny); newsym(grd->mx, grd->my); restfakecorr(grd); return (1); }
void invault(void) { struct monst *guard; int trycount, vaultroom = (int)vault_occupied(u.urooms); if (!vaultroom) { u.uinvault = 0; return; } vaultroom -= ROOMOFFSET; guard = findgd(); if (++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */ char buf[BUFSZ]; int x, y, dd, gx, gy; int lx = 0, ly = 0; /* first find the goal for the guard */ for (dd = 2; (dd < ROWNO || dd < COLNO); dd++) { for (y = u.uy - dd; y <= u.uy + dd; ly = y, y++) { if (y < 0 || y > ROWNO - 1) continue; for (x = u.ux - dd; x <= u.ux + dd; lx = x, x++) { if (y != u.uy - dd && y != u.uy + dd && x != u.ux - dd) x = u.ux + dd; if (x < 1 || x > COLNO - 1) continue; if (levl[x][y].typ == CORR) { if (x < u.ux) lx = x + 1; else if (x > u.ux) lx = x - 1; else lx = x; if (y < u.uy) ly = y + 1; else if (y > u.uy) ly = y - 1; else ly = y; if (levl[lx][ly].typ != STONE && levl[lx][ly].typ != CORR) goto incr_radius; goto fnd; } } } incr_radius: ; } impossible("Not a single corridor on this level??"); tele(); return; fnd: gx = x; gy = y; /* next find a good place for a door in the wall */ x = u.ux; y = u.uy; if (levl[x][y].typ != ROOM) { /* player dug a door and is in it */ if (levl[x + 1][y].typ == ROOM) x = x + 1; else if (levl[x][y + 1].typ == ROOM) y = y + 1; else if (levl[x - 1][y].typ == ROOM) x = x - 1; else if (levl[x][y - 1].typ == ROOM) y = y - 1; else if (levl[x + 1][y + 1].typ == ROOM) { x = x + 1; y = y + 1; } else if (levl[x - 1][y - 1].typ == ROOM) { x = x - 1; y = y - 1; } else if (levl[x + 1][y - 1].typ == ROOM) { x = x + 1; y = y - 1; } else if (levl[x - 1][y + 1].typ == ROOM) { x = x - 1; y = y + 1; } } while (levl[x][y].typ == ROOM) { int dx, dy; dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; if (abs(gx - x) >= abs(gy - y)) x += dx; else y += dy; } if (x == u.ux && y == u.uy) { if (levl[x + 1][y].typ == HWALL || levl[x + 1][y].typ == DOOR) x = x + 1; else if (levl[x - 1][y].typ == HWALL || levl[x - 1][y].typ == DOOR) x = x - 1; else if (levl[x][y + 1].typ == VWALL || levl[x][y + 1].typ == DOOR) y = y + 1; else if (levl[x][y - 1].typ == VWALL || levl[x][y - 1].typ == DOOR) y = y - 1; else return; } /* make something interesting happen */ if (!(guard = makemon(&mons[PM_GUARD], x, y, NO_MM_FLAGS))) return; guard->isgd = 1; guard->mpeaceful = 1; set_malign(guard); EGD(guard)->gddone = 0; EGD(guard)->ogx = x; EGD(guard)->ogy = y; assign_level(&(EGD(guard)->gdlevel), &u.uz); EGD(guard)->vroom = vaultroom; EGD(guard)->warncnt = 0; reset_faint(); /* if fainted - wake up */ if (canspotmon(guard)) { char name[BUFSZ]; g_monnam(name, BUFSZ, guard); pline("Suddenly one of the Vault's %s enters!", makeplural(name)); } else { pline("Someone else has entered the Vault."); } newsym(guard->mx, guard->my); if (youmonst.m_ap_type == M_AP_OBJECT || u.uundetected) { if (youmonst.m_ap_type == M_AP_OBJECT && youmonst.mappearance != GOLD_PIECE) verbalize("Hey! Who left that %s in here?", mimic_obj_name(&youmonst)); /* You're mimicking some object or you're hidden. */ pline("Puzzled, %s turns around and leaves.", mhe(guard)); mongone(guard); return; } if (Strangled|| is_silent(youmonst.data) || multi < 0) { /* [we ought to record whether this this message has already been given in order to vary it upon repeat visits, but discarding the monster and its egd data renders that hard] */ verbalize("I'll be back when you're ready to speak to me!"); mongone(guard); return; } stop_occupation(); /* if occupied, stop it *now* */ trycount = 5; do { getlin("\"Hello stranger, who are you?\" -", buf); (void)mungspaces(buf); } while (!letter(buf[0]) && --trycount > 0); if (u.ualign.type == A_LAWFUL && /* ignore trailing text, in case player includes character's rank */ strncmpi(buf, plname, (int)strlen(plname)) != 0) { adjalign(-1); /* Liar! */ } if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos") || !strcmpi(buf, "Creosote")) { if (!mvitals[PM_CROESUS].died) { verbalize("Oh, yes, of course. Sorry to have disturbed you."); mongone(guard); } else { setmangry(guard); verbalize("Back from the dead, are you? I'll remedy that!"); /* don't want guard to waste next turn wielding a weapon */ if (!MON_WEP(guard)) { guard->weapon_check = NEED_HTH_WEAPON; (void)mon_wield_item(guard); } } return; } verbalize("I don't know you."); if (!u.ugold && !hidden_gold()) verbalize("Please follow me."); else { if (!u.ugold) verbalize("You have hidden gold."); verbalize("Most likely all your gold was stolen from this vault."); verbalize("Please drop that gold and follow me."); } EGD(guard)->gdx = gx; EGD(guard)->gdy = gy; EGD(guard)->fcbeg = 0; EGD(guard)->fakecorr[0].fx = x; EGD(guard)->fakecorr[0].fy = y; if (IS_WALL(levl[x][y].typ)) EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ; else { /* the initial guard location is a dug door */ int vlt = EGD(guard)->vroom; signed char lowx = rooms[vlt].lx, hix = rooms[vlt].hx; signed char lowy = rooms[vlt].ly, hiy = rooms[vlt].hy; if (x == lowx - 1 && y == lowy - 1) EGD(guard)->fakecorr[0].ftyp = TLCORNER; else if (x == hix + 1 && y == lowy - 1) EGD(guard)->fakecorr[0].ftyp = TRCORNER; else if (x == lowx - 1 && y == hiy + 1) EGD(guard)->fakecorr[0].ftyp = BLCORNER; else if (x == hix + 1 && y == hiy + 1) EGD(guard)->fakecorr[0].ftyp = BRCORNER; else if (y == lowy - 1 || y == hiy + 1) EGD(guard)->fakecorr[0].ftyp = HWALL; else if (x == lowx - 1 || x == hix + 1) EGD(guard)->fakecorr[0].ftyp = VWALL; } levl[x][y].typ = DOOR; levl[x][y].flags = D_NODOOR; unblock_point(x, y); /* doesn't block light */ EGD(guard)->fcend = 1; EGD(guard)->warncnt = 1; } }
/* Locks the live log file and writes 'buffer' */ void livelog_write_string(char* buffer) { FILE* livelogfile; #ifdef FILE_AREAS if (lock_file_area(LOGAREA, LIVELOGFILE, 10)) { #else if (lock_file(LIVELOGFILE, SCOREPREFIX, 10)) { #endif if(!(livelogfile = fopen_datafile_area(LOGAREA, LIVELOGFILE, "a", SCOREPREFIX))) { pline("Cannot open live log file!"); } else { fprintf(livelogfile, "%s", buffer); (void) fclose(livelogfile); } unlock_file_area(LOGAREA, LIVELOGFILE); } } static char *livelog_prefix() { s_level *lev = Is_special(&u.uz); snprintf(prefixbuf, STRBUF_LEN, "version=%s-%d.%d.%d:" "player=%s:turns=%ld:starttime=%ld:" "currenttime=%ld:" "dnum=%d:dname=%s:dlev=%d:maxlvl=%d:" "dlev_name=%s:" "hp=%d:maxhp=%d:deaths=%d:" #ifdef RECORD_REALTIME "realtime=%ld:" #endif "conduct=0x%lx:" "role=%s:race=%s:" "gender=%s:align=%s:" "gender0=%s:align0=%s:" "explvl=%d:exp=%ld:" "elbereths=%ld:" "xplevel=%d:" /* XP level */ "exp=%ld:" /* Experience points */ "mode=%s:" "gold=%ld", GAME_SHORT_NAME, VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, plname, moves, (long)u.ubirthday, (long)current_epoch(), u.uz.dnum, dungeons[u.uz.dnum].dname, depth(&u.uz), deepest_lev_reached(TRUE), lev ? lev->proto : "", /* proto level name if special level */ u.uhp, u.uhpmax, u.umortality, #ifdef RECORD_REALTIME (long)realtime_data.realtime, #endif encodeconduct(), urole.filecode, urace.filecode, genders[flags.female].filecode, aligns[1-u.ualign.type].filecode, genders[flags.initgend].filecode, aligns[1-u.ualignbase[A_ORIGINAL]].filecode, u.ulevel,u.uexp, u.uconduct.elbereths, u.ulevel, /* XP level */ (long)u.uexp, /* Experience points */ (flags.debug ? "debug" : /* mode */ flags.explore ? "explore" : hell_and_hell_mode ? "hah" : heaven_or_hell_mode ? "hoh" : "normal"), #ifndef GOLDOBJ (u.ugold + hidden_gold()) #else (money_cnt(invent) + hidden_gold()) #endif ); return prefixbuf; }
/* * return 1: guard moved, 0: guard didn't, -1: let m_move do it, -2: died */ int gd_move(struct monst *grd) { int x, y, nx, ny, m, n; int dx, dy, gx = 0, gy = 0, fci; uchar typ; struct fakecorridor *fcp; struct egd *egrd = EGD(grd); struct rm *crm; boolean goldincorridor = FALSE, u_in_vault = vault_occupied(u.urooms) ? TRUE : FALSE, grd_in_vault = *in_rooms(level, grd->mx, grd->my, VAULT) ? TRUE : FALSE; boolean disappear_msg_seen = FALSE, semi_dead = (grd->mhp <= 0); long umoney = money_cnt(invent); boolean u_carry_gold = ((umoney + hidden_gold()) > 0L); boolean see_guard; if (!on_level(&(egrd->gdlevel), &u.uz)) return -1; nx = ny = m = n = 0; if (!u_in_vault && !grd_in_vault) wallify_vault(grd); if (!grd->mpeaceful) { if (semi_dead) { egrd->gddone = 1; goto newpos; } if (!u_in_vault && (grd_in_vault || (in_fcorridor(grd, grd->mx, grd->my) && !in_fcorridor(grd, u.ux, u.uy)))) { rloc(grd, FALSE); wallify_vault(grd); clear_fcorr(grd, TRUE); goto letknow; } if (!in_fcorridor(grd, grd->mx, grd->my)) clear_fcorr(grd, TRUE); return -1; } if (abs(egrd->ogx - grd->mx) > 1 || abs(egrd->ogy - grd->my) > 1) return -1; /* teleported guard - treat as monster */ if (egrd->fcend == 1) { if (u_in_vault && (u_carry_gold || um_dist(grd->mx, grd->my, 1))) { if (egrd->warncnt == 3) verbalize("I repeat, %sfollow me!", u_carry_gold ? (!umoney ? "drop that hidden money and " : "drop that money and ") : ""); if (egrd->warncnt == 7) { m = grd->mx; n = grd->my; verbalize("You've been warned, knave!"); mnexto(grd); level->locations[m][n].typ = egrd->fakecorr[0].ftyp; newsym(m, n); msethostility(grd, TRUE, FALSE); return -1; } /* not fair to get mad when (s)he's fainted or paralyzed */ if (!u_helpless(hm_all)) egrd->warncnt++; return 0; } if (!u_in_vault) { if (u_carry_gold) { /* player teleported */ m = grd->mx; n = grd->my; rloc(grd, FALSE); level->locations[m][n].typ = egrd->fakecorr[0].ftyp; newsym(m, n); msethostility(grd, TRUE, FALSE); letknow: if (!cansee(grd->mx, grd->my) || !mon_visible(grd)) You_hear("the shrill sound of a guard's whistle."); else pline(um_dist(grd->mx, grd->my, 2) ? "You see an angry guard approaching." : "You are confronted by an angry guard."); return -1; } else { verbalize("Well, begone."); wallify_vault(grd); egrd->gddone = 1; goto cleanup; } } } if (egrd->fcend > 1) { if (egrd->fcend > 2 && in_fcorridor(grd, grd->mx, grd->my) && !egrd->gddone && !in_fcorridor(grd, u.ux, u.uy) && level->locations[egrd->fakecorr[0].fx][egrd->fakecorr[0].fy].typ == egrd->fakecorr[0].ftyp) { if (canseemon(grd)) { pline("%s, confused, disappears.", Monnam(grd)); disappear_msg_seen = TRUE; } goto cleanup; } if (u_carry_gold && (in_fcorridor(grd, u.ux, u.uy) || /* cover a 'blind' spot */ (egrd->fcend > 1 && u_in_vault))) { if (!grd->mx) { restfakecorr(grd); return -2; } if (egrd->warncnt < 6) { egrd->warncnt = 6; verbalize("Drop all your gold, scoundrel!"); return 0; } else { verbalize("So be it, rogue!"); msethostility(grd, TRUE, FALSE); return -1; } } } for (fci = egrd->fcbeg; fci < egrd->fcend; fci++) if (gold_at(level, egrd->fakecorr[fci].fx, egrd->fakecorr[fci].fy)) { m = egrd->fakecorr[fci].fx; n = egrd->fakecorr[fci].fy; goldincorridor = TRUE; } if (goldincorridor && !egrd->gddone) { boolean yours = FALSE; x = grd->mx; y = grd->my; if (m == u.ux && n == u.uy) { struct obj *gold = gold_at(level, m, n); yours = TRUE; /* Grab the gold from between the hero's feet. */ obj_extract_self(gold); add_to_minv(grd, gold); newsym(m, n); } else if (m == x && n == y) { mpickgold(grd); /* does a newsym */ } else { /* just for insurance... */ if (MON_AT(level, m, n) && m != grd->mx && n != grd->my) { verbalize("Out of my way, scum!"); rloc(m_at(level, m, n), FALSE); } remove_monster(level, grd->mx, grd->my); newsym(grd->mx, grd->my); place_monster(grd, m, n); mpickgold(grd); /* does a newsym */ } if (cansee(m, n)) { if (yours) { pline("%s%s picks up the gold.", Monnam(grd), grd->mpeaceful ? " calms down and" : ""); } else { pline("%s picks up some gold.", Monnam(grd)); } } if (x != grd->mx || y != grd->my) { remove_monster(level, grd->mx, grd->my); newsym(grd->mx, grd->my); place_monster(grd, x, y); newsym(x, y); } if (!grd->mpeaceful) return -1; else { egrd->warncnt = 5; return 0; } } if (um_dist(grd->mx, grd->my, 1) || egrd->gddone) { if (!egrd->gddone && !rn2(10)) verbalize("Move along!"); restfakecorr(grd); return 0; /* didn't move */ } x = grd->mx; y = grd->my; if (u_in_vault) goto nextpos; /* look around (hor & vert only) for accessible places */ for (nx = x - 1; nx <= x + 1; nx++) for (ny = y - 1; ny <= y + 1; ny++) { if ((nx == x || ny == y) && (nx != x || ny != y) && isok(nx, ny)) { typ = (crm = &level->locations[nx][ny])->typ; if (!IS_STWALL(typ) && !IS_POOL(typ)) { if (in_fcorridor(grd, nx, ny)) goto nextnxy; if (*in_rooms(level, nx, ny, VAULT)) continue; /* seems we found a good place to leave him alone */ egrd->gddone = 1; if (ACCESSIBLE(typ)) goto newpos; crm->typ = (typ == SCORR) ? CORR : DOOR; if (crm->typ == DOOR) crm->doormask = D_NODOOR; goto proceed; } } nextnxy:; } nextpos: nx = x; ny = y; gx = egrd->gdx; gy = egrd->gdy; dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; if (abs(gx - x) >= abs(gy - y)) nx += dx; else ny += dy; while ((typ = (crm = &level->locations[nx][ny])->typ) != 0) { /* in view of the above we must have IS_WALL(typ) or typ == POOL */ /* must be a wall here */ if (isok(nx + nx - x, ny + ny - y) && !IS_POOL(typ) && IS_ROOM(level->locations[nx + nx - x][ny + ny - y].typ)) { crm->typ = DOOR; crm->doormask = D_NODOOR; goto proceed; } if (dy && nx != x) { nx = x; ny = y + dy; continue; } if (dx && ny != y) { ny = y; nx = x + dx; dy = 0; continue; } /* I don't like this, but ... */ if (IS_ROOM(typ)) { crm->typ = DOOR; crm->doormask = D_NODOOR; goto proceed; } break; } crm->typ = CORR; proceed: unblock_point(nx, ny); /* doesn't block light */ if (cansee(nx, ny)) newsym(nx, ny); if ((nx != gx || ny != gy) || (grd->mx != gx || grd->my != gy)) { fcp = &(egrd->fakecorr[egrd->fcend]); if (egrd->fcend++ == FCSIZ) panic("fakecorr overflow"); fcp->fx = nx; fcp->fy = ny; fcp->ftyp = typ; } else if (!egrd->gddone) { /* We're stuck, so try to find a new destination. */ if (!find_guard_dest(grd, &egrd->gdx, &egrd->gdy) || (egrd->gdx == gx && egrd->gdy == gy)) { pline("%s, confused, disappears.", Monnam(grd)); disappear_msg_seen = TRUE; goto cleanup; } else goto nextpos; } newpos: if (egrd->gddone) { /* The following is a kludge. We need to keep the guard around in order to be able to make the fake corridor disappear as the player moves out of it, but we also need the guard out of the way. We send the guard to never-never land. We set ogx ogy to mx my in order to avoid a check at the top of this function. At the end of the process, the guard is killed in restfakecorr(). */ cleanup: x = grd->mx; y = grd->my; see_guard = canspotmon(grd); wallify_vault(grd); remove_monster(level, grd->mx, grd->my); newsym(grd->mx, grd->my); grd->mx = COLNO; grd->my = ROWNO; egrd->ogx = grd->mx; egrd->ogy = grd->my; restfakecorr(grd); if (!semi_dead && (in_fcorridor(grd, u.ux, u.uy) || cansee(x, y))) { if (!disappear_msg_seen && see_guard) pline("Suddenly, %s disappears.", noit_mon_nam(grd)); return 1; } return -2; } egrd->ogx = grd->mx; /* update old positions */ egrd->ogy = grd->my; remove_monster(level, grd->mx, grd->my); place_monster(grd, nx, ny); newsym(grd->mx, grd->my); restfakecorr(grd); return 1; }
void invault(void) { struct monst *guard; int trycount, vaultroom = (int)vault_occupied(u.urooms); boolean messages = TRUE; if (!vaultroom) { u.uinvault = 0; return; } vaultroom -= ROOMOFFSET; guard = findgd(); if (++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */ int x, y, gx, gy; xchar rx, ry; long umoney; const char *buf; /* first find the goal for the guard */ if (!find_guard_dest(NULL, &rx, &ry)) return; gx = rx; gy = ry; /* next find a good place for a door in the wall */ x = u.ux; y = u.uy; if (level->locations[x][y].typ != ROOM) { /* player dug a door and is in it */ if (level->locations[x + 1][y].typ == ROOM) x = x + 1; else if (level->locations[x][y + 1].typ == ROOM) y = y + 1; else if (level->locations[x - 1][y].typ == ROOM) x = x - 1; else if (level->locations[x][y - 1].typ == ROOM) y = y - 1; else if (level->locations[x + 1][y + 1].typ == ROOM) { x = x + 1; y = y + 1; } else if (level->locations[x - 1][y - 1].typ == ROOM) { x = x - 1; y = y - 1; } else if (level->locations[x + 1][y - 1].typ == ROOM) { x = x + 1; y = y - 1; } else if (level->locations[x - 1][y + 1].typ == ROOM) { x = x - 1; y = y + 1; } } while (level->locations[x][y].typ == ROOM) { int dx, dy; dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; if (abs(gx - x) >= abs(gy - y)) x += dx; else y += dy; } if (x == u.ux && y == u.uy) { if (level->locations[x + 1][y].typ == HWALL || level->locations[x + 1][y].typ == DOOR) x = x + 1; else if (level->locations[x - 1][y].typ == HWALL || level->locations[x - 1][y].typ == DOOR) x = x - 1; else if (level->locations[x][y + 1].typ == VWALL || level->locations[x][y + 1].typ == DOOR) y = y + 1; else if (level->locations[x][y - 1].typ == VWALL || level->locations[x][y - 1].typ == DOOR) y = y - 1; else return; } /* make something interesting happen */ if (!(guard = makemon(&mons[PM_GUARD], level, x, y, NO_MM_FLAGS))) return; guard->isgd = 1; msethostility(guard, FALSE, TRUE); EGD(guard)->gddone = 0; EGD(guard)->ogx = x; EGD(guard)->ogy = y; assign_level(&(EGD(guard)->gdlevel), &u.uz); EGD(guard)->vroom = vaultroom; EGD(guard)->warncnt = 0; /* We used to reset fainted status here, but that doesn't really make sense; instead, that's treated like normal helplessness */ if (canspotmon(guard)) pline("Suddenly one of the Vault's guards enters!"); else if (canhear()) You_hear("someone else enter the Vault."); else messages = FALSE; newsym(guard->mx, guard->my); if (youmonst.m_ap_type == M_AP_OBJECT || u.uundetected || u.uburied) { if (youmonst.m_ap_type == M_AP_OBJECT && youmonst.mappearance != GOLD_PIECE) verbalize("Hey! Who left that %s in here?", mimic_obj_name(&youmonst)); /* You're mimicking some object or you're hidden. */ if (messages) pline("Puzzled, %s turns around and leaves.", mhe(guard)); mongone(guard); return; } if (Engulfed) { if ((!u.ustuck->minvis || perceives(guard->data))) verbalize("How did that %s get in here?", m_monnam(u.ustuck)); if (messages) pline("Puzzled, %s turns around and leaves.", mhe(guard)); mongone(guard); return; } if (Strangled || is_silent(youmonst.data) || u_helpless(hm_all)) { /* [we ought to record whether this this message has already been given in order to vary it upon repeat visits, but discarding the monster and its egd data renders that hard] */ verbalize("I'll be back when you're ready to speak to me!"); mongone(guard); return; } action_interrupted(); trycount = 5; do { buf = getlin("\"Hello stranger, who are you?\" -", FALSE); buf = msgmungspaces(buf); } while (!letter(buf[0]) && --trycount > 0); if (u.ualign.type == A_LAWFUL && /* ignore trailing text, in case player includes character's rank */ strncmpi(buf, u.uplname, (int)strlen(u.uplname)) != 0) { adjalign(-1); /* Liar! */ } if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos") || !strcmpi(buf, "Creosote")) { if (!mvitals[PM_CROESUS].died) { verbalize("Oh, yes, of course. Sorry to have disturbed you."); mongone(guard); } else { setmangry(guard); verbalize("Back from the dead, are you? I'll remedy that!"); /* don't want guard to waste next turn wielding a weapon */ if (!MON_WEP(guard)) { guard->weapon_check = NEED_HTH_WEAPON; mon_wield_item(guard); } } return; } verbalize("I don't know you."); umoney = money_cnt(invent); if (!umoney && !hidden_gold()) verbalize("Please follow me."); else { if (!umoney) verbalize("You have hidden money."); verbalize("Most likely all your money was stolen from this vault."); verbalize("Please drop that money and follow me."); } EGD(guard)->gdx = gx; EGD(guard)->gdy = gy; EGD(guard)->fcbeg = 0; EGD(guard)->fakecorr[0].fx = x; EGD(guard)->fakecorr[0].fy = y; if (IS_WALL(level->locations[x][y].typ)) EGD(guard)->fakecorr[0].ftyp = level->locations[x][y].typ; else { /* the initial guard location is a dug door */ int vlt = EGD(guard)->vroom; xchar lowx = level->rooms[vlt].lx, hix = level->rooms[vlt].hx; xchar lowy = level->rooms[vlt].ly, hiy = level->rooms[vlt].hy; if (x == lowx - 1 && y == lowy - 1) EGD(guard)->fakecorr[0].ftyp = TLCORNER; else if (x == hix + 1 && y == lowy - 1) EGD(guard)->fakecorr[0].ftyp = TRCORNER; else if (x == lowx - 1 && y == hiy + 1) EGD(guard)->fakecorr[0].ftyp = BLCORNER; else if (x == hix + 1 && y == hiy + 1) EGD(guard)->fakecorr[0].ftyp = BRCORNER; else if (y == lowy - 1 || y == hiy + 1) EGD(guard)->fakecorr[0].ftyp = HWALL; else if (x == lowx - 1 || x == hix + 1) EGD(guard)->fakecorr[0].ftyp = VWALL; } level->locations[x][y].typ = DOOR; level->locations[x][y].doormask = D_NODOOR; unblock_point(x, y); /* doesn't block light */ EGD(guard)->fcend = 1; EGD(guard)->warncnt = 1; } }