1    | /*	SCCS Id: @(#)quest.c	3.3	2000/05/05	*/
2    | /*	Copyright 1991, M. Stephenson		  */
3    | /* NetHack may be freely redistributed.  See license for details. */
4    | 
5    | #include "hack.h"
6    | 
7    | /*  quest dungeon branch routines. */
8    | 
9    | #include "quest.h"
10   | #include "qtext.h"
11   | 
12   | #define Not_firsttime	(on_level(&u.uz0, &u.uz))
13   | #define Qstat(x)	(quest_status.x)
14   | 
15   | STATIC_DCL void NDECL(on_start);
16   | STATIC_DCL void NDECL(on_locate);
17   | STATIC_DCL void NDECL(on_goal);
18   | STATIC_DCL boolean NDECL(not_capable);
19   | STATIC_DCL boolean FDECL(is_pure, (BOOLEAN_P));
20   | STATIC_DCL void FDECL(expulsion, (BOOLEAN_P));
21   | STATIC_DCL void NDECL(chat_with_leader);
22   | STATIC_DCL void NDECL(chat_with_nemesis);
23   | STATIC_DCL void NDECL(chat_with_guardian);
24   | STATIC_DCL void FDECL(prisoner_speaks, (struct monst *));
25   | 
26   | 
27   | STATIC_OVL void
28   | on_start()
29   | {
30   |   if(!Qstat(first_start)) {
31   |     qt_pager(QT_FIRSTTIME);
32   |     Qstat(first_start) = TRUE;
33   |   } else if((u.uz0.dnum != u.uz.dnum) || (u.uz0.dlevel < u.uz.dlevel)) {
34   |     if(Qstat(not_ready) <= 2) qt_pager(QT_NEXTTIME);
35   |     else	qt_pager(QT_OTHERTIME);
36   |   }
37   | }
38   | 
39   | STATIC_OVL void
40   | on_locate()
41   | {
42   |   if(!Qstat(first_locate)) {
43   |     qt_pager(QT_FIRSTLOCATE);
44   |     Qstat(first_locate) = TRUE;
45   |   } else if(u.uz0.dlevel < u.uz.dlevel && !Qstat(killed_nemesis))
46   | 	qt_pager(QT_NEXTLOCATE);
47   | }
48   | 
49   | STATIC_OVL void
50   | on_goal()
51   | {
52   |   if (Qstat(killed_nemesis)) {
53   |     return;
54   |   } else if (!Qstat(made_goal)) {
55   |     qt_pager(QT_FIRSTGOAL);
56   |     Qstat(made_goal) = 1;
57   |   } else {
58   |     qt_pager(QT_NEXTGOAL);
59   |     if(Qstat(made_goal) < 7) Qstat(made_goal)++;
60   |   }
61   | }
62   | 
63   | void
64   | onquest()
65   | {
66   | 	if(u.uevent.qcompleted || Not_firsttime) return;
67   | 	if(!Is_special(&u.uz)) return;
68   | 
69   | 	if(Is_qstart(&u.uz)) on_start();
70   | 	else if(Is_qlocate(&u.uz) && u.uz.dlevel > u.uz0.dlevel) on_locate();
71   | 	else if(Is_nemesis(&u.uz)) on_goal();
72   | 	return;
73   | }
74   | 
75   | void
76   | nemdead()
77   | {
78   | 	if(!Qstat(killed_nemesis)) {
79   | 	    Qstat(killed_nemesis) = TRUE;
80   | 	    qt_pager(QT_KILLEDNEM);
81   | 	}
82   | }
83   | 
84   | void
85   | artitouch()
86   | {
87   | 	if(!Qstat(touched_artifact)) {
88   | 	    Qstat(touched_artifact) = TRUE;
89   | 	    qt_pager(QT_GOTIT);
90   | 	    exercise(A_WIS, TRUE);
91   | 	}
92   | }
93   | 
94   | /* external hook for do.c (level change check) */
95   | boolean
96   | ok_to_quest()
97   | {
98   | 	return((boolean)((Qstat(got_quest) || Qstat(got_thanks)))
99   | 			&& is_pure(FALSE));
100  | }
101  | 
102  | STATIC_OVL boolean
103  | not_capable()
104  | {
105  | 	return((boolean)(u.ulevel < MIN_QUEST_LEVEL));
106  | }
107  | 
108  | STATIC_OVL boolean
109  | is_pure(talk)
110  | boolean talk;
111  | {
112  |     aligntyp original_alignment = u.ualignbase[A_ORIGINAL];
113  | 
114  | #ifdef WIZARD
115  |     if (wizard && talk) {
116  | 	if (u.ualign.type != original_alignment) {
117  | 	    You("are currently %s instead of %s.",
118  | 		align_str(u.ualign.type), align_str(original_alignment));
119  | 	} else if (u.ualignbase[A_CURRENT] != original_alignment) {
120  | 	    You("have converted.");
121  | 	} else if (u.ualign.record < MIN_QUEST_ALIGN) {
122  | 	    You("are currently %d and require %d.",
123  | 		u.ualign.record, MIN_QUEST_ALIGN);
124  | 	    if (yn_function("adjust?", (char *)0, 'y') == 'y')
125  | 		u.ualign.record = MIN_QUEST_ALIGN;
126  | 	}
127  |     }
128  | #endif
129  |     return (boolean)(u.ualign.record >= MIN_QUEST_ALIGN &&
130  | 		     u.ualign.type == original_alignment &&
131  | 		     u.ualignbase[A_CURRENT] == original_alignment);
132  | }
133  | 
134  | /*
135  |  * Expell the player to the stairs on the parent of the quest dungeon.
136  |  *
137  |  * This assumes that the hero is currently _in_ the quest dungeon and that
138  |  * there is a single branch to and from it.
139  |  */
140  | STATIC_OVL void
141  | expulsion(seal)
142  | boolean seal;
143  | {
144  |     branch *br;
145  |     d_level *dest;
146  |     struct trap *t;
147  |     int portal_flag;
148  | 
149  |     br = dungeon_branch("The Quest");
150  |     dest = (br->end1.dnum == u.uz.dnum) ? &br->end2 : &br->end1;
151  |     portal_flag = u.uevent.qexpelled ? 0 :	/* returned via artifact? */
152  | 		  !seal ? 1 : -1;
153  |     schedule_goto(dest, FALSE, FALSE, portal_flag, (char *)0, (char *)0);
154  |     if (seal) {	/* remove the portal to the quest - sealing it off */
155  | 	u.uevent.qexpelled = 1;
156  | 	/* Delete the near portal now; the far (main dungeon side)
157  | 	   portal will be deleted as part of arrival on that level.
158  | 	   If monster movement is in progress, any who haven't moved
159  | 	   yet will now miss out on a chance to wander through it... */
160  | 	for (t = ftrap; t; t = t->ntrap)
161  | 	    if (t->ttyp == MAGIC_PORTAL) break;
162  | 	if (t) deltrap(t);	/* (display might be briefly out of sync) */
163  | 	else impossible("quest portal already gone?");
164  |     }
165  | }
166  | 
167  | /* Either you've returned to quest leader while carrying the quest
168  |    artifact or you've just thrown it to/at him or her.  If quest
169  |    completion text hasn't been given yet, give it now.  Otherwise
170  |    give another message about the character keeping the artifact
171  |    and using the magic portal to return to the dungeon. */
172  | void
173  | finish_quest(obj)
174  | struct obj *obj;	/* quest artifact; possibly null if carrying Amulet */
175  | {
176  | 	struct obj *otmp;
177  | 
178  | 	if (u.uhave.amulet) {	/* unlikely but not impossible */
179  | 	    qt_pager(QT_HASAMULET);
180  | 	    /* leader IDs the real amulet but ignores any fakes */
181  | 	    if ((otmp = carrying(AMULET_OF_YENDOR)) != 0)
182  | 		fully_identify_obj(otmp);
183  | 	} else {
184  | 	    qt_pager(!Qstat(got_thanks) ? QT_OFFEREDIT : QT_OFFEREDIT2);
185  | 	    /* should have obtained bell during quest;
186  | 	       if not, suggest returning for it now */
187  | 	    if ((otmp = carrying(BELL_OF_OPENING)) == 0)
188  | 		com_pager(5);
189  | 	}
190  | 	Qstat(got_thanks) = TRUE;
191  | 
192  | 	if (obj) {
193  | 	    u.uevent.qcompleted = 1;	/* you did it! */
194  | 	    /* behave as if leader imparts sufficient info about the
195  | 	       quest artifact */
196  | 	    fully_identify_obj(obj);
197  | 	}
198  | }
199  | 
200  | STATIC_OVL void
201  | chat_with_leader()
202  | {
203  | /*	Rule 0:	Cheater checks.					*/
204  | 	if(u.uhave.questart && !Qstat(met_nemesis))
205  | 	    Qstat(cheater) = TRUE;
206  | 
207  | /*	It is possible for you to get the amulet without completing
208  |  *	the quest.  If so, try to induce the player to quest.
209  |  */
210  | 	if(Qstat(got_thanks)) {
211  | /*	Rule 1:	You've gone back with/without the amulet.	*/
212  | 	    if(u.uhave.amulet)	finish_quest((struct obj *)0);
213  | 
214  | /*	Rule 2:	You've gone back before going for the amulet.	*/
215  | 	    else		qt_pager(QT_POSTHANKS);
216  | 	}
217  | 
218  | /*	Rule 3: You've got the artifact and are back to return it. */
219  | 	  else if(u.uhave.questart) {
220  | 	    struct obj *otmp;
221  | 
222  | 	    for (otmp = invent; otmp; otmp = otmp->nobj)
223  | 		if (is_quest_artifact(otmp)) break;
224  | 
225  | 	    finish_quest(otmp);
226  | 
227  | /*	Rule 4: You haven't got the artifact yet.	*/
228  | 	} else if(Qstat(got_quest)) {
229  | 	    qt_pager(rn1(10, QT_ENCOURAGE));
230  | 
231  | /*	Rule 5: You aren't yet acceptable - or are you? */
232  | 	} else {
233  | 	  if(!Qstat(met_leader)) {
234  | 	    qt_pager(QT_FIRSTLEADER);
235  | 	    Qstat(met_leader) = TRUE;
236  | 	    Qstat(not_ready) = 0;
237  | 	  } else qt_pager(QT_NEXTLEADER);
238  | 	  /* the quest leader might have passed through the portal into
239  | 	     the regular dungeon; none of the remaining make sense there */
240  | 	  if (!on_level(&u.uz, &qstart_level)) return;
241  | 
242  | 	  if(not_capable()) {
243  | 	    qt_pager(QT_BADLEVEL);
244  | 	    exercise(A_WIS, TRUE);
245  | 	    expulsion(FALSE);
246  | 	  } else if(!is_pure(TRUE)) {
247  | 	    qt_pager(QT_BADALIGN);
248  | 	    if(Qstat(not_ready) == MAX_QUEST_TRIES) {
249  | 	      qt_pager(QT_LASTLEADER);
250  | 	      expulsion(TRUE);
251  | 	    } else {
252  | 	      Qstat(not_ready)++;
253  | 	      exercise(A_WIS, TRUE);
254  | 	      expulsion(FALSE);
255  | 	    }
256  | 	  } else {	/* You are worthy! */
257  | 	    qt_pager(QT_ASSIGNQUEST);
258  | 	    exercise(A_WIS, TRUE);
259  | 	    Qstat(got_quest) = TRUE;
260  | 	  }
261  | 	}
262  | }
263  | 
264  | void
265  | leader_speaks(mtmp)
266  | 	register struct monst *mtmp;
267  | {
268  | 	/* maybe you attacked leader? */
269  | 	if(!mtmp->mpeaceful) {
270  | 		Qstat(pissed_off) = TRUE;
271  | 		mtmp->mstrategy &= ~STRAT_WAITMASK;	/* end the inaction */
272  | 	}
273  | 	/* the quest leader might have passed through the portal into the
274  | 	   regular dungeon; if so, mustn't perform "backwards expulsion" */
275  | 	if (!on_level(&u.uz, &qstart_level)) return;
276  | 
277  | 	if(Qstat(pissed_off)) {
278  | 	  qt_pager(QT_LASTLEADER);
279  | 	  expulsion(TRUE);
280  | 	} else chat_with_leader();
281  | }
282  | 
283  | STATIC_OVL void
284  | chat_with_nemesis()
285  | {
286  | /*	The nemesis will do most of the talking, but... */
287  | 	qt_pager(rn1(10, QT_DISCOURAGE));
288  | 	if(!Qstat(met_nemesis)) Qstat(met_nemesis++);
289  | }
290  | 
291  | void
292  | nemesis_speaks()
293  | {
294  | 	if(!Qstat(in_battle)) {
295  | 	  if(u.uhave.questart) qt_pager(QT_NEMWANTSIT);
296  | 	  else if(Qstat(made_goal) == 1) qt_pager(QT_FIRSTNEMESIS);
297  | 	  else if(Qstat(made_goal) < 4) qt_pager(QT_NEXTNEMESIS);
298  | 	  else if(Qstat(made_goal) < 7) qt_pager(QT_OTHERNEMESIS);
299  | 	  else if(!rn2(5))	qt_pager(rn1(10, QT_DISCOURAGE));
300  | 	  if(Qstat(made_goal) < 7) Qstat(made_goal)++;
301  | 	  Qstat(met_nemesis) = TRUE;
302  | 	} else /* he will spit out random maledictions */
303  | 	  if(!rn2(5))	qt_pager(rn1(10, QT_DISCOURAGE));
304  | }
305  | 
306  | STATIC_OVL void
307  | chat_with_guardian()
308  | {
309  | /*	These guys/gals really don't have much to say... */
310  | 	qt_pager(rn1(5, QT_GUARDTALK));
311  | }
312  | 
313  | STATIC_OVL void
314  | prisoner_speaks (mtmp)
315  | 	register struct monst *mtmp;
316  | {
317  | 	if (mtmp->data == &mons[PM_PRISONER] &&
318  | 			(mtmp->mstrategy & STRAT_WAITMASK)) {
319  | 	    /* Awaken the prisoner */
320  | 	    if (canseemon(mtmp))
321  | 	    	pline("%s speaks:", Monnam(mtmp));
322  | 	    verbalize("I'm finally free!");
323  | 	    mtmp->mstrategy &= ~STRAT_WAITMASK;
324  | 	    mtmp->mpeaceful = 1;
325  | 
326  | 	    /* Your god is happy... */
327  | 	    adjalign(3);
328  | 
329  | 		/* ...But the guards are not */
330  | 	    (void) angry_guards(FALSE);
331  | 	}
332  | 	return;
333  | }
334  | 
335  | void
336  | quest_chat(mtmp)
337  | 	register struct monst *mtmp;
338  | {
339  |     switch(mtmp->data->msound) {
340  | 	    case MS_LEADER:	chat_with_leader(); break;
341  | 	    case MS_NEMESIS:	chat_with_nemesis(); break;
342  | 	    case MS_GUARDIAN:	chat_with_guardian(); break;
343  | 	    default:	impossible("quest_chat: Unknown quest character %s.",
344  | 				   mon_nam(mtmp));
345  | 	}
346  | }
347  | 
348  | void
349  | quest_talk(mtmp)
350  | 	register struct monst *mtmp;
351  | {
352  |     switch(mtmp->data->msound) {
353  | 	    case MS_LEADER:	leader_speaks(mtmp); break;
354  | 	    case MS_NEMESIS:	nemesis_speaks(); break;
355  | 	    case MS_DJINNI:	prisoner_speaks(mtmp); break;
356  | 	    default:		break;
357  | 	}
358  | }
359  | 
360  | void
361  | quest_stat_check(mtmp)
362  | 	struct monst *mtmp;
363  | {
364  |     if(mtmp->data->msound == MS_NEMESIS)
365  | 	Qstat(in_battle) = (mtmp->mcanmove && !mtmp->msleeping &&
366  | 			    monnear(mtmp, u.ux, u.uy));
367  | }
368  | 
369  | /*quest.c*/