/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* hack.do.c version 1.0.1 - check Levitation with POT_PARALYSIS - added flags.no_rest_on_space */ #include #ifndef AMIGA #include /* Is this really used??? */ #endif #include #include "hack.h" #include "def.func_tab.h" extern char *getenv(),*parse(),*getlogin(),*lowc(),*unctrl(); extern int float_down(); extern char *nomovemsg, *catmore; extern struct obj *splitobj(), *addinv(); extern boolean hmon(); extern char morc; /* Routines to do various user commands */ int done1(); dodrink() { register struct obj *otmp,*objs; register struct monst *mtmp; register int unkn = 0, nothing = 0; otmp = getobj("!", "drink"); if(!otmp) return(0); switch(otmp->otyp){ case POT_RESTORE_STRENGTH: unkn++; pline("Wow! This makes you feel great!"); if(u.ustr < u.ustrmax) { u.ustr = u.ustrmax; flags.botl = 1; } break; case POT_BOOZE: unkn++; pline("Ooph! This tastes like liquid fire!"); Confusion += d(3,8); /* the whiskey makes us feel better */ if(u.uhp < u.uhpmax) losehp(-1, "bottle of whiskey"); if(!rn2(4)) { pline("You pass out."); multi = -rnd(15); nomovemsg = "You awake with a headache."; } break; case POT_INVISIBILITY: if(Invis) nothing++; else { if(!Blind) pline("Gee! All of a sudden, you can't see yourself."); else pline("You feel rather airy."), unkn++; newsym(u.ux,u.uy); } Invis += rn1(15,31); break; case POT_FRUIT_JUICE: pline("This tastes like fruit juice."); lesshungry(20); break; case POT_HEALING: pline("You begin to feel better."); flags.botl = 1; u.uhp += rnd(10); if(u.uhp > u.uhpmax) u.uhp = ++u.uhpmax; if(Blind) Blind = 1; /* see on next move */ if(Sick) Sick = 0; break; case POT_PARALYSIS: if(Levitation) pline("Your head is frozen to the ceiling!"); else pline("Your feet are frozen to the floor!"); nomul(-(rn1(10,25))); break; case POT_MONSTER_DETECTION: if(!fmon) { strange_feeling(otmp); return(1); } else { cls(); for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->mx > 0) at(mtmp->mx,mtmp->my,mtmp->data->mlet); prme(); pline("You sense the presence of monsters."); more(); docrt(); } break; case POT_OBJECT_DETECTION: if(!fobj) { strange_feeling(otmp); return(1); } else { for(objs = fobj; objs; objs = objs->nobj) if(objs->ox != u.ux || objs->oy != u.uy) goto outobjmap; pline("You sense the presence of objects close nearby."); break; outobjmap: cls(); for(objs = fobj; objs; objs = objs->nobj) at(objs->ox,objs->oy,objs->olet); prme(); pline("You sense the presence of objects."); more(); docrt(); } break; case POT_SICKNESS: pline("Yech! This stuff tastes like poison."); if(Poison_resistance) pline("(But in fact it was biologically contaminated orange juice.)"); losestr(rn1(4,3)); losehp(rnd(10), "poison potion"); break; case POT_CONFUSION: if(!Confusion) pline("Huh, What? Where am I?"); else nothing++; Confusion += rn1(7,16); break; case POT_GAIN_STRENGTH: pline("Wow do you feel strong!"); if(u.ustr == 118) break; if(u.ustr > 17) u.ustr += rnd(118-u.ustr); else u.ustr++; if(u.ustr > u.ustrmax) u.ustrmax = u.ustr; flags.botl = 1; break; case POT_SPEED: if(Wounded_legs) { if((Wounded_legs & BOTH_SIDES) == BOTH_SIDES) pline("Your legs feel somewhat better."); else pline("Your leg feels somewhat better."); Wounded_legs = 0; unkn++; break; } if(!(Fast & ~INTRINSIC)) pline("You are suddenly moving much faster."); else pline("Your legs get new energy."), unkn++; Fast += rn1(10,100); break; case POT_BLINDNESS: if(!Blind) pline("A cloud of darkness falls upon you."); else nothing++; Blind += rn1(100,250); seeoff(0); break; case POT_GAIN_LEVEL: pluslvl(); break; case POT_EXTRA_HEALING: pline("You feel much better."); flags.botl = 1; u.uhp += d(2,20)+1; if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += 2); if(Blind) Blind = 1; if(Sick) Sick = 0; break; case POT_LEVITATION: if(!Levitation) float_up(); else nothing++; Levitation += rnd(100); u.uprops[PROP(RIN_LEVITATION)].p_tofn = float_down; break; default: pline("What a funny potion! (%d)", otmp->otyp); impossible(); return(0); } if(nothing) { unkn++; pline("You have a peculiar feeling for a moment, then it passes."); } if(otmp->dknown && !objects[otmp->otyp].oc_name_known) { if(!unkn) { objects[otmp->otyp].oc_name_known = 1; u.urexp += 10; } else if(!objects[otmp->otyp].oc_uname) docall(otmp); } useup(otmp); return(1); } pluslvl() { register int num; pline("You feel more experienced."); num = rnd(10); u.uhpmax += num; u.uhp += num; u.uexp = (10*pow(u.ulevel-1))+1; pline("Welcome to level %d.", ++u.ulevel); flags.botl = 1; } strange_feeling(obj) register struct obj *obj; { pline("You have a strange feeling for a moment, then it passes."); if(!objects[obj->otyp].oc_name_known && !objects[obj->otyp].oc_uname) docall(obj); useup(obj); } dodrop() { register struct obj *obj; obj = getobj("0$#", "drop"); if(!obj) return(0); if(obj->olet == '$') { if(obj->quan == 0) pline("You didn't drop any gold pieces."); else { mkgold((int) obj->quan, u.ux, u.uy); pline("You dropped %u gold piece%s.", obj->quan, plur(obj->quan)); if(Invis) newsym(u.ux, u.uy); } free((char *) obj); return(1); } return(drop(obj)); } drop(obj) register struct obj *obj; { if(obj->owornmask & (W_ARMOR | W_RING)){ pline("You cannot drop something you are wearing."); return(0); } if(obj == uwep) { if(uwep->cursed) { pline("Your weapon is welded to your hand!"); return(0); } setuwep((struct obj *) 0); } pline("You dropped %s.", doname(obj)); dropx(obj); return(1); } dropx(obj) register struct obj *obj; { if(obj->otyp == CRYSKNIFE) obj->otyp = WORM_TOOTH; freeinv(obj); obj->ox = u.ux; obj->oy = u.uy; obj->nobj = fobj; fobj = obj; if(Invis) newsym(u.ux,u.uy); subfrombill(obj); stackobj(obj); } /* drop several things */ doddrop() { return(ggetobj("drop", drop, 0)); } rhack(cmd) register char *cmd; { register struct func_tab *tlist = list; boolean firsttime = FALSE; register int res; if(!cmd) { firsttime = TRUE; flags.nopick = 0; cmd = parse(); } if(!*cmd || *cmd == 0377 || (flags.no_rest_on_space && *cmd == ' ')){ flags.move = 0; return; /* probably we just had an interrupt */ } if(movecm(cmd)) { walk: if(multi) flags.mv = 1; domove(); return; } if(movecm(lowc(cmd))) { flags.run = 1; rush: if(firsttime){ if(!multi) multi = COLNO; u.last_str_turn = 0; } flags.mv = 1; #ifdef QUEST if(flags.run >= 4) finddir(); if(firsttime){ u.ux0 = u.ux + u.dx; u.uy0 = u.uy + u.dy; } #endif QUEST domove(); return; } if((*cmd == 'f' && movecm(cmd+1)) || movecm(unctrl(cmd))) { flags.run = 2; goto rush; } if(*cmd == 'F' && movecm(lowc(cmd+1))) { flags.run = 3; goto rush; } if(*cmd == 'm' && movecm(cmd+1)) { flags.run = 0; flags.nopick = 1; goto walk; } if(*cmd == 'M' && movecm(lowc(cmd+1))) { flags.run = 1; flags.nopick = 1; goto rush; } #ifdef QUEST if(*cmd == cmd[1] && (*cmd == 'f' || *cmd == 'F')) { flags.run = 4; if(*cmd == 'F') flags.run += 2; if(cmd[2] == '-') flags.run += 1; goto rush; } #endif QUEST while(tlist->f_char) { if(*cmd == tlist->f_char){ res = (*(tlist->f_funct))(0); if(!res) { flags.move = 0; multi = 0; } return; } tlist++; } pline("Unknown command '%s'",cmd); multi = flags.move = 0; } doredraw() { docrt(); return(0); } dohelp() { FILE *fp; char bufr[BUFSZ]; int line, i; if ( (fp = fopen(HELP,"r")) == NULL) pline("cannot access help"); else { cls(); line = 1; while(fgets(bufr,BUFSZ,fp)) { myprintf("%s", bufr); if (line++ > ROWNO) { myprintf("---more---"); xwaitforspace(FALSE); morc = 0; for (i=0;i<10;i++) backsp(); cl_end(); line = 1; } } more(); docrt(); } } #ifdef SHELL dosh(){ char *file, *Open(); if ( (file = Open("CON:1/1/639/199/Hack SubProcess", 1006)) == NULL) pline("cannot create process window"); if (Execute("", file, NULL)) pline("cannot execute commands"); Close(file); return(0); } #endif SHELL child(wt) { pline("Cannot create children"); docrt(); return(0); } dodown() { if(u.ux != xdnstair || u.uy != ydnstair) { pline("You can't go down here."); return(0); } if(u.ustuck) { pline("You are being held, and cannot go down."); return(1); } if(Levitation) { pline("You're floating high above the stairs."); return(0); } goto_level(dlevel+1, TRUE); return(1); } doup() { if(u.ux != xupstair || u.uy != yupstair) { pline("You can't go up here."); return(0); } if(u.ustuck) { pline("You are being held, and cannot go up."); return(1); } if(inv_weight() + 5 > 0) { pline("Your load is too heavy to climb the stairs."); return(1); } goto_level(dlevel-1, TRUE); return(1); } goto_level(newlevel, at_stairs) register int newlevel; register boolean at_stairs; { register int fd; register boolean up = (newlevel < dlevel); if(newlevel <= 0) done("escaped"); /* in fact < 0 is impossible */ if(newlevel == dlevel) return; /* this cannot happen either */ glo(dlevel); fd = creat(lock,FMASK); if(fd < 0) { /* * This is not quite impossible: e.g., we may have * exceeded our quota. If that is the case then we * cannot leave this level, and cannot save either. */ pline("A mysterious force prevents you from going %s.", up ? "up" : "down"); return; } if(Punished) unplacebc(); keepdogs(); seeoff(1); flags.nscrinh = 1; u.ux = FAR; /* hack */ (void) inshop(); /* probably was a trapdoor */ savelev(fd); (void) close(fd); dlevel = newlevel; if(maxdlevel < dlevel) maxdlevel = dlevel; glo(dlevel); if((fd = open(lock,0)) < 0) mklev(); else { (void) getlev(fd); (void) close(fd); } if(at_stairs) { if(up) { u.ux = xdnstair; u.uy = ydnstair; if(!u.ux) { /* entering a maze from below? */ u.ux = xupstair; /* this will confuse the player! */ u.uy = yupstair; } if(Punished){ pline("With great effort you climb the stairs"); placebc(1); } } else { u.ux = xupstair; u.uy = yupstair; if(inv_weight() + 5 > 0 || Punished){ pline("You fall down the stairs."); losehp(rnd(3), "fall"); if(Punished) { if(uwep != uball && rn2(3)){ pline("... and are hit by the iron ball"); losehp(rnd(20), "iron ball"); } placebc(1); } selftouch("Falling, you"); } } } else { /* trapdoor or level_tele */ do { u.ux = rnd(COLNO-1); u.uy = rn2(ROWNO); } while(levl[u.ux][u.uy].typ != ROOM || m_at(u.ux,u.uy)); if(Punished){ if(uwep != uball && !up /* %% */ && rn2(5)){ pline("The iron ball falls on your head."); losehp(rnd(25), "iron ball"); } placebc(1); } selftouch("Falling, you"); } (void) inshop(); #ifdef TRACK initrack(); #endif TRACK losedogs(); flags.nscrinh = 0; setsee(); { register struct monst *mtmp; if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp); /* riv05!a3 */ } docrt(); pickup(); read_engr_at(u.ux,u.uy); } donull() { return(1); /* Do nothing, but let other things happen */ } struct monst *bhit(), *boomhit(); dothrow() { register struct obj *obj; register struct monst *mon; register int tmp; obj = getobj("#)", "throw"); /* it is also possible to throw food */ /* (or jewels, or iron balls ... ) */ if(!obj || !getdir()) return(0); if(obj->owornmask & (W_ARMOR | W_RING)){ pline("You can't throw something you are wearing"); return(0); } if(obj == uwep){ if(obj->cursed){ pline("Your weapon is welded to your hand"); return(1); } if(obj->quan > 1) setuwep(splitobj(obj, 1)); else setuwep((struct obj *) 0); } else if(obj->quan > 1) (void) splitobj(obj, 1); freeinv(obj); if(u.uswallow) { mon = u.ustuck; bhitpos.x = mon->mx; bhitpos.y = mon->my; } else if(obj->otyp == BOOMERANG) { mon = boomhit(u.dx,u.dy); /* boomhit delivers -1 if the thing was caught */ if((int) mon == -1) { (void) addinv(obj); return(1); } } else mon = bhit(u.dx,u.dy, (!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1, obj->olet); if(mon) { /* awake monster if sleeping */ wakeup(mon); if(obj->olet == WEAPON_SYM) { tmp = -1+u.ulevel+mon->data->ac+abon(); if(obj->otyp < ROCK) { if(!uwep || uwep->otyp != obj->otyp+(BOW-ARROW)) tmp -= 4; else { tmp += uwep->spe; } } else if(obj->otyp == BOOMERANG) tmp += 4; tmp += obj->spe; if(u.uswallow || tmp >= rnd(20)) { if(hmon(mon,obj,1) == TRUE){ /* mon still alive */ #ifndef NOWORM cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp); #endif NOWORM } else mon = 0; /* weapons thrown disappear sometimes */ if(obj->otyp < BOOMERANG && rn2(3)) { /* check bill; free */ obfree(obj, (struct obj *) 0); return(1); } } else miss(objects[obj->otyp].oc_name, mon); } else if(obj->otyp == HEAVY_IRON_BALL) { tmp = -1+u.ulevel+mon->data->ac+abon(); if(!Punished || obj != uball) tmp += 2; if(u.utrap) tmp -= 2; if(u.uswallow || tmp >= rnd(20)) { if(hmon(mon,obj,1) == FALSE) mon = 0; /* he died */ } else miss("iron ball", mon); } else { if(cansee(bhitpos.x,bhitpos.y)) pline("You miss %s.",monnam(mon)); else pline("You miss it."); if(obj->olet == FOOD_SYM && mon->data->mlet == 'd') if(tamedog(mon,obj)) return(1); if(obj->olet == GEM_SYM && mon->data->mlet == 'u'){ if(obj->dknown && objects[obj->otyp].oc_name_known){ if(objects[obj->otyp].g_val > 0){ u.uluck += 5; goto valuable; } else { pline("%s is not interested in your junk.", Monnam(mon)); } } else { /* value unknown to @ */ u.uluck++; valuable: pline("%s graciously accepts your gift.", Monnam(mon)); mpickobj(mon, obj); rloc(mon); return(1); } } } } obj->ox = bhitpos.x; obj->oy = bhitpos.y; obj->nobj = fobj; fobj = obj; /* prevent him from throwing articles to the exit and escaping */ /* subfrombill(obj); */ stackobj(obj); if(Punished && obj == uball && (bhitpos.x != u.ux || bhitpos.y != u.uy)){ freeobj(uchain); unpobj(uchain); if(u.utrap){ if(u.utraptype == TT_PIT) pline("The ball pulls you out of the pit!"); else { register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE; pline("The ball pulls you out of the bear trap."); pline("Your %s leg is severely damaged.", (side == LEFT_SIDE) ? "left" : "right"); Wounded_legs |= side + rnd(1000); losehp(2, "thrown ball"); } u.utrap = 0; } unsee(); uchain->nobj = fobj; fobj = uchain; u.ux = uchain->ox = bhitpos.x - u.dx; u.uy = uchain->oy = bhitpos.y - u.dy; setsee(); (void) inshop(); } if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y); return(1); } /* split obj so that it gets size num */ /* remainder is put in the object structure delivered by this call */ struct obj * splitobj(obj, num) register struct obj *obj; register int num; { register struct obj *otmp; otmp = newobj(0); *otmp = *obj; /* copies whole structure */ otmp->o_id = flags.ident++; otmp->onamelth = 0; obj->quan = num; obj->owt = weight(obj); otmp->quan -= num; otmp->owt = weight(otmp); /* -= obj->owt ? */ obj->nobj = otmp; if(obj->unpaid) splitbill(obj,otmp); return(otmp); } char * lowc(str) register char *str; { static char buf[2]; if(*str >= 'A' && *str <= 'Z') *buf = *str+'a'-'A'; else *buf = *str; buf[1] = 0; return(buf); } char * unctrl(str) register char *str; { static char buf[2]; if(*str >= ('A' & 037) && *str <= ('Z' & 037)) *buf = *str + 0140; else *buf = *str; buf[1] = 0; return(buf); }