OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / src / quest.c
1 /*      SCCS Id: @(#)quest.c    3.4     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 int 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) > 0));
100 }
101
102 STATIC_OVL boolean
103 not_capable()
104 {
105         return((boolean)(u.ulevel < MIN_QUEST_LEVEL));
106 }
107
108 STATIC_OVL int
109 is_pure(talk)
110 boolean talk;
111 {
112     int purity;
113     aligntyp original_alignment = u.ualignbase[A_ORIGINAL];
114
115 #ifdef WIZARD
116     if (wizard && talk) {
117         if (u.ualign.type != original_alignment) {
118             You("are currently %s instead of %s.",
119                 align_str(u.ualign.type), align_str(original_alignment));
120         } else if (u.ualignbase[A_CURRENT] != original_alignment) {
121             You("have converted.");
122         } else if (u.ualign.record < MIN_QUEST_ALIGN) {
123             You("are currently %d and require %d.",
124                 u.ualign.record, MIN_QUEST_ALIGN);
125             if (yn_function("adjust?", (char *)0, 'y') == 'y')
126                 u.ualign.record = MIN_QUEST_ALIGN;
127         }
128     }
129 #endif
130     purity = (u.ualign.record >= MIN_QUEST_ALIGN &&
131               u.ualign.type == original_alignment &&
132               u.ualignbase[A_CURRENT] == original_alignment) ?  1 :
133              (u.ualignbase[A_CURRENT] != original_alignment) ? -1 : 0;
134     return purity;
135 }
136
137 /*
138  * Expell the player to the stairs on the parent of the quest dungeon.
139  *
140  * This assumes that the hero is currently _in_ the quest dungeon and that
141  * there is a single branch to and from it.
142  */
143 STATIC_OVL void
144 expulsion(seal)
145 boolean seal;
146 {
147     branch *br;
148     d_level *dest;
149     struct trap *t;
150     int portal_flag;
151
152     br = dungeon_branch("The Quest");
153     dest = (br->end1.dnum == u.uz.dnum) ? &br->end2 : &br->end1;
154     portal_flag = u.uevent.qexpelled ? 0 :      /* returned via artifact? */
155                   !seal ? 1 : -1;
156     schedule_goto(dest, FALSE, FALSE, portal_flag, (char *)0, (char *)0);
157     if (seal) { /* remove the portal to the quest - sealing it off */
158         int reexpelled = u.uevent.qexpelled;
159         u.uevent.qexpelled = 1;
160         /* Delete the near portal now; the far (main dungeon side)
161            portal will be deleted as part of arrival on that level.
162            If monster movement is in progress, any who haven't moved
163            yet will now miss out on a chance to wander through it... */
164         for (t = ftrap; t; t = t->ntrap)
165             if (t->ttyp == MAGIC_PORTAL) break;
166         if (t) deltrap(t);      /* (display might be briefly out of sync) */
167         else if (!reexpelled) impossible("quest portal already gone?");
168     }
169 }
170
171 /* Either you've returned to quest leader while carrying the quest
172    artifact or you've just thrown it to/at him or her.  If quest
173    completion text hasn't been given yet, give it now.  Otherwise
174    give another message about the character keeping the artifact
175    and using the magic portal to return to the dungeon. */
176 void
177 finish_quest(obj)
178 struct obj *obj;        /* quest artifact; possibly null if carrying Amulet */
179 {
180         struct obj *otmp;
181
182         if (u.uhave.amulet) {   /* unlikely but not impossible */
183             qt_pager(QT_HASAMULET);
184             /* leader IDs the real amulet but ignores any fakes */
185             if ((otmp = carrying(AMULET_OF_YENDOR)) != 0)
186                 fully_identify_obj(otmp);
187         } else {
188             qt_pager(!Qstat(got_thanks) ? QT_OFFEREDIT : QT_OFFEREDIT2);
189             /* should have obtained bell during quest;
190                if not, suggest returning for it now */
191             if ((otmp = carrying(BELL_OF_OPENING)) == 0)
192                 com_pager(5);
193         }
194         Qstat(got_thanks) = TRUE;
195
196         if (obj) {
197             u.uevent.qcompleted = 1;    /* you did it! */
198             /* behave as if leader imparts sufficient info about the
199                quest artifact */
200             fully_identify_obj(obj);
201             update_inventory();
202         }
203 }
204
205 STATIC_OVL void
206 chat_with_leader()
207 {
208 /*      Rule 0: Cheater checks.                                 */
209         if(u.uhave.questart && !Qstat(met_nemesis))
210             Qstat(cheater) = TRUE;
211
212 /*      It is possible for you to get the amulet without completing
213  *      the quest.  If so, try to induce the player to quest.
214  */
215         if(Qstat(got_thanks)) {
216 /*      Rule 1: You've gone back with/without the amulet.       */
217             if(u.uhave.amulet)  finish_quest((struct obj *)0);
218
219 /*      Rule 2: You've gone back before going for the amulet.   */
220             else                qt_pager(QT_POSTHANKS);
221         }
222
223 /*      Rule 3: You've got the artifact and are back to return it. */
224           else if(u.uhave.questart) {
225             struct obj *otmp;
226
227             for (otmp = invent; otmp; otmp = otmp->nobj)
228                 if (is_quest_artifact(otmp)) break;
229
230             finish_quest(otmp);
231
232 /*      Rule 4: You haven't got the artifact yet.       */
233         } else if(Qstat(got_quest)) {
234             qt_pager(rn1(10, QT_ENCOURAGE));
235
236 /*      Rule 5: You aren't yet acceptable - or are you? */
237         } else {
238           if(!Qstat(met_leader)) {
239             qt_pager(QT_FIRSTLEADER);
240             Qstat(met_leader) = TRUE;
241             Qstat(not_ready) = 0;
242           } else qt_pager(QT_NEXTLEADER);
243           /* the quest leader might have passed through the portal into
244              the regular dungeon; none of the remaining make sense there */
245           if (!on_level(&u.uz, &qstart_level)) return;
246
247           if(not_capable()) {
248             qt_pager(QT_BADLEVEL);
249             exercise(A_WIS, TRUE);
250             expulsion(FALSE);
251           } else if(is_pure(TRUE) < 0) {
252             com_pager(QT_BANISHED);
253             expulsion(TRUE);
254           } else if(is_pure(TRUE) == 0) {
255             qt_pager(QT_BADALIGN);
256             if(Qstat(not_ready) == MAX_QUEST_TRIES) {
257               qt_pager(QT_LASTLEADER);
258               expulsion(TRUE);
259             } else {
260               Qstat(not_ready)++;
261               exercise(A_WIS, TRUE);
262               expulsion(FALSE);
263             }
264           } else {      /* You are worthy! */
265             qt_pager(QT_ASSIGNQUEST);
266             exercise(A_WIS, TRUE);
267             Qstat(got_quest) = TRUE;
268           }
269         }
270 }
271
272 void
273 leader_speaks(mtmp)
274         register struct monst *mtmp;
275 {
276         /* maybe you attacked leader? */
277         if(!mtmp->mpeaceful) {
278                 Qstat(pissed_off) = TRUE;
279                 mtmp->mstrategy &= ~STRAT_WAITMASK;     /* end the inaction */
280         }
281         /* the quest leader might have passed through the portal into the
282            regular dungeon; if so, mustn't perform "backwards expulsion" */
283         if (!on_level(&u.uz, &qstart_level)) return;
284
285         if(Qstat(pissed_off)) {
286           qt_pager(QT_LASTLEADER);
287           expulsion(TRUE);
288         } else chat_with_leader();
289 }
290
291 STATIC_OVL void
292 chat_with_nemesis()
293 {
294 /*      The nemesis will do most of the talking, but... */
295         qt_pager(rn1(10, QT_DISCOURAGE));
296         if(!Qstat(met_nemesis)) Qstat(met_nemesis++);
297 }
298
299 void
300 nemesis_speaks()
301 {
302         if(!Qstat(in_battle)) {
303           if(u.uhave.questart) qt_pager(QT_NEMWANTSIT);
304           else if(Qstat(made_goal) == 1 || !Qstat(met_nemesis))
305               qt_pager(QT_FIRSTNEMESIS);
306           else if(Qstat(made_goal) < 4) qt_pager(QT_NEXTNEMESIS);
307           else if(Qstat(made_goal) < 7) qt_pager(QT_OTHERNEMESIS);
308           else if(!rn2(5))      qt_pager(rn1(10, QT_DISCOURAGE));
309           if(Qstat(made_goal) < 7) Qstat(made_goal)++;
310           Qstat(met_nemesis) = TRUE;
311         } else /* he will spit out random maledictions */
312           if(!rn2(5))   qt_pager(rn1(10, QT_DISCOURAGE));
313 }
314
315 STATIC_OVL void
316 chat_with_guardian()
317 {
318 /*      These guys/gals really don't have much to say... */
319         if (u.uhave.questart && Qstat(killed_nemesis))
320             qt_pager(rn1(5, QT_GUARDTALK2));
321         else
322             qt_pager(rn1(5, QT_GUARDTALK));
323 }
324
325 STATIC_OVL void
326 prisoner_speaks (mtmp)
327         register struct monst *mtmp;
328 {
329         if (mtmp->data == &mons[PM_PRISONER] &&
330                         (mtmp->mstrategy & STRAT_WAITMASK)) {
331             /* Awaken the prisoner */
332             if (canseemon(mtmp))
333                 pline("%s speaks:", Monnam(mtmp));
334             verbalize("I'm finally free!");
335             mtmp->mstrategy &= ~STRAT_WAITMASK;
336             mtmp->mpeaceful = 1;
337
338             /* Your god is happy... */
339             adjalign(3);
340
341                 /* ...But the guards are not */
342             (void) angry_guards(FALSE);
343         }
344         return;
345 }
346
347 void
348 quest_chat(mtmp)
349         register struct monst *mtmp;
350 {
351     if (mtmp->m_id == Qstat(leader_m_id)) {
352         chat_with_leader();
353         return;
354     }
355     switch(mtmp->data->msound) {
356             case MS_NEMESIS:    chat_with_nemesis(); break;
357             case MS_GUARDIAN:   chat_with_guardian(); break;
358             default:    impossible("quest_chat: Unknown quest character %s.",
359                                    mon_nam(mtmp));
360         }
361 }
362
363 void
364 quest_talk(mtmp)
365         register struct monst *mtmp;
366 {
367     if (mtmp->m_id == Qstat(leader_m_id)) {
368         leader_speaks(mtmp);
369         return;
370     }
371     switch(mtmp->data->msound) {
372             case MS_NEMESIS:    nemesis_speaks(); break;
373             case MS_DJINNI:     prisoner_speaks(mtmp); break;
374             default:            break;
375         }
376 }
377
378 void
379 quest_stat_check(mtmp)
380         struct monst *mtmp;
381 {
382     if(mtmp->data->msound == MS_NEMESIS)
383         Qstat(in_battle) = (mtmp->mcanmove && !mtmp->msleeping &&
384                             monnear(mtmp, u.ux, u.uy));
385 }
386
387 /*quest.c*/