comparison arogue5/wizard.c @ 63:0ed67132cf10

Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
author elwin
date Thu, 09 Aug 2012 22:58:48 +0000
parents
children c49f7927b0fa
comparison
equal deleted inserted replaced
62:0ef99244acb8 63:0ed67132cf10
1 /*
2 * Special wizard commands (some of which are also non-wizard commands
3 * under strange circumstances)
4 *
5 * Advanced Rogue
6 * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
7 * All rights reserved.
8 *
9 * Based on "Rogue: Exploring the Dungeons of Doom"
10 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
11 * All rights reserved.
12 *
13 * See the file LICENSE.TXT for full copyright and licensing information.
14 */
15
16 #include "curses.h"
17 #include <ctype.h>
18 #include "rogue.h"
19
20
21 /*
22 * create_obj:
23 * Create any object for wizard, scroll, magician, or cleric
24 */
25 create_obj(prompt, which_item, which_type)
26 bool prompt;
27 int which_item, which_type;
28 {
29 reg struct linked_list *item;
30 reg struct object *obj;
31 reg int wh;
32 reg char ch, newitem, newtype = 0, whc, msz, *pt;
33 WINDOW *thiswin;
34
35 thiswin = cw;
36 if (prompt) {
37 bool nogood = TRUE;
38
39 thiswin = hw;
40 wclear(hw);
41 wprintw(hw,"Item\t\t\tKey\n\n");
42 wprintw(hw,"%s\t\t\t%c\n%s\t\t\t%c\n",things[TYP_RING].mi_name,RING,
43 things[TYP_STICK].mi_name,STICK);
44 wprintw(hw,"%s\t\t\t%c\n%s\t\t\t%c\n",things[TYP_POTION].mi_name,POTION,
45 things[TYP_SCROLL].mi_name,SCROLL);
46 wprintw(hw,"%s\t\t\t%c\n%s\t\t\t%c\n",things[TYP_ARMOR].mi_name,ARMOR,
47 things[TYP_WEAPON].mi_name,WEAPON);
48 wprintw(hw,"%s\t%c\n",things[TYP_MM].mi_name,MM);
49 wprintw(hw,"%s\t\t\t%c\n",things[TYP_FOOD].mi_name,FOOD);
50 if (wizard) {
51 wprintw(hw,"%s\t\t%c\n",things[TYP_RELIC].mi_name,RELIC);
52 waddstr(hw,"monster\t\t\tm");
53 }
54 wprintw(hw,"\n\nWhat do you want to create? ");
55 draw(hw);
56 do {
57 ch = wgetch(hw);
58 if (ch == ESCAPE) {
59 restscr(cw);
60 return;
61 }
62 switch (ch) {
63 case RING:
64 case STICK:
65 case POTION:
66 case SCROLL:
67 case ARMOR:
68 case WEAPON:
69 case FOOD:
70 case MM:
71 nogood = FALSE;
72 break;
73 case RELIC:
74 case 'm':
75 if (wizard)
76 nogood = FALSE;
77 break;
78 default:
79 nogood = TRUE;
80 }
81 } while (nogood);
82 newitem = ch;
83 }
84 else
85 newitem = which_item;
86
87 pt = "those";
88 msz = 0;
89 if(newitem == 'm') {
90 makemonster(TRUE); /* make monster and be done with it */
91 return;
92 }
93 if(newitem == GOLD)
94 pt = "gold";
95 /* else if(isatrap(newitem))
96 pt = "traps";
97 */
98 switch(newitem) {
99 case POTION: whc = TYP_POTION; msz = MAXPOTIONS;
100 when SCROLL: whc = TYP_SCROLL; msz = MAXSCROLLS;
101 when WEAPON: whc = TYP_WEAPON; msz = MAXWEAPONS;
102 when ARMOR: whc = TYP_ARMOR; msz = MAXARMORS;
103 when RING: whc = TYP_RING; msz = MAXRINGS;
104 when STICK: whc = TYP_STICK; msz = MAXSTICKS;
105 when MM: whc = TYP_MM; msz = MAXMM;
106 when RELIC: whc = TYP_RELIC; msz = MAXRELIC;
107 when FOOD:
108 whc = TYP_FOOD;
109 msz = MAXFOODS;
110 if (thiswin == hw)
111 restscr(cw);
112 mpos = 0;
113 otherwise:
114 if (thiswin == hw)
115 restscr(cw);
116 mpos = 0;
117 msg("Even wizards can't create %s !!",pt);
118 return;
119 }
120 if(msz == 1) { /* if only one type of item */
121 ch = 'a';
122 }
123 else if (prompt) {
124 register struct magic_item *wmi;
125 char wmn;
126 register int ii;
127 int old_prob;
128
129 mpos = 0;
130 wmi = NULL;
131 wmn = 0;
132 switch(newitem) {
133 case POTION: wmi = &p_magic[0];
134 when SCROLL: wmi = &s_magic[0];
135 when RING: wmi = &r_magic[0];
136 when STICK: wmi = &ws_magic[0];
137 when MM: wmi = &m_magic[0];
138 when RELIC: wmi = &rel_magic[0];
139 when WEAPON: wmn = 1;
140 when ARMOR: wmn = 2;
141 }
142 wclear(hw);
143 thiswin = hw;
144 if (wmi != NULL) {
145 ii = old_prob = 0;
146 while (ii < msz) {
147 if(wmi->mi_prob == old_prob && wizard == FALSE) {
148 msz--; /* can't make a unique item */
149 }
150 else {
151 mvwaddch(hw,ii % 13,ii > 12 ? COLS/2 : 0, ii + 'a');
152 waddstr(hw,") ");
153 waddstr(hw,wmi->mi_name);
154 ii++;
155 }
156 old_prob = wmi->mi_prob;
157 wmi++;
158 }
159 }
160 else if (wmn != 0) {
161 for(ii = 0 ; ii < msz ; ii++) {
162 mvwaddch(hw,ii % 13,ii > 12 ? COLS/2 : 0, ii + 'a');
163 waddstr(hw,") ");
164 if(wmn == 1)
165 waddstr(hw,weaps[ii].w_name);
166 else
167 waddstr(hw,armors[ii].a_name);
168 }
169 }
170 sprintf(prbuf,"Which %s? ",things[whc].mi_name);
171 mvwaddstr(hw,LINES - 1, 0, prbuf);
172 draw(hw);
173 do {
174 ch = wgetch(hw);
175 if (ch == ESCAPE) {
176 restscr(cw);
177 msg("");
178 return;
179 }
180 } until (isalpha(ch));
181 if (thiswin == hw) /* restore screen if need be */
182 restscr(cw);
183 newtype = tolower(ch) - 'a';
184 if(newtype < 0 || newtype >= msz) { /* if an illegal value */
185 mpos = 0;
186 msg("There is no such %s",things[whc].mi_name);
187 return;
188 }
189 }
190 else
191 newtype = which_type;
192 item = new_item(sizeof *obj); /* get some memory */
193 obj = OBJPTR(item);
194 obj->o_type = newitem; /* store the new items */
195 obj->o_mark[0] = '\0';
196 obj->o_which = newtype;
197 obj->o_group = 0;
198 obj->contents = NULL;
199 obj->o_count = 1;
200 obj->o_flags = 0;
201 obj->o_dplus = obj->o_hplus = 0;
202 obj->o_weight = 0;
203 wh = obj->o_which;
204 mpos = 0;
205 if (!wizard) /* users get 0 to +3 */
206 whc = rnd(4);
207 else /* wizard gets to choose */
208 whc = getbless();
209 if (whc < 0)
210 obj->o_flags |= ISCURSED;
211 switch (obj->o_type) {
212 case WEAPON:
213 case ARMOR:
214 if (obj->o_type == WEAPON) {
215 init_weapon(obj, wh);
216 obj->o_hplus += whc;
217 obj->o_dplus += whc;
218 }
219 else { /* armor here */
220 obj->o_weight = armors[wh].a_wght;
221 obj->o_ac = armors[wh].a_class - whc;
222 }
223 when RING:
224 if (whc > 1 && r_magic[wh].mi_bless != 0)
225 obj->o_flags |= ISBLESSED;
226 r_know[wh] = TRUE;
227 switch(wh) {
228 case R_ADDSTR:
229 case R_ADDWISDOM:
230 case R_ADDINTEL:
231 case R_PROTECT:
232 case R_ADDHIT:
233 case R_ADDDAM:
234 case R_DIGEST:
235 obj->o_ac = whc + 1;
236 break;
237 default:
238 obj->o_ac = 0;
239 }
240 obj->o_weight = things[TYP_RING].mi_wght;
241 when MM:
242 if (whc > 1 && m_magic[wh].mi_bless != 0)
243 obj->o_flags |= ISBLESSED;
244 m_know[wh] = TRUE;
245 switch(wh) {
246 case MM_JUG:
247 switch(rnd(9)) {
248 case 0: obj->o_ac = P_PHASE;
249 when 1: obj->o_ac = P_CLEAR;
250 when 2: obj->o_ac = P_SEEINVIS;
251 when 3: obj->o_ac = P_HEALING;
252 when 4: obj->o_ac = P_MFIND;
253 when 5: obj->o_ac = P_TFIND;
254 when 6: obj->o_ac = P_HASTE;
255 when 7: obj->o_ac = P_RESTORE;
256 when 8: obj->o_ac = P_FLY;
257 }
258 when MM_OPEN:
259 case MM_HUNGER:
260 case MM_DRUMS:
261 case MM_DISAPPEAR:
262 case MM_CHOKE:
263 case MM_KEOGHTOM:
264 if (whc < 0)
265 whc = -whc; /* these cannot be negative */
266 obj->o_ac = (whc + 1) * 5;
267 break;
268 when MM_BRACERS:
269 obj->o_ac = whc * 2 + 1;
270 when MM_DISP:
271 obj->o_ac = 2;
272 when MM_PROTECT:
273 obj->o_ac = whc;
274 when MM_SKILLS:
275 if (wizard && whc != 0)
276 obj->o_ac = rnd(4);
277 else
278 obj->o_ac = player.t_ctype;
279 otherwise:
280 obj->o_ac = 0;
281 }
282 obj->o_weight = things[TYP_MM].mi_wght;
283 when STICK:
284 if (whc > 1 && ws_magic[wh].mi_bless != 0)
285 obj->o_flags |= ISBLESSED;
286 ws_know[wh] = TRUE;
287 fix_stick(obj);
288 when SCROLL:
289 if (whc > 1 && s_magic[wh].mi_bless != 0)
290 obj->o_flags |= ISBLESSED;
291 obj->o_weight = things[TYP_SCROLL].mi_wght;
292 s_know[wh] = TRUE;
293 when POTION:
294 if (whc > 1 && p_magic[wh].mi_bless != 0)
295 obj->o_flags |= ISBLESSED;
296 obj->o_weight = things[TYP_POTION].mi_wght;
297 p_know[wh] = TRUE;
298 when RELIC:
299 obj->o_weight = things[TYP_RELIC].mi_wght;
300 }
301 mpos = 0;
302 obj->o_flags |= ISKNOW;
303 if (add_pack(item, FALSE, NULL) == FALSE) {
304 obj->o_pos = hero;
305 fall(item, TRUE);
306 }
307 }
308
309 /*
310 * getbless:
311 * Get a blessing for a wizards object
312 */
313 getbless()
314 {
315 reg char bless;
316
317 msg("Blessing? (+,-,n)");
318 bless = readchar();
319 if (bless == '+')
320 return (rnd(3) + 2);
321 else if (bless == '-')
322 return (-rnd(3) - 1);
323 else
324 return (0);
325 }
326
327 /*
328 * get a non-monster death type
329 */
330 getdeath()
331 {
332 register int i;
333 int which_death;
334 char label[80];
335
336 clear();
337 for (i=0; i<DEATHNUM; i++) {
338 sprintf(label, "[%d] %s", i+1, deaths[i].name);
339 mvaddstr(i+2, 0, label);
340 }
341 mvaddstr(0, 0, "Which death? ");
342 refresh();
343
344 /* Get the death */
345 for (;;) {
346 get_str(label, stdscr);
347 which_death = atoi(label);
348 if ((which_death < 1 || which_death > DEATHNUM)) {
349 mvaddstr(0, 0, "Please enter a number in the displayed range -- ");
350 refresh();
351 }
352 else break;
353 }
354 return(deaths[which_death-1].reason);
355 }
356
357 /*
358 * make a monster for the wizard
359 */
360 makemonster(create)
361 bool create;
362 {
363 register int i;
364 register short which_monst;
365 register int num_monst = NUMMONST, pres_monst=1, num_lines=2*(LINES-3);
366 char monst_name[40];
367
368 /* Print out the monsters */
369 while (num_monst > 0) {
370 register left_limit;
371
372 if (num_monst < num_lines) left_limit = (num_monst+1)/2;
373 else left_limit = num_lines/2;
374
375 wclear(hw);
376 touchwin(hw);
377
378 /* Print left column */
379 wmove(hw, 2, 0);
380 for (i=0; i<left_limit; i++) {
381 sprintf(monst_name, "[%d] %s\n",
382 pres_monst, monsters[pres_monst].m_name);
383 waddstr(hw, monst_name);
384 pres_monst++;
385 }
386
387 /* Print right column */
388 for (i=0; i<left_limit && pres_monst<=NUMMONST; i++) {
389 sprintf(monst_name, "[%d] %s",
390 pres_monst, monsters[pres_monst].m_name);
391 wmove(hw, i+2, COLS/2);
392 waddstr(hw, monst_name);
393 pres_monst++;
394 }
395
396 if ((num_monst -= num_lines) > 0) {
397 mvwaddstr(hw, LINES-1, 0, morestr);
398 draw(hw);
399 wait_for(hw,' ');
400 }
401
402 else {
403 mvwaddstr(hw, 0, 0, "Which monster");
404 if (!terse && create) waddstr(hw, " do you wish to create");
405 waddstr(hw, "? ");
406 draw(hw);
407 }
408 }
409
410 get_monst:
411 get_str(monst_name, hw);
412 which_monst = atoi(monst_name);
413 if ((which_monst < 1 || which_monst > NUMMONST)) {
414 mvwaddstr(hw, 0, 0, "Please enter a number in the displayed range -- ");
415 draw(hw);
416 goto get_monst;
417 }
418 restscr(cw);
419 if (create) {
420 creat_mons (&player, which_monst, TRUE);
421 light(&hero);
422 }
423 touchwin(cw);
424 return(which_monst);
425 }
426
427 /*
428 * passwd:
429 * see if user knows password
430 */
431
432 passwd()
433 {
434 register char *sp, c;
435 char buf[LINELEN];
436
437 msg("Wizard's Password:");
438 mpos = 0;
439 sp = buf;
440 while ((c = readchar()) != '\n' && c != '\r' && c != '\033')
441 if (c == md_killchar())
442 sp = buf;
443 else if (c == md_erasechar() && sp > buf)
444 sp--;
445 else
446 *sp++ = c;
447 if (sp == buf)
448 return FALSE;
449 *sp = '\0';
450 return (strcmp(PASSWD, md_crypt(buf, "Si")) == 0);
451 }
452
453
454 /*
455 * teleport:
456 * Bamf the hero someplace else
457 */
458
459 teleport()
460 {
461 register struct room *new_rp, *old_rp = roomin(&hero);
462 register int rm;
463 coord c;
464
465 c = hero;
466 mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));
467 do
468 {
469 rm = rnd_room();
470 rnd_pos(&rooms[rm], &hero);
471 } until(winat(hero.y, hero.x) == FLOOR);
472 player.t_oldpos = c; /* Save last position */
473
474 /* If hero gets moved, darken old room */
475 new_rp = &rooms[rm];
476 if (old_rp && old_rp != new_rp) {
477 old_rp->r_flags |= FORCEDARK; /* Fake darkness */
478 light(&c);
479 old_rp->r_flags &= ~FORCEDARK; /* Restore light state */
480 }
481
482 /* Darken where we just came from */
483 else if (levtype == MAZELEV) light(&c);
484
485 light(&hero);
486 mvwaddch(cw, hero.y, hero.x, PLAYER);
487
488 /* Reset current room and position */
489 oldrp = new_rp; /* Used in look() */
490 player.t_oldpos = hero;
491
492 /*
493 * turn off ISHELD in case teleportation was done while fighting
494 * something that holds you
495 */
496 if (on(player, ISHELD)) {
497 register struct linked_list *ip, *nip;
498 register struct thing *mp;
499
500 turn_off(player, ISHELD);
501 hold_count = 0;
502 for (ip = mlist; ip; ip = nip) {
503 mp = THINGPTR(ip);
504 nip = next(ip);
505 if (on(*mp, DIDHOLD)) {
506 turn_off(*mp, DIDHOLD);
507 turn_on(*mp, CANHOLD);
508 }
509 turn_off(*mp, DIDSUFFOCATE); /* Suffocation -- see below */
510 }
511 }
512
513 /* Make sure player does not suffocate */
514 extinguish(suffocate);
515
516 count = 0;
517 running = FALSE;
518 md_flushinp();
519 return rm;
520 }
521
522 /*
523 * whatis:
524 * What a certin object is
525 */
526
527 whatis(what)
528 struct linked_list *what;
529 {
530 register struct object *obj;
531 register struct linked_list *item;
532
533 if (what == NULL) { /* do we need to ask which one? */
534 if ((item = get_item(pack, "identify", IDENTABLE)) == NULL)
535 return;
536 }
537 else
538 item = what;
539 obj = OBJPTR(item);
540 switch (obj->o_type) {
541 case SCROLL:
542 s_know[obj->o_which] = TRUE;
543 if (s_guess[obj->o_which]) {
544 free(s_guess[obj->o_which]);
545 s_guess[obj->o_which] = NULL;
546 }
547 when POTION:
548 p_know[obj->o_which] = TRUE;
549 if (p_guess[obj->o_which]) {
550 free(p_guess[obj->o_which]);
551 p_guess[obj->o_which] = NULL;
552 }
553 when STICK:
554 ws_know[obj->o_which] = TRUE;
555 if (ws_guess[obj->o_which]) {
556 free(ws_guess[obj->o_which]);
557 ws_guess[obj->o_which] = NULL;
558 }
559 when RING:
560 r_know[obj->o_which] = TRUE;
561 if (r_guess[obj->o_which]) {
562 free(r_guess[obj->o_which]);
563 r_guess[obj->o_which] = NULL;
564 }
565 when MM:
566 /* If it's an identified jug, identify its potion */
567 if (obj->o_which == MM_JUG && (obj->o_flags & ISKNOW)) {
568 if (obj->o_ac != JUG_EMPTY)
569 p_know[obj->o_ac] = TRUE;
570 break;
571 }
572
573 m_know[obj->o_which] = TRUE;
574 if (m_guess[obj->o_which]) {
575 free(m_guess[obj->o_which]);
576 m_guess[obj->o_which] = NULL;
577 }
578 otherwise:
579 break;
580 }
581 obj->o_flags |= ISKNOW;
582 if (what == NULL)
583 msg(inv_name(obj, FALSE));
584 }
585