1 /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
2 /* command3.c */
3
4 /* This file contains some more top level command functions
5 called from command1.c */
6
7 #ifndef MSDOS_SUPPORTED_ANTIQUE
8 #include <pwd.h>
9 #include <unistd.h>
10 #endif
11
12 #include "glob.h"
13 #include "date.h"
14
15 /* look at some spot */
examine()16 void examine()
17 {
18 pol ol;
19 int x=Player.x,y=Player.y,drewmenu=FALSE;
20
21 clearmsg();
22
23 /* WDT HACK: I'm not sure I buy that one shouldn't be able to examine
24 * when one is blind. However, the 'right' way to do it is certainly
25 * too difficult (I would expect to be able to examine only the items
26 * I actually recall). So, for now I'll use David Given's compromise.
27 * 12/30/98
28 */
29 if (Player.status[BLINDED] > 0)
30 {
31 mprint("You're blind - you can't examine things.");
32 return;
33 }
34 setgamestatus(SKIP_MONSTERS);
35 mprint("Examine --");
36 setspot(&x,&y);
37 if (inbounds(x,y)) {
38 clearmsg();
39 if (Current_Environment == E_COUNTRYSIDE) {
40 if (! c_statusp(x, y, SEEN))
41 print3("How should I know what that is?");
42 else {
43 mprint("That terrain is:");
44 mprint(countryid(Country[x][y].current_terrain_type));
45 }
46 }
47 else if (! view_los_p(Player.x,Player.y,x,y))
48 print3("I refuse to examine something I can't see.");
49 else {
50 clearmsg();
51 if (Level->site[x][y].creature != NULL)
52 mprint(mstatus_string(Level->site[x][y].creature));
53 else if ((Player.x == x) && (Player.y ==y))
54 describe_player();
55 if (loc_statusp(x,y,SECRET))
56 print2("An age-worn stone wall.");
57 else
58 switch (Level->site[x][y].locchar) {
59 case SPACE: print2("An infinite void."); break;
60 case PORTCULLIS: print2("A heavy steel portcullis"); break;
61 case ABYSS: print2("An entrance to the infinite abyss"); break;
62 case FLOOR:
63 if (Current_Dungeon == Current_Environment)
64 print2("A dirty stone floor.");
65 else print2("The ground.");
66 break;
67 case WALL:
68 if (Level->site[x][y].aux == 0)
69 print2("A totally impervious wall.");
70 else if (Level->site[x][y].aux < 10)
71 print2("A pitted concrete wall.");
72 else if (Level->site[x][y].aux < 30)
73 print2("An age-worn sandstone wall.");
74 else if (Level->site[x][y].aux < 50)
75 print2("A smooth basalt wall.");
76 else if (Level->site[x][y].aux < 70)
77 print2("A solid granite wall.");
78 else if (Level->site[x][y].aux < 90)
79 print2("A wall of steel.");
80 else if (Level->site[x][y].aux < 210) {
81 if (Current_Environment == E_CITY)
82 print2("A thick wall of Rampart bluestone");
83 else print2("A magically reinforced wall.");
84 }
85 else print2("An almost totally impervious wall.");
86 break;
87 case RUBBLE:print2("A dangerous-looking pile of rubble."); break;
88 case SAFE:print2("A steel safe inset into the floor."); break;
89 case CLOSED_DOOR:print2("A solid oaken door, now closed."); break;
90 case OPEN_DOOR:print2("A solid oaken door, now open."); break;
91 case STATUE:print2("A strange-looking statue."); break;
92 case STAIRS_UP:print2("A stairway leading up."); break;
93 case STAIRS_DOWN:print2("A stairway leading down...."); break;
94 case TRAP:print2(trapid(Level->site[x][y].p_locf)); break;
95 case HEDGE:
96 if (Level->site[x][y].p_locf == L_EARTH_STATION)
97 print2("A weird fibrillation of oozing tendrils.");
98 else print2("A brambly, thorny hedge.");
99 break;
100 case LAVA:print2("A bubbling pool of lava."); break;
101 case LIFT:print2("A strange glowing disk."); break;
102 case ALTAR:print2("An (un?)holy altar."); break;
103 case CHAIR:print2("A chair."); break;
104 case WHIRLWIND:print2("A strange cyclonic electrical storm."); break;
105 case WATER:
106 if (Level->site[x][y].p_locf == L_WATER)
107 print2("A deep pool of water.");
108 else if (Level->site[x][y].p_locf == L_CHAOS)
109 print2("A pool of primal chaos.");
110 else if (Level->site[x][y].p_locf == L_WATER_STATION)
111 print2("A bubbling pool of acid.");
112 else print2("An eerie pool of water.");
113 break;
114 case FIRE:print2("A curtain of fire."); break;
115 default:print2("Wow, I haven't the faintest idea!"); break;
116 }
117 if ((ol = Level->site[x][y].things) != NULL && !loc_statusp(x,y,SECRET)) {
118 if (ol->next == NULL)
119 print3(itemid(ol->thing));
120 else {
121 drewmenu = TRUE;
122 menuclear();
123 menuprint("Things on floor:\n");
124 while (ol != NULL) {
125 menuprint("\n");
126 menuprint(itemid(ol->thing));
127 ol = ol->next;
128 }
129 showmenu();
130 }
131 }
132 morewait();
133 sign_print(x,y,TRUE);
134 }
135 }
136 if (drewmenu) xredraw();
137 }
138
help()139 void help()
140 {
141 char c;
142 char filestr[80];
143 FILE *in, *out;
144 int n;
145
146 clearmsg();
147 print1("Please enter the letter indicating what topic you want help on.");
148 menuclear();
149 menuprint("a: Overview\n");
150 menuprint("b: Characters\n");
151 menuprint("c: Inventories\n");
152 menuprint("d: Movement\n");
153 menuprint("e: Combat\n");
154 menuprint("f: Bugs\n");
155 menuprint("g: Magic\n");
156 menuprint("h: The Countryside\n");
157 menuprint("i: The Screen Display\n");
158 menuprint("j: Saving and Restoring\n");
159 menuprint("k: Options Settings\n");
160 menuprint("l: Dungeon/City/Other Command List\n");
161 menuprint("m: Countryside Command List\n");
162 #if !defined(MSDOS) && !defined(AMIGA)
163 menuprint("n: Everything\n");
164 #endif
165 menuprint("ESCAPE: Forget the whole thing.");
166 showmenu();
167 do
168 c = (char) mcigetc();
169 #if defined(MSDOS) || defined(AMIGA)
170 while ((c < 'a' || c > 'm') && c != ESCAPE);
171 if (c != ESCAPE) {
172 sprintf(filestr, "%shelp%d.txt", Omegalib, c+1-'a');
173 displayfile(filestr);
174 }
175 #else
176 while ((c < 'a' || c > 'n') && c != ESCAPE);
177 if (c == 'n') {
178 print1("Trying to copy all help files to ./omega.doc ");
179 nprint1("Confirm [yn]");
180 if (ynq1()=='y') {
181 change_to_user_perms();
182 out = checkfopen("omega.doc", "w");
183 print2("Copying");
184 for (n = 1; n <= 13; n++)
185 {
186 nprint2(".");
187 sprintf(Str1, "%shelp%d.txt", Omegalib, n);
188 in = checkfopen(Str1, "r");
189 while (fgets(Str1, STRING_LEN, in))
190 fputs(Str1, out);
191 fclose(in);
192 }
193 fclose(out);
194 change_to_game_perms();
195 nprint2(" Done.");
196 }
197 }
198 else if (c != ESCAPE) {
199 sprintf(filestr, "%shelp%d.txt", Omegalib, c+1-'a');
200 print1("Display help file, or Copy help file to file in wd. [dc] ");
201 do
202 c = (char) mcigetc();
203 while ((c != 'd') && (c != 'c')&& (c!=ESCAPE));
204 if (c == 'd')
205 displayfile(filestr);
206 else if (c == 'c') copyfile(filestr);
207 }
208 #endif
209 xredraw();
210 }
211
version()212 void version()
213 {
214 setgamestatus(SKIP_MONSTERS);
215 print3(VERSIONSTRING);
216 nprint3(":");
217 nprint3(" Last Edited: ");
218 nprint3(LAST_OMEGA_EDIT_DATE);
219 }
220
fire()221 void fire()
222 {
223 int index,x1,y1,x2,y2;
224 pob obj;
225 struct monster *m;
226
227 clearmsg();
228
229 print1("Fire/Throw --");
230 index = getitem(NULL_ITEM);
231 if (index == ABORT)
232 setgamestatus(SKIP_MONSTERS);
233 else if (index == CASHVALUE) print3("Can't fire money at something!");
234 else if (cursed(Player.possessions[index]) &&
235 Player.possessions[index]->used)
236 print3("You can't seem to get rid of it!");
237 /* load a crossbow */
238 else if ((Player.possessions[O_WEAPON_HAND] != NULL) &&
239 (Player.possessions[O_WEAPON_HAND]->id == WEAPONID+27) &&
240 (Player.possessions[O_WEAPON_HAND]->aux != LOADED) &&
241 (Player.possessions[index]->id == WEAPONID+29)) {
242 mprint("You crank back the crossbow and load a bolt.");
243 Player.possessions[O_WEAPON_HAND]->aux = LOADED;
244 }
245 else {
246 if (Player.possessions[index]->used) {
247 Player.possessions[index]->used = FALSE;
248 item_use(Player.possessions[index]);
249 }
250 obj = Player.possessions[index];
251 x1 = x2 = Player.x;
252 y1 = y2 = Player.y;
253 setspot(&x2,&y2);
254 if ((x2 == Player.x) && (y2 == Player.y))
255 mprint("You practice juggling for a moment or two.");
256 else {
257 do_object_los(obj->objchar,&x1,&y1,x2,y2);
258 if ((m=Level->site[x1][y1].creature) != NULL) {
259 if (obj->dmg == 0) {
260 if (m->treasure > 0) { /* the monster can have treasure/objects */
261 mprint("Your gift is caught!");
262 givemonster(m,split_item(1,obj));
263 conform_lost_objects(1,obj);
264 }
265 else {
266 mprint("Your thrown offering is ignored.");
267 setgamestatus(SUPPRESS_PRINTING);
268 p_drop_at(x1,y1,1,obj);
269 resetgamestatus(SUPPRESS_PRINTING);
270 conform_lost_objects(1,obj);
271 }
272 }
273 else if (obj->aux == I_SCYTHE) {
274 mprint("It isn't very aerodynamic... you miss.");
275 setgamestatus(SUPPRESS_PRINTING);
276 p_drop_at(x1,y1,1,obj);
277 resetgamestatus(SUPPRESS_PRINTING);
278 conform_lost_objects(1,obj);
279 }
280 else if (hitp(Player.hit,m->ac)) {/* ok already, hit the damn thing */
281 weapon_use(2*statmod(Player.str),obj,m);
282 if ((obj->id == WEAPONID+28 || obj->id == WEAPONID+29) &&
283 !random_range(4))
284 dispose_lost_objects(1,obj);
285 else {
286 setgamestatus(SUPPRESS_PRINTING);
287 p_drop_at(x1,y1,1,obj);
288 resetgamestatus(SUPPRESS_PRINTING);
289 conform_lost_objects(1,obj);
290 }
291 }
292 else {
293 mprint("You miss it.");
294 setgamestatus(SUPPRESS_PRINTING);
295 p_drop_at(x1,y1,1,obj);
296 resetgamestatus(SUPPRESS_PRINTING);
297 conform_lost_objects(1,obj);
298 }
299 }
300 else {
301 setgamestatus(SUPPRESS_PRINTING);
302 p_drop_at(x1,y1,1,obj);
303 resetgamestatus(SUPPRESS_PRINTING);
304 conform_lost_objects(1,obj);
305 plotspot(x1,y1,TRUE);
306 }
307 }
308 }
309 }
310
311
312
quit()313 void quit()
314 {
315 clearmsg();
316 change_to_game_perms();
317 mprint("Quit: Are you sure? [yn] ");
318 if (ynq()=='y') {
319 if (Player.rank[ADEPT] == 0) display_quit();
320 else display_bigwin();
321 #ifdef SAVE_LEVELS
322 kill_all_levels();
323 #endif
324 endgraf();
325 exit(0);
326 }
327 else resetgamestatus(SKIP_MONSTERS);
328 }
329
330
331
332 /* rest in 10 second segments so if woken up by monster won't
333 die automatically.... */
nap()334 void nap()
335 {
336 static int naptime;
337 if (gamestatusp(FAST_MOVE)) {
338 if (naptime-- < 1) {
339 clearmsg();
340 mprint("Yawn. You wake up.");
341 resetgamestatus(FAST_MOVE);
342 drawvision(Player.x,Player.y);
343 }
344 }
345 else {
346 clearmsg();
347 mprint("Rest for how long? (in minutes) ");
348 naptime = (int) parsenum();
349 if (naptime > 600) {
350 print3("You can only sleep up to 10 hours (600 minutes)");
351 naptime = 3600;
352 }
353 else naptime *= 6;
354 if (naptime > 1) {
355 clearmsg();
356 setgamestatus(FAST_MOVE);
357 mprint("Resting.... ");
358 }
359 }
360 }
361
362
charid()363 void charid()
364 {
365 char id;
366 int countryside=FALSE;
367 char cstr[80];
368
369 clearmsg();
370 mprint("Character to identify: ");
371 id = mgetc();
372 if (Current_Environment == E_COUNTRYSIDE) {
373 countryside = TRUE;
374 strcpy(cstr,countryid(id));
375 if (strcmp(cstr,"I have no idea.")==0)
376 countryside = FALSE;
377 else mprint(cstr);
378 }
379 if (! countryside) {
380 if ((id >= 'a' && id <= 'z') || (id >= 'A' && id <= 'Z') || id == '@')
381 mprint("A monster or NPC -- examine (x) to find out exactly.");
382 else switch(id) {
383 case (SPACE&0xff):
384 mprint(" : An airless void (if seen) or unknown region (if unseen)");
385 break;
386 case (WALL&0xff):
387 mprint(" : An (impenetrable?) wall");
388 break;
389 case (OPEN_DOOR&0xff):
390 mprint(" : An open door");
391 break;
392 case (CLOSED_DOOR&0xff):
393 mprint(" : A closed (possibly locked) door");
394 break;
395 case (LAVA&0xff):
396 mprint(" : A pool of lava");
397 break;
398 case (HEDGE&0xff):
399 mprint(" : A dense hedge");
400 break;
401 case (WATER&0xff):
402 mprint(" : A deep body of water");
403 break;
404 case (FIRE&0xff):
405 mprint(" : A curtain of fire");
406 break;
407 case (TRAP&0xff):
408 mprint(" : An uncovered trap");
409 break;
410 case (STAIRS_UP&0xff):
411 mprint(" : A stairway leading up");
412 break;
413 case (STAIRS_DOWN&0xff):
414 mprint(" : A stairway leading down");
415 break;
416 case (FLOOR&0xff):
417 mprint(" : The dungeon floor");
418 break;
419 case (PORTCULLIS&0xff):
420 mprint(" : A heavy steel portcullis");
421 break;
422 case (ABYSS&0xff):
423 mprint(" : An entrance to the infinite abyss");
424 break;
425 case (PLAYER&0xff):
426 mprint(" : You, the player");
427 break;
428 case (CORPSE&0xff):
429 mprint(" : The remains of some creature");
430 break;
431 case (THING&0xff):
432 mprint(" : Some random miscellaneous object");
433 break;
434 case (SAFE&0xff):
435 mprint(" : A steel safe inset into the floor");
436 break;
437 case (RUBBLE&0xff):
438 mprint(" : A dangerous-looking pile of rubble");
439 break;
440 case (STATUE&0xff):
441 mprint(" : A statue");
442 break;
443 case (ALTAR&0xff):
444 mprint(" : A (un?)holy altar");
445 break;
446 case (CASH&0xff):
447 mprint(" : Bills, specie, gems: cash");
448 break;
449 case (PILE&0xff):
450 mprint(" : A pile of objects");
451 break;
452 case (FOOD&0xff):
453 mprint(" : Something edible");
454 break;
455 case (WEAPON&0xff):
456 mprint(" : Some kind of weapon");
457 break;
458 case (MISSILEWEAPON&0xff):
459 mprint(" : Some kind of missile weapon");
460 break;
461 case (SCROLL&0xff):
462 mprint(" : Something readable");
463 break;
464 case (POTION&0xff):
465 mprint(" : Something drinkable");
466 break;
467 case (ARMOR&0xff):
468 mprint(" : A suit of armor");
469 break;
470 case (SHIELD&0xff):
471 mprint(" : A shield");
472 break;
473 case (CLOAK&0xff):
474 mprint(" : A cloak");
475 break;
476 case (BOOTS&0xff):
477 mprint(" : A pair of boots");
478 break;
479 case (STICK&0xff):
480 mprint(" : A stick");
481 break;
482 case (RING&0xff):
483 mprint(" : A ring");
484 break;
485 case (ARTIFACT&0xff):
486 mprint(" : An artifact");
487 break;
488 case (CHAIR&0xff):
489 mprint(" : A chair");
490 break;
491 case (WHIRLWIND&0xff):
492 mprint(" : A whirlwind");
493 break;
494 default:
495 mprint("That character is unused.");
496 break;
497 }
498 }
499 }
500
501
wizard()502 void wizard()
503 {
504 char *lname;
505 #ifndef MSDOS_SUPPORTED_ANTIQUE
506 struct passwd *dastuff;
507 #endif
508
509 setgamestatus(SKIP_MONSTERS);
510 if (gamestatusp(CHEATED)) mprint("You're already in wizard mode!");
511 else {
512 clearmsg();
513 mprint("Really try to enter wizard mode? [yn] ");
514 if (ynq()=='y') {
515 lname = getlogin();
516 #ifndef MSDOS_SUPPORTED_ANTIQUE
517 if (!lname || strlen(lname) == 0)
518 {
519 dastuff = getpwuid(getuid());
520 lname = dastuff->pw_name;
521 }
522 #endif
523 if (strcmp(lname,WIZARD)==0) {
524 setgamestatus(CHEATED);
525 mprint("Wizard mode set.");
526 }
527 else {
528 mprint("There is a shrieking sound, as of reality being distorted.");
529 strcpy(Str1,WIZARD);
530 strcat(Str1,", the Wizard of Omega appears before you....");
531 if (Str1[0] >= 'a' && Str1[0] <= 'z')
532 Str1[0] += 'A'-'a'; /* capitalise 1st letter */
533 mprint(Str1);
534 mprint("'Do not meddle in the affairs of Wizards --");
535 if (random_range(2)) mprint("it makes them soggy and hard to light.'");
536 else mprint("for they are subtle, and swift to anger!'");
537 }
538 }
539 }
540 }
541
542 /* Jump, that is */
vault()543 void vault()
544 {
545 int x=Player.x,y=Player.y,jumper=0;
546
547 clearmsg();
548
549 if (Player.possessions[O_BOOTS] != NULL)
550 if (Player.possessions[O_BOOTS]->usef == I_BOOTS_JUMPING)
551 jumper = 2;
552 if (Player.status[IMMOBILE] > 0) {
553 resetgamestatus(FAST_MOVE);
554 print3("You are unable to move");
555 }
556 else {
557 setgamestatus(SKIP_MONSTERS);
558 mprint("Jump where?");
559 setspot(&x,&y);
560 if (! los_p(Player.x,Player.y,x,y))
561 print3("The way is obstructed.");
562 else if (Player.itemweight > Player.maxweight)
563 print3("You are too burdened to jump anywhere.");
564 else if (distance(x,y,Player.x,Player.y) >
565 max(2,statmod(Player.agi)+2)+jumper)
566 print3("The jump is too far for you.");
567 else if (Level->site[x][y].creature != NULL)
568 print3("You can't jump on another creature.");
569 else if (! p_moveable(x,y))
570 print3("You can't jump there.");
571 else {
572 resetgamestatus(SKIP_MONSTERS);
573 Player.x = x;
574 Player.y = y;
575 if ((! jumper) && (random_range(30) > Player.agi)) {
576 mprint("Oops -- took a tumble.");
577 setgamestatus(SKIP_PLAYER);
578 p_damage((Player.itemweight/250),UNSTOPPABLE,"clumsiness");
579 }
580 p_movefunction(Level->site[Player.x][Player.y].p_locf);
581 if (Current_Environment != E_COUNTRYSIDE)
582 if ((Level->site[Player.x][Player.y].things != NULL) &&
583 (optionp(PICKUP)))
584 pickup();
585 }
586 }
587 }
588
589
590 /* Sets sequence of combat maneuvers. */
tacoptions()591 void tacoptions()
592 {
593 int actionsleft,done,place;
594 char defatt, *attstr, *defstr; /* for the default setting */
595 int draw_again = 1;
596
597 setgamestatus(SKIP_MONSTERS);
598
599 done = FALSE;
600 actionsleft = maneuvers();
601 place = 0;
602 do {
603 if (draw_again) {
604 menuclear();
605 menuprint("Enter a combat maneuvers sequence.\n");
606 menuprint("? for help, ! for default, backspace to start again,\n");
607 menuprint(" RETURN to save sequence\n");
608 showmenu();
609 draw_again = 0;
610 }
611 clearmsg();
612 mprint("Maneuvers Left:");
613 mnumprint(actionsleft);
614 switch(mgetc()) {
615 case '?':
616 combat_help();
617 draw_again = 1;
618 break;
619 case 'a': case 'A':
620 if (actionsleft < 1) print3("No more maneuvers!");
621 else {
622 if (Player.possessions[O_WEAPON_HAND] == NULL) {
623 Player.meleestr[place] = 'C';
624 menuprint("\nPunch:");
625 }
626 else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
627 Player.meleestr[place] = 'T';
628 menuprint("\nThrust:");
629 }
630 else if (Player.possessions[O_WEAPON_HAND]->type == STRIKING) {
631 Player.meleestr[place] = 'C';
632 menuprint("\nStrike:");
633 }
634 else {
635 menuprint("\nCut:");
636 Player.meleestr[place] = 'C';
637 }
638 place++;
639 Player.meleestr[place]=getlocation();
640 place++;
641 actionsleft--;
642 }
643 break;
644 case 'b': case 'B':
645 if (actionsleft<1) print3("No more maneuvers!");
646 else {
647 Player.meleestr[place] = 'B';
648 if (Player.possessions[O_WEAPON_HAND] == NULL)
649 menuprint("\nDodge (from):");
650 else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING)
651 menuprint("\nParry:");
652 else menuprint("\nBlock:");
653 place++;
654 Player.meleestr[place]= getlocation();
655 place++;
656 actionsleft--;
657 }
658 break;
659 case 'l': case 'L':
660 if (actionsleft<2) print3("Not enough maneuvers to lunge!");
661 else {
662 if (Player.possessions[O_WEAPON_HAND] != NULL) {
663 if (Player.possessions[O_WEAPON_HAND]->type != MISSILE) {
664 menuprint("\nLunge:");
665 Player.meleestr[place] = 'L';
666 place++;
667 Player.meleestr[place]=getlocation();
668 place++;
669 actionsleft -= 2;
670 }
671 else {
672 print3("Can't lunge with a missile weapon!");
673 morewait();
674 }
675 }
676 else {
677 print3("Can't lunge without a weapon!");
678 morewait();
679 }
680 }
681 break;
682 case 'r': case 'R':
683 if (actionsleft<2) print3("Not enough maneuvers to riposte!");
684 else {
685 if (Player.possessions[O_WEAPON_HAND] != NULL) {
686 if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
687 Player.meleestr[place++] = 'R';
688 menuprint("\nRiposte:");
689 Player.meleestr[place++]=getlocation();
690 actionsleft -= 2;
691 }
692 else {
693 print3("Can't riposte without a thrusting weapon!");
694 morewait();
695 }
696 }
697 else {
698 print3("Can't riposte without a thrusting weapon!");
699 morewait();
700 }
701 }
702 break;
703 case BACKSPACE:
704 case DELETE:
705 place = 0;
706 actionsleft=maneuvers();
707 draw_again = 1;
708 break;
709 case '!':
710 if (Player.possessions[O_WEAPON_HAND] == NULL) {
711 defatt = 'C';
712 attstr = "Punch";
713 }
714 else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
715 defatt = 'T';
716 attstr = "Thrust";
717 }
718 else if (Player.possessions[O_WEAPON_HAND]->type == STRIKING) {
719 defatt = 'C';
720 attstr = "Strike";
721 }
722 else {
723 defatt = 'C';
724 attstr = "Cut";
725 }
726 if (Player.possessions[O_WEAPON_HAND] == NULL)
727 defstr = "Dodge";
728 else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING)
729 defstr = "Parry";
730 else defstr = "Block";
731 menuclear();
732 menuprint("Enter a combat maneuvers sequence.\n");
733 menuprint("? for help, ! for default, backspace to start again,\n");
734 menuprint(" RETURN to save sequence\n\n");
735 for(place=0;place<maneuvers();place++)
736 if (place&1) { /* every 2nd time around */
737 Player.meleestr[place*2] = 'B';
738 Player.meleestr[(place*2)+1] = 'C';
739 menuprint(defstr);
740 menuprint(" Center.\n");
741 }
742 else {
743 Player.meleestr[place*2] = defatt;
744 Player.meleestr[(place*2)+1] = 'C';
745 menuprint(attstr);
746 menuprint(" Center.\n");
747 }
748 actionsleft = 0;
749 showmenu();
750 Player.meleestr[place*2]='\0';
751 break;
752 case RETURN:
753 case LINEFEED:
754 case ESCAPE:
755 done = TRUE;
756 break;
757 }
758 /* if (actionsleft < 1) morewait(); */ /* FIXED 12/30/98 */
759 } while (! done);
760 xredraw();
761 Player.meleestr[place] = 0;
762 }
763
764
765
766
767 /* Do the Artful Dodger trick */
pickpocket()768 void pickpocket()
769 {
770 int dx,dy,index=0;
771 struct monster *m;
772
773 clearmsg();
774
775 mprint("Pickpocketing --");
776
777 index = getdir();
778
779 if (index == ABORT)
780 setgamestatus(SKIP_MONSTERS);
781 else {
782 dx = Dirs[0][index];
783 dy = Dirs[1][index];
784
785 if ((! inbounds(Player.x+dx, Player.y+dy)) ||
786 (Level->site[Player.x+dx][Player.y+dy].creature == NULL)) {
787 print3("There's nothing there to steal from!!!");
788 setgamestatus(SKIP_MONSTERS);
789 }
790 else {
791 m = Level->site[Player.x+dx][Player.y+dy].creature;
792 if (m->id == GUARD) {
793 mprint("Trying to steal from a guardsman, eh?");
794 mprint("Not a clever idea.");
795 if (Player.cash > 0) {
796 mprint("As a punitive fine, the guard takes all your money.");
797 Player.cash = 0;
798 dataprint();
799 }
800 else {
801 mprint("The guardsman places you under arrest.");
802 morewait();
803 send_to_jail();
804 }
805 }
806 else if (m->possessions == NULL) {
807 mprint("You couldn't find anything worth taking!");
808 mprint("But you managed to annoy it...");
809 m_status_set(m,HOSTILE);
810 }
811 else if (Player.dex*5+Player.rank[THIEVES]*20+random_range(100) >
812 random_range(100)+m->level*20) {
813 mprint("You successfully complete your crime!");
814 mprint("You stole:");
815 mprint(itemid(m->possessions->thing));
816 Player.alignment--;
817 gain_experience(m->level*m->level);
818 gain_item(m->possessions->thing);
819 m->possessions = m->possessions->next;
820 }
821 }
822 }
823 }
824
825
826
rename_player()827 void rename_player()
828 {
829 setgamestatus(SKIP_MONSTERS);
830 clearmsg();
831 mprint("Rename Character: ");
832 strcpy(Str1,msgscanstring());
833 if (strlen(Str1) == 0)
834 mprint(Player.name);
835 else {
836 if (Str1[0] >= 'a' && Str1[0] <= 'z')
837 Str1[0] += 'A' - 'a';
838 strcpy(Player.name, Str1);
839 }
840 sprintf(Str1, "Henceforth, you shall be known as %s", Player.name);
841 print2(Str1);
842 }
843
844
abortshadowform()845 void abortshadowform()
846 {
847 setgamestatus(SKIP_MONSTERS);
848 if (Player.status[SHADOWFORM] && (Player.status[SHADOWFORM]<1000)) {
849 mprint("You abort your spell of Shadow Form.");
850 Player.immunity[NORMAL_DAMAGE]--;
851 Player.immunity[ACID]--;
852 Player.immunity[THEFT]--;
853 Player.immunity[INFECTION]--;
854 mprint("You feel less shadowy now.");
855 Player.status[SHADOWFORM] = 0;
856 }
857 }
858
tunnel()859 void tunnel()
860 {
861 int dir,ox,oy,aux;
862
863 clearmsg();
864 mprint("Tunnel -- ");
865 dir = getdir();
866 if (dir == ABORT)
867 setgamestatus(SKIP_MONSTERS);
868 else {
869 ox = Player.x + Dirs[0][dir];
870 oy = Player.y + Dirs[1][dir];
871 if (loc_statusp(ox,oy,SECRET))
872 mprint("You have no success as yet.");
873 else if (Level->site[ox][oy].locchar != WALL) {
874 print3("You can't tunnel through that!");
875 setgamestatus(SKIP_MONSTERS);
876 }
877 else {
878 aux = Level->site[ox][oy].aux;
879 if (random_range(20)==1){
880 if (Player.possessions[O_WEAPON_HAND] == NULL) {
881 mprint("Ouch! broke a fingernail...");
882 p_damage(Player.str / 6,UNSTOPPABLE,"a broken fingernail");
883 }
884 else if ((Player.possessions[O_WEAPON_HAND]->type == THRUSTING) ||
885 ((Player.possessions[O_WEAPON_HAND]->type != STRIKING) &&
886 (Player.possessions[O_WEAPON_HAND]->fragility <
887 random_range(20)))) {
888 mprint("Clang! Uh oh...");
889 (void) damage_item(Player.possessions[O_WEAPON_HAND]);
890 }
891 else mprint("Your digging implement shows no sign of breaking.");
892 }
893 if (Player.possessions[O_WEAPON_HAND] == NULL) {
894 if ((aux > 0) && ((Player.str/3)+random_range(100) > aux)) {
895 mprint("You carve a tunnel through the stone!");
896 tunnelcheck();
897 Level->site[ox][oy].locchar = RUBBLE;
898 Level->site[ox][oy].p_locf = L_RUBBLE;
899 lset(ox, oy, CHANGED);
900 }
901 else mprint("No joy.");
902 }
903 else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
904 if ((aux > 0) &&
905 (Player.possessions[O_WEAPON_HAND]->dmg*2+random_range(100) >
906 aux)) {
907 mprint("You carve a tunnel through the stone!");
908 tunnelcheck();
909 Level->site[ox][oy].locchar = RUBBLE;
910 Level->site[ox][oy].p_locf = L_RUBBLE;
911 lset(ox, oy, CHANGED);
912 }
913 else mprint("No luck.");
914 }
915 else if ((aux > 0) &&
916 (Player.possessions[O_WEAPON_HAND]->dmg+random_range(100)
917 > aux)) {
918 mprint("You carve a tunnel through the stone!");
919 tunnelcheck();
920 Level->site[ox][oy].locchar = RUBBLE;
921 Level->site[ox][oy].p_locf = L_RUBBLE;
922 lset(ox, oy, CHANGED);
923 }
924 else mprint("You have no success as yet.");
925 }
926 }
927 }
928
929
930
931
hunt(terrain)932 void hunt(terrain)
933 Symbol terrain;
934 {
935 int fertility=0;
936 switch(terrain) {
937 case SWAMP:
938 mprint("You hesitate to hunt for food in the marshy wasteland.");
939 break;
940 case VOLCANO:
941 case CASTLE:
942 case TEMPLE:
943 case CAVES:
944 case STARPEAK:
945 case MAGIC_ISLE:
946 case DRAGONLAIR:
947 mprint("There is nothing alive here (or so it seems)");
948 break;
949 case VILLAGE:
950 case CITY:
951 mprint("You can find no food here; perhaps if you went inside....");
952 break;
953 case ROAD:
954 mprint("You feel it would be a better idea to hunt off the road.");
955 break;
956 case CHAOS_SEA:
957 mprint("Food in the Sea of Chaos? Go on!");
958 break;
959 case DESERT:
960 mprint("You wander off into the trackless desert in search of food...");
961 Time += 100;
962 hourly_check();
963 fertility = 10;
964 break;
965 case JUNGLE:
966 mprint("You search the lush and verdant jungle for game....");
967 Time += 100;
968 hourly_check();
969 fertility = 80;
970 break;
971 case PLAINS:
972 mprint("You set off through the tall grass; the game is afoot.");
973 Time += 100;
974 hourly_check();
975 fertility = 50;
976 break;
977 case TUNDRA:
978 mprint("You blaze a trail through the frozen wasteland....");
979 Time += 100;
980 hourly_check();
981 fertility = 30;
982 break;
983 case FOREST:
984 mprint("You try to follow the many tracks through the forest loam....");
985 Time += 100;
986 hourly_check();
987 fertility = 70;
988 break;
989 case MOUNTAINS: case PASS:
990 mprint("You search the cliff walls looking for something to eat....");
991 Time += 100;
992 hourly_check();
993 fertility = 30;
994 break;
995 case RIVER:
996 mprint("The halcyon river is your hopeful food source...");
997 Time += 100;
998 hourly_check();
999 fertility = 80;
1000 break;
1001 }
1002 if (((Date % 360 < 60) || (Date % 360 > 300)) &&
1003 (terrain != DESERT) &&
1004 (terrain != JUNGLE)) {
1005 mprint("The cold weather impedes your hunt....");
1006 fertility = fertility / 2;
1007 }
1008 if (fertility > random_range(100)) {
1009 mprint("You have an encounter...");
1010 change_environment(E_TACTICAL_MAP);
1011 }
1012 else mprint("Your hunt is fruitless.");
1013 }
1014
dismount_steed()1015 void dismount_steed()
1016 {
1017 pml ml;
1018 if (! gamestatusp(MOUNTED))
1019 print3("You're on foot already!");
1020 else if (Current_Environment == E_COUNTRYSIDE) {
1021 mprint("If you leave your steed here he will wander away!");
1022 mprint("Do it anyway? [yn] ");
1023 if (ynq()=='y') resetgamestatus(MOUNTED);
1024 }
1025 else {
1026 resetgamestatus(MOUNTED);;
1027 ml = ((pml) checkmalloc(sizeof(mltype)));
1028 ml->m = ((pmt) checkmalloc(sizeof(montype)));
1029 *(ml->m) = Monsters[HORSE];
1030 ml->m->x = Player.x;
1031 ml->m->y = Player.y;
1032 ml->m->status = MOBILE+SWIMMING;
1033 ml->next = Level->mlist;
1034 Level->site[Player.x][Player.y].creature = ml->m;
1035 Level->mlist = ml;
1036 }
1037 calc_melee();
1038 }
1039
1040
city_move()1041 void city_move()
1042 {
1043 int site,x=Player.x,y=Player.y,toggle=FALSE;
1044 clearmsg();
1045 if (Current_Environment != E_CITY) {
1046 print3("This command only works in the city!");
1047 setgamestatus(SKIP_MONSTERS);
1048 }
1049 else if (Player.status[IMMOBILE] > 0)
1050 print3("You can't even move!");
1051 else if (hostilemonstersnear()) {
1052 setgamestatus(SKIP_MONSTERS);
1053 print3("You can't move this way with hostile monsters around!");
1054 }
1055 else if (Level->site[Player.x][Player.y].aux == NOCITYMOVE)
1056 print3("You can't use the 'M' command from this location.");
1057 else {
1058 print1("Move to which establishment [? for help, ESCAPE to quit]");
1059 site = parsecitysite();
1060 if (site != ABORT) {
1061 mprint("You're on your way...");
1062 morewait();
1063 while ((x != CitySiteList[site][1]) || (y != CitySiteList[site][2])) {
1064 toggle = ! toggle;
1065 if (toggle) {
1066 Time++;
1067 if (Time % 10 == 0) tenminute_check();
1068 else minute_status_check();
1069 }
1070 x += sign(CitySiteList[site][1] - x);
1071 y += sign(CitySiteList[site][2] - y);
1072 screencheck(y);
1073 omshowcursor(x,y);
1074 }
1075 Player.x = x;
1076 Player.y = y;
1077 screencheck(Player.y);
1078 mprint("Made it!");
1079 drawvision(Player.x, Player.y);
1080 morewait();
1081 p_movefunction(Level->site[x][y].p_locf);
1082 }
1083 }
1084 }
1085
1086
1087
frobgamestatus()1088 void frobgamestatus()
1089 {
1090 char response;
1091 long num;
1092 mprint("Set or Reset or Forget it [s,r,ESCAPE]:");
1093 do response = (char) mcigetc();
1094 while ((response != 'r') && (response != 's') && (response != ESCAPE));
1095 if (response != ESCAPE) {
1096 mprint("Enter log2 of flag:");
1097 num = (int) parsenum();
1098 if (num > -1) {
1099 num = pow2(num);
1100 if (num == CHEATED) {
1101 mprint("Can't alter Wizard flag.");
1102 return;
1103 }
1104 if (response == 's') setgamestatus(num);
1105 else resetgamestatus(num);
1106 mprint("Done....");
1107 }
1108 }
1109 }
1110
1111