/* * 从 i 开始, 其父节点路径中每个节点的 priority 小于该节点父节点的 priority, 则 TODO */ static void float_up_or_down(struct heap *heap, size_t i) { if (!float_up(heap, i)) { float_down(heap, i); } }
void ringoff(struct obj *obj) { long mask; mask = obj->owornmask & W_RING; setworn(NULL, obj->owornmask); if(!(u.uprops[PROP(obj->otyp)].p_flgs & mask)) impossible("Strange... I didn't know you had that ring."); u.uprops[PROP(obj->otyp)].p_flgs &= ~mask; switch(obj->otyp) { case RIN_FIRE_RESISTANCE: /* Bad luck if the player is in hell... --jgm */ if (!Fire_resistance && dlevel >= 30) { pline("The flames of Hell burn you to a crisp."); killer = "stupidity in hell"; done("burned"); } break; case RIN_LEVITATION: if(!Levitation) { /* no longer floating */ float_down(); } break; case RIN_GAIN_STRENGTH: u.ustr -= obj->spe; u.ustrmax -= obj->spe; if(u.ustr > 118) u.ustr = 118; if(u.ustrmax > 118) u.ustrmax = 118; flags.botl = 1; break; case RIN_INCREASE_DAMAGE: u.udaminc -= obj->spe; break; } }
//能保证权限大小排序么? void heap_rebuild(struct heap *heap) { size_t i; for (i = heap->n / 2; i >= 1; i--) { float_down(heap, i); } }
void nh_timeout() { register struct prop *upp; int sleeptime; int m_idx; int baseluck = (flags.moonphase == FULL_MOON) ? 1 : 0; if (flags.friday13) baseluck -= 1; if (u.uluck != baseluck && moves % (u.uhave.amulet || u.ugangr ? 300 : 600) == 0) { /* Cursed luckstones stop bad luck from timing out; blessed luckstones * stop good luck from timing out; normal luckstones stop both; * neither is stopped if you don't have a luckstone. * Luck is based at 0 usually, +1 if a full moon and -1 on Friday 13th */ register int time_luck = stone_luck(FALSE); boolean nostone = !carrying(LUCKSTONE) && !stone_luck(TRUE); if(u.uluck > baseluck && (nostone || time_luck < 0)) u.uluck--; else if(u.uluck < baseluck && (nostone || time_luck > 0)) u.uluck++; } if(u.uinvulnerable) return; /* things past this point could kill you */ if(Stoned) stoned_dialogue(); if(Slimed) slime_dialogue(); if(Vomiting) vomiting_dialogue(); if(Strangled) choke_dialogue(); if(u.mtimedone && !--u.mtimedone) { if (Unchanging) u.mtimedone = rnd(100*youmonst.data->mlevel + 1); else rehumanize(); } if(u.ucreamed) u.ucreamed--; /* Dissipate spell-based protection. */ if (u.usptime) { if (--u.usptime == 0 && u.uspellprot) { u.usptime = u.uspmtime; u.uspellprot--; find_ac(); if (!Blind) Norep("The %s haze around you %s.", hcolor(NH_GOLDEN), u.uspellprot ? "becomes less dense" : "disappears"); } } #ifdef STEED if (u.ugallop) { if (--u.ugallop == 0L && u.usteed) pline("%s stops galloping.", Monnam(u.usteed)); } #endif for(upp = u.uprops; upp < u.uprops+SIZE(u.uprops); upp++) if((upp->intrinsic & TIMEOUT) && !(--upp->intrinsic & TIMEOUT)) { switch(upp - u.uprops){ case STONED: if (delayed_killer && !killer) { killer = delayed_killer; delayed_killer = 0; } if (!killer) { /* leaving killer_format would make it "petrified by petrification" */ killer_format = NO_KILLER_PREFIX; killer = "killed by petrification"; } done(STONING); break; case SLIMED: if (delayed_killer && !killer) { killer = delayed_killer; delayed_killer = 0; } if (!killer) { killer_format = NO_KILLER_PREFIX; killer = "turned into green slime"; } done(TURNED_SLIME); break; case VOMITING: make_vomiting(0L, TRUE); break; case SICK: You("die from your illness."); killer_format = KILLED_BY_AN; killer = u.usick_cause; if ((m_idx = name_to_mon(killer)) >= LOW_PM) { if (type_is_pname(&mons[m_idx])) { killer_format = KILLED_BY; } else if (mons[m_idx].geno & G_UNIQ) { killer = the(killer); Strcpy(u.usick_cause, killer); killer_format = KILLED_BY; } } u.usick_type = 0; done(POISONING); break; case FAST: if (!Very_fast) You_feel("yourself slowing down%s.", Fast ? " a bit" : ""); break; case CONFUSION: HConfusion = 1; /* So make_confused works properly */ make_confused(0L, TRUE); stop_occupation(); break; case STUNNED: HStun = 1; make_stunned(0L, TRUE); stop_occupation(); break; case BLINDED: Blinded = 1; make_blinded(0L, TRUE); stop_occupation(); break; case INVIS: newsym(u.ux,u.uy); if (!Invis && !BInvis && !Blind) { You(!See_invisible ? "are no longer invisible." : "can no longer see through yourself."); stop_occupation(); } break; case SEE_INVIS: set_mimic_blocking(); /* do special mimic handling */ see_monsters(); /* make invis mons appear */ newsym(u.ux,u.uy); /* make self appear */ stop_occupation(); break; case WOUNDED_LEGS: heal_legs(); stop_occupation(); break; case HALLUC: HHallucination = 1; (void) make_hallucinated(0L, TRUE, 0L); stop_occupation(); break; case SLEEPING: if (unconscious() || Sleep_resistance) HSleeping += rnd(100); else if (Sleeping) { You("fall asleep."); sleeptime = rnd(20); fall_asleep(-sleeptime, TRUE); HSleeping += sleeptime + rnd(100); } break; case LEVITATION: (void) float_down(I_SPECIAL|TIMEOUT, 0L); break; case STRANGLED: killer_format = KILLED_BY; killer = (u.uburied) ? "suffocation" : "strangulation"; done(DIED); break; case FUMBLING: /* call this only when a move took place. */ /* otherwise handle fumbling msgs locally. */ if (u.umoved && !Levitation) { slip_or_trip(); nomul(-2, "fumbling"); nomovemsg = ""; /* The more you are carrying the more likely you * are to make noise when you fumble. Adjustments * to this number must be thoroughly play tested. */ if ((inv_weight() > -500)) { You("make a lot of noise!"); wake_nearby(); } } /* from outside means slippery ice; don't reset counter if that's the only fumble reason */ HFumbling &= ~FROMOUTSIDE; if (Fumbling) HFumbling += rnd(20); break; case DETECT_MONSTERS: see_monsters(); break; case PREGNANT: { char buf[BUFSZ]; if (!flags.female) { strcpy(buf, body_part(STOMACH)); if (!strcmp(buf, "stomach")) strcpy(buf, "belly"); pline("Something bursts out of your %s!"); killer_format = KILLED_BY; killer = "male childbirth"; done(DIED); } mksobj_at(PLACENTA, u.ux, u.uy, FALSE, FALSE); pline("BABIES!"); /* TODO */ stop_occupation(); break; } } } run_timers(); }
static int arti_invoke(struct obj *obj) { const struct artifact *oart = get_artifact(obj); if (!oart || !oart->inv_prop) { if (obj->oclass == WAND_CLASS) return do_break_wand(obj); else if (obj->oclass == GEM_CLASS || obj->oclass == TOOL_CLASS) return dorub(obj); else if (obj->otyp == CRYSTAL_BALL) use_crystal_ball(obj); else pline("Nothing happens."); return 1; } if (oart->inv_prop > LAST_PROP) { /* It's a special power, not "just" a property */ if (obj->age > moves) { /* the artifact is tired :-) */ pline("You feel that %s %s ignoring you.", the(xname(obj)), otense(obj, "are")); /* and just got more so; patience is essential... */ obj->age += (long) dice(3,10); return 1; } obj->age = moves + rnz(100); switch(oart->inv_prop) { case TAMING: { struct obj pseudo; boolean unused_known; pseudo = zeroobj; /* neither cursed nor blessed */ pseudo.otyp = SCR_TAMING; seffects(&pseudo, &unused_known); break; } case HEALING: { int healamt = (u.uhpmax + 1 - u.uhp) / 2; long creamed = (long)u.ucreamed; if (Upolyd) healamt = (u.mhmax + 1 - u.mh) / 2; if (healamt || Sick || Slimed || Blinded > creamed) pline("You feel better."); else goto nothing_special; if (healamt > 0) { if (Upolyd) u.mh += healamt; else u.uhp += healamt; } if (Sick) make_sick(0L,NULL,FALSE,SICK_ALL); if (Slimed) Slimed = 0L; if (Blinded > creamed) make_blinded(creamed, FALSE); iflags.botl = 1; break; } case ENERGY_BOOST: { int epboost = (u.uenmax + 1 - u.uen) / 2; if (epboost > 120) epboost = 120; /* arbitrary */ else if (epboost < 12) epboost = u.uenmax - u.uen; if (epboost) { pline("You feel re-energized."); u.uen += epboost; iflags.botl = 1; } else goto nothing_special; break; } case UNTRAP: { if (!untrap(TRUE)) { obj->age = 0; /* don't charge for changing their mind */ return 0; } break; } case CHARGE_OBJ: { struct obj *otmp = getobj(recharge_type, "charge"); boolean b_effect; if (!otmp) { obj->age = 0; return 0; } b_effect = obj->blessed && (Role_switch == oart->role || !oart->role); recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0); update_inventory(); break; } case LEV_TELE: level_tele(); break; case CREATE_PORTAL: { int i, num_ok_dungeons, last_ok_dungeon = 0; d_level newlev; extern int n_dgns; /* from dungeon.c */ struct nh_menuitem *items; items = malloc(n_dgns * sizeof(struct nh_menuitem)); num_ok_dungeons = 0; for (i = 0; i < n_dgns; i++) { if (!dungeons[i].dunlev_ureached) continue; items[num_ok_dungeons].id = i+1; items[num_ok_dungeons].accel = 0; items[num_ok_dungeons].role = MI_NORMAL; items[num_ok_dungeons].selected = FALSE; strcpy(items[num_ok_dungeons].caption, dungeons[i].dname); num_ok_dungeons++; last_ok_dungeon = i; } if (num_ok_dungeons > 1) { /* more than one entry; display menu for choices */ int n; int selected[1]; n = display_menu(items, num_ok_dungeons, "Open a portal to which dungeon?", PICK_ONE, selected); free(items); if (n <= 0) goto nothing_special; i = selected[0] - 1; } else { free(items); i = last_ok_dungeon; /* also first & only OK dungeon */ } /* * i is now index into dungeon structure for the new dungeon. * Find the closest level in the given dungeon, open * a use-once portal to that dungeon and go there. * The closest level is either the entry or dunlev_ureached. */ newlev.dnum = i; if (dungeons[i].depth_start >= depth(&u.uz)) newlev.dlevel = dungeons[i].entry_lev; else newlev.dlevel = dungeons[i].dunlev_ureached; if (u.uhave.amulet || In_endgame(&u.uz) || In_endgame(&newlev) || newlev.dnum == u.uz.dnum) { pline("You feel very disoriented for a moment."); } else { if (!Blind) pline("You are surrounded by a shimmering sphere!"); else pline("You feel weightless for a moment."); goto_level(&newlev, FALSE, FALSE, FALSE); } break; } case ENLIGHTENING: enlightenment(0); break; case CREATE_AMMO: { struct obj *otmp = mksobj(level, ARROW, TRUE, FALSE); if (!otmp) goto nothing_special; otmp->blessed = obj->blessed; otmp->cursed = obj->cursed; otmp->bknown = obj->bknown; if (obj->blessed) { if (otmp->spe < 0) otmp->spe = 0; otmp->quan += rnd(10); } else if (obj->cursed) { if (otmp->spe > 0) otmp->spe = 0; } else otmp->quan += rnd(5); otmp->owt = weight(otmp); hold_another_object(otmp, "Suddenly %s out.", aobjnam(otmp, "fall"), NULL); break; } } } else { long eprop = (u.uprops[oart->inv_prop].extrinsic ^= W_ARTI), iprop = u.uprops[oart->inv_prop].intrinsic; boolean on = (eprop & W_ARTI) != 0; /* true if invoked prop just set */ if (on && obj->age > moves) { /* the artifact is tired :-) */ u.uprops[oart->inv_prop].extrinsic ^= W_ARTI; pline("You feel that %s %s ignoring you.", the(xname(obj)), otense(obj, "are")); /* can't just keep repeatedly trying */ obj->age += (long) dice(3,10); return 1; } else if (!on) { /* when turning off property, determine downtime */ /* arbitrary for now until we can tune this -dlc */ obj->age = moves + rnz(100); } if ((eprop & ~W_ARTI) || iprop) { nothing_special: /* you had the property from some other source too */ if (carried(obj)) pline("You feel a surge of power, but nothing seems to happen."); return 1; } switch(oart->inv_prop) { case CONFLICT: if (on) pline("You feel like a rabble-rouser."); else pline("You feel the tension decrease around you."); break; case LEVITATION: if (on) { float_up(); spoteffects(FALSE); } else float_down(I_SPECIAL|TIMEOUT, W_ARTI); break; case INVIS: if (BInvis || Blind) goto nothing_special; newsym(u.ux, u.uy); if (on) pline("Your body takes on a %s transparency...", Hallucination ? "normal" : "strange"); else pline("Your body seems to unfade..."); break; } } return 1; }
/* Stop riding the current steed */ void dismount_steed(int reason) { struct monst *mtmp; struct obj *otmp; coord cc; const char *verb = "fall"; boolean repair_leg_damage = TRUE; unsigned save_utrap = u.utrap; boolean have_spot = landing_spot(&cc, reason, 0); mtmp = u.usteed; /* make a copy of steed pointer */ /* Sanity check */ if (!mtmp) /* Just return silently */ return; /* Check the reason for dismounting */ otmp = which_armor(mtmp, os_saddle); switch (reason) { case DISMOUNT_THROWN: verb = "are thrown"; case DISMOUNT_FELL: pline("You %s off of %s!", verb, mon_nam(mtmp)); if (!have_spot) have_spot = landing_spot(&cc, reason, 1); losehp(rn1(10, 10), "killed in a riding accident"); set_wounded_legs(LEFT_SIDE, (int)LWounded_legs + rn1(5, 5)); set_wounded_legs(RIGHT_SIDE, (int)RWounded_legs + rn1(5, 5)); repair_leg_damage = FALSE; break; case DISMOUNT_POLY: pline("You can no longer ride %s.", mon_nam(u.usteed)); if (!have_spot) have_spot = landing_spot(&cc, reason, 1); break; case DISMOUNT_ENGULFED: /* caller displays message */ break; case DISMOUNT_BONES: /* hero has just died... */ break; case DISMOUNT_GENERIC: /* no messages, just make it so */ break; case DISMOUNT_BYCHOICE: default: if (otmp && otmp->cursed) { pline("You can't. The saddle %s cursed.", otmp->bknown ? "is" : "seems to be"); otmp->bknown = TRUE; return; } if (!have_spot) { pline("You can't. There isn't anywhere for you to stand."); return; } if (!mtmp->mnamelth) { pline("You've been through the dungeon on %s with no name.", an(mtmp->data->mname)); if (Hallucination) pline("It felt good to get out of the rain."); } else pline("You dismount %s.", mon_nam(mtmp)); } /* While riding these refer to the steed's legs so after dismounting they refer to the player's legs once again. */ if (repair_leg_damage) LWounded_legs = RWounded_legs = 0; /* Release the steed and saddle */ u.usteed = 0; u.ugallop = 0L; /* Set player and steed's position. Try moving the player first unless we're in the midst of creating a bones file. */ if (reason == DISMOUNT_BONES) { /* move the steed to an adjacent square */ if (enexto(&cc, level, u.ux, u.uy, mtmp->data)) rloc_to(mtmp, cc.x, cc.y); else /* evidently no room nearby; move steed elsewhere */ rloc(mtmp, FALSE); return; } if (!DEADMONSTER(mtmp)) { place_monster(mtmp, u.ux, u.uy); if (!Engulfed && !u.ustuck && have_spot) { const struct permonst *mdat = mtmp->data; /* The steed may drop into water/lava */ if (!is_flyer(mdat) && !is_floater(mdat) && !is_clinger(mdat)) { if (is_pool(level, u.ux, u.uy)) { if (!Underwater) pline("%s falls into the %s!", Monnam(mtmp), surface(u.ux, u.uy)); if (!is_swimmer(mdat) && !amphibious(mdat)) { killed(mtmp); adjalign(-1); } } else if (is_lava(level, u.ux, u.uy)) { pline("%s is pulled into the lava!", Monnam(mtmp)); if (!likes_lava(mdat)) { killed(mtmp); adjalign(-1); } } } /* Steed dismounting consists of two steps: being moved to another square, and descending to the floor. We have functions to do each of these activities, but they're normally called individually and include an attempt to look at or pick up the objects on the floor: teleds() --> spoteffects() --> pickup() float_down() --> pickup() We use this kludge to make sure there is only one such attempt. Clearly this is not the best way to do it. A full fix would involve having these functions not call pickup() at all, instead calling them first and calling pickup() afterwards. But it would take a lot of work to keep this change from having any unforseen side effects (for instance, you would no longer be able to walk onto a square with a hole, and autopickup before falling into the hole). */ /* [ALI] No need to move the player if the steed died. */ if (!DEADMONSTER(mtmp)) { /* Keep steed here, move the player to cc; teleds() clears u.utrap */ in_steed_dismounting = TRUE; teleds(cc.x, cc.y, TRUE); in_steed_dismounting = FALSE; /* Put your steed in your trap */ if (save_utrap) mintrap(mtmp); } /* Couldn't... try placing the steed */ } else if (enexto(&cc, level, u.ux, u.uy, mtmp->data)) { /* Keep player here, move the steed to cc */ rloc_to(mtmp, cc.x, cc.y); /* Player stays put */ /* Otherwise, kill the steed */ } else { killed(mtmp); adjalign(-1); } } /* Return the player to the floor */ if (reason != DISMOUNT_ENGULFED) { in_steed_dismounting = TRUE; float_down(0L); in_steed_dismounting = FALSE; encumber_msg(); turnstate.vision_full_recalc = TRUE; } else /* polearms behave differently when not mounted */ if (uwep && is_pole(uwep)) u.bashmsg = FALSE; return; }