Blindfold removal fix
[slashemextended.git] / src / quest.c
blob10cb12308ecf925298ca2d0aa39e20370096eecf
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. */
5 #include "hack.h"
7 /* quest dungeon branch routines. */
9 #include "quest.h"
10 #include "qtext.h"
12 #define Not_firsttime (on_level(&u.uz0, &u.uz))
13 #define Qstat(x) (quest_status.x)
15 STATIC_DCL void on_start(void);
16 STATIC_DCL void on_locate(void);
17 STATIC_DCL void on_goal(void);
18 STATIC_DCL boolean not_capable(void);
19 STATIC_DCL int is_pure(BOOLEAN_P);
20 STATIC_DCL void expulsion(BOOLEAN_P);
21 STATIC_DCL void chat_with_leader(void);
22 STATIC_DCL void chat_with_nemesis(void);
23 STATIC_DCL void chat_with_guardian(void);
24 STATIC_DCL void prisoner_speaks(struct monst *);
27 STATIC_OVL void
28 on_start()
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);
39 STATIC_OVL void
40 on_locate()
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);
49 STATIC_OVL void
50 on_goal()
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)++;
63 void
64 onquest()
66 if(u.uevent.qcompleted || Not_firsttime) return;
67 if(!Is_special(&u.uz)) return;
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;
75 void
76 nemdead()
78 if(!Qstat(killed_nemesis)) {
79 Qstat(killed_nemesis) = TRUE;
80 qt_pager(QT_KILLEDNEM);
82 if (!Race_if(PM_BABYLONIAN)) {
83 u.weapon_slots += 1;
84 pline("As a bonus, you gain an additional skill slot!");
87 /* quest-specific artifacts of all roles can randomly generate now; note that this doesn't mean the actual QAs,
88 * but rather special artifacts that are placed somewhere on a specific quest --Amy
89 * also, if you've killed the nemesis, then your own quest artifact may generate randomly */
90 de_energise_artifact(ART_PROCOMFORT_SUPER);
91 de_energise_artifact((unsigned int) urole.questarti);
93 if (achieveX.completed_rivalquest) {
94 int quartinum = ART_ORB_OF_DETECTION;
95 while (quartinum <= ART_PENUMBRAL_LASSO) {
96 de_energise_artifact(quartinum);
97 quartinum++;
101 if (Role_if(PM_PRACTICANT) || isbeacher) {
102 You("managed to overthrow %s's reign of terror!!!", noroelaname());
103 if (u.practicantcash) {
104 You("rummage through %s's possessions and find the box in which she kept the money she stole from you. The bitch spent some of it, but you take the remaining %d zorkmids and pocket them.", noroelaname(), u.practicantcash);
105 u.ugold += u.practicantcash;
106 u.practicantcash = 0;
112 void
113 artitouch()
115 if(!Qstat(touched_artifact)) {
116 Qstat(touched_artifact) = TRUE;
117 qt_pager(QT_GOTIT);
119 if (!Race_if(PM_BABYLONIAN)) {
120 u.weapon_slots += 1;
121 pline("As a bonus, you gain an additional skill slot!");
124 exercise(A_WIS, TRUE);
128 /* external hook for do.c (level change check) */
129 boolean
130 ok_to_quest()
132 return((boolean)((Qstat(got_quest) || Qstat(got_thanks)))
133 && (is_pure(FALSE) > 0));
136 STATIC_OVL boolean
137 not_capable()
139 return((boolean)(u.ulevel < MIN_QUEST_LEVEL));
142 STATIC_OVL int
143 is_pure(talk)
144 boolean talk;
146 int purity;
147 aligntyp original_alignment = u.ualignbase[A_ORIGINAL];
149 #ifdef WIZARD
150 if (wizard && talk) {
151 if (u.ualign.type != original_alignment) {
152 You("are currently %s instead of %s.",
153 align_str(u.ualign.type), align_str(original_alignment));
154 } else if (u.ualignbase[A_CURRENT] != original_alignment) {
155 You("have converted.");
156 } else if (u.ualign.record < MIN_QUEST_ALIGN) {
157 You("are currently %d and require %d.",
158 u.ualign.record, MIN_QUEST_ALIGN);
159 if (yn_function("adjust?", (char *)0, 'y') == 'y')
160 u.ualign.record = MIN_QUEST_ALIGN;
163 #endif
164 purity = (u.ualign.record >= MIN_QUEST_ALIGN &&
165 u.ualign.type == original_alignment &&
166 u.ualignbase[A_CURRENT] == original_alignment) ? 1 :
167 (u.ualignbase[A_CURRENT] != original_alignment) ? -1 : 0;
168 return purity;
172 * Expell the player to the stairs on the parent of the quest dungeon.
174 * This assumes that the hero is currently _in_ the quest dungeon and that
175 * there is a single branch to and from it.
177 STATIC_OVL void
178 expulsion(seal)
179 boolean seal;
181 branch *br;
182 d_level *dest;
183 struct trap *t;
184 int portal_flag;
186 br = dungeon_branch("The Quest");
187 dest = (br->end1.dnum == u.uz.dnum) ? &br->end2 : &br->end1;
188 portal_flag = u.uevent.qexpelled ? 0 : /* returned via artifact? */
189 !seal ? 1 : -1;
190 schedule_goto(dest, FALSE, FALSE, portal_flag, (char *)0, (char *)0);
191 if (seal) { /* remove the portal to the quest - sealing it off */
192 int reexpelled = u.uevent.qexpelled;
193 u.uevent.qexpelled = 1;
194 /* Delete the near portal now; the far (main dungeon side)
195 portal will be deleted as part of arrival on that level.
196 If monster movement is in progress, any who haven't moved
197 yet will now miss out on a chance to wander through it... */
198 for (t = ftrap; t; t = t->ntrap)
199 if (t->ttyp == MAGIC_PORTAL) break;
200 if (t) deltrap(t); /* (display might be briefly out of sync) */
201 else if (!reexpelled) impossible("quest portal already gone?");
205 /* Either you've returned to quest leader while carrying the quest
206 artifact or you've just thrown it to/at him or her. If quest
207 completion text hasn't been given yet, give it now. Otherwise
208 give another message about the character keeping the artifact
209 and using the magic portal to return to the dungeon. */
210 void
211 finish_quest(obj)
212 struct obj *obj; /* quest artifact; possibly null if carrying Amulet */
214 struct obj *otmp;
216 if (u.uhave.amulet) { /* unlikely but not impossible */
217 qt_pager(QT_HASAMULET);
218 /* leader IDs the real amulet but ignores any fakes */
219 if ((otmp = carrying(AMULET_OF_YENDOR)) != 0)
220 fully_identify_obj(otmp);
221 makeknown(otmp->otyp);
223 if (!Qstat(amulet_bonus)) {
224 Qstat(amulet_bonus) = TRUE;
225 u.weapon_slots += 2;
226 pline("As a reward, you gain 2 extra skill slots!");
228 if (u.amuletcompletelyimbued && !Qstat(amulet_bonus2)) {
229 Qstat(amulet_bonus2) = TRUE;
230 u.weapon_slots += 3;
231 pline("As an additional reward, you gain 3 extra skill slots!");
234 } else {
235 qt_pager(!Qstat(got_thanks) ? QT_OFFEREDIT : QT_OFFEREDIT2);
236 /* should have obtained bell during quest;
237 if not, suggest returning for it now */
238 if ((otmp = carrying(BELL_OF_OPENING)) == 0)
239 /*com_pager(5)*/qt_pager(QT_SILVERBELL); /* have individual messages for certain classes --Amy */
242 if (!Qstat(got_thanks)) {
243 Qstat(got_thanks) = TRUE; /* filthy hangup cheater */
244 u.weapon_slots += 2;
245 pline("As a reward, you gain 2 extra skill slots!");
248 Qstat(got_thanks) = TRUE;
250 if (obj) {
251 u.uevent.qcompleted = 1; /* you did it! */
252 /* behave as if leader imparts sufficient info about the
253 quest artifact */
254 fully_identify_obj(obj);
255 makeknown(obj->otyp);
256 update_inventory();
260 STATIC_OVL void
261 chat_with_leader()
263 register struct monst *mon;
265 /* Rule 0: Cheater checks. */
266 if(u.uhave.questart && !Qstat(met_nemesis))
267 Qstat(cheater) = TRUE;
269 /* It is possible for you to get the amulet without completing
270 * the quest. If so, try to induce the player to quest.
272 if(Qstat(got_thanks)) {
273 /* Rule 1: You've gone back with/without the amulet. */
274 if(u.uhave.amulet) finish_quest((struct obj *)0);
276 /* Rule 2: You've gone back before going for the amulet. */
277 else qt_pager(QT_POSTHANKS);
280 /* Rule 3: You've got the artifact and are back to return it. */
281 else if(u.uhave.questart) {
282 struct obj *otmp;
284 for (otmp = invent; otmp; otmp = otmp->nobj)
285 if (is_quest_artifact(otmp)) break;
287 finish_quest(otmp);
289 /* Rule 4: You haven't got the artifact yet. */
290 } else if(Qstat(got_quest)) {
291 qt_pager(rn1(10, QT_ENCOURAGE));
293 /* Rule 5: You aren't yet acceptable - or are you? */
294 } else {
295 if(!Qstat(met_leader)) {
296 qt_pager(QT_FIRSTLEADER);
297 Qstat(met_leader) = TRUE;
298 Qstat(not_ready) = 0;
299 } else if (Qstat(not_ready) < MAX_QUEST_TRIES - 1) qt_pager(QT_NEXTLEADER);
300 else qt_pager(QT_OTHERLEADER);
301 /* the quest leader might have passed through the portal into
302 the regular dungeon; none of the remaining make sense there */
303 if (!on_level(&u.uz, &qstart_level)) return;
305 if(not_capable()) {
306 qt_pager(QT_BADLEVEL);
307 exercise(A_WIS, TRUE);
308 expulsion(FALSE);
309 } else if(is_pure(TRUE) < 0) {
310 /*com_pager(QT_BANISHED);*/
311 qt_pager(QT_HERETIC); /* gotta have realistic dialogue for all quest leaders! --Amy */
313 /* turn them all hostile --Amy */
315 for (mon = fmon; mon; mon = mon->nmon)
316 if (!DEADMONSTER(mon) && (mon->data->msound == MS_GUARDIAN || mon->data->msound == MS_LEADER) && mon->mpeaceful) {
317 mon->mpeaceful = 0;
319 Qstat(pissed_off) = TRUE;
321 /* expulsion(TRUE); */
322 /* expulsion(FALSE); */ /* prevent infinite loops for converted heroes */
323 } else if(is_pure(TRUE) == 0) {
324 qt_pager(QT_BADALIGN);
325 if(Qstat(not_ready) == MAX_QUEST_TRIES) {
326 qt_pager(QT_LASTLEADER);
327 /* expulsion(TRUE); */
328 expulsion(FALSE);
329 } else {
330 Qstat(not_ready)++;
331 exercise(A_WIS, TRUE);
332 expulsion(FALSE);
334 } else { /* You are worthy! */
335 qt_pager(QT_ASSIGNQUEST);
336 exercise(A_WIS, TRUE);
337 Qstat(got_quest) = TRUE;
342 void
343 leader_speaks(mtmp)
344 register struct monst *mtmp;
346 /* maybe you attacked leader? */
347 if(!mtmp->mpeaceful) {
348 Qstat(pissed_off) = TRUE;
349 mtmp->mstrategy &= ~STRAT_WAITMASK; /* end the inaction */
351 /* the quest leader might have passed through the portal into the
352 regular dungeon; if so, mustn't perform "backwards expulsion" */
353 if (!on_level(&u.uz, &qstart_level)) return;
355 if(Qstat(pissed_off)) {
356 qt_pager(QT_LASTLEADER); /* remove expulsion to prevent infinite loops --Amy */
357 /* expulsion(TRUE); */ /* since the quest cannot be sealed anymore to prevent the game from */
358 /* expulsion(FALSE); */ /* becoming unwinnable - whoever had that stupid idea anyway?! */
359 } else chat_with_leader();
362 STATIC_OVL void
363 chat_with_nemesis()
365 /* The nemesis will do most of the talking, but... */
366 qt_pager(rn1(10, QT_DISCOURAGE));
367 if(!Qstat(met_nemesis)) Qstat(met_nemesis++);
370 void
371 nemesis_speaks()
373 if(!Qstat(in_battle)) {
374 if(u.uhave.questart) qt_pager(QT_NEMWANTSIT);
375 else if(Qstat(made_goal) == 1 || !Qstat(met_nemesis))
376 qt_pager(QT_FIRSTNEMESIS);
377 else if(Qstat(made_goal) < 4) qt_pager(QT_NEXTNEMESIS);
378 else if(Qstat(made_goal) < 7) qt_pager(QT_OTHERNEMESIS);
379 else if(!rn2(5)) qt_pager(rn1(10, QT_DISCOURAGE));
380 if(Qstat(made_goal) < 7) Qstat(made_goal)++;
381 Qstat(met_nemesis) = TRUE;
382 } else /* he will spit out random maledictions */
383 if(!rn2(5)) qt_pager(rn1(10, QT_DISCOURAGE));
386 STATIC_OVL void
387 chat_with_guardian()
389 /* These guys/gals really don't have much to say... */
390 if (u.uhave.questart && Qstat(killed_nemesis))
391 qt_pager(rn1(5, QT_GUARDTALK2));
392 else
393 qt_pager(rn1(5, QT_GUARDTALK));
396 STATIC_OVL void
397 prisoner_speaks (mtmp)
398 register struct monst *mtmp;
400 if ((mtmp->data == &mons[PM_PRISONER] || mtmp->data == &mons[PM_CASTLE_PRISONER] || mtmp->data == &mons[PM_YLVA_PRISONER] || mtmp->data == &mons[PM_YOUR_BROTHER] || mtmp->data == &mons[PM_YOUR_SISTER] || mtmp->data == &mons[PM_OCCASIONAL_FRIEND] || mtmp->data == &mons[PM_GIRL_OUTSIDE_GANG] || mtmp->data == &mons[PM_ARCANE_PRISONER] || mtmp->data == &mons[PM_GRAVITY_STRIKER] || mtmp->data == &mons[PM_POEZ_PRESIDENT] || mtmp->data == &mons[PM_IDIOT_HOME_PRINCESS]) &&
401 (mtmp->mstrategy & STRAT_WAITMASK)) {
402 /* Awaken the prisoner */
403 if (canseemon(mtmp))
404 pline("%s speaks:", Monnam(mtmp));
405 verbalize("I'm finally free!");
406 mtmp->mstrategy &= ~STRAT_WAITMASK;
407 mtmp->mpeaceful = 1;
409 /* Your god is happy... */
410 if (Race_if(PM_HUMANOID_DEVIL)) devil_misbehavior();
411 else adjalign(3);
413 /* ...But the guards are not */
414 (void) angry_guards(FALSE);
416 return;
419 void
420 quest_chat(mtmp)
421 register struct monst *mtmp;
423 if (mtmp->m_id == Qstat(leader_m_id)) {
424 chat_with_leader();
425 return;
427 switch(mtmp->data->msound) {
428 case MS_NEMESIS: chat_with_nemesis(); break;
429 case MS_GUARDIAN: chat_with_guardian(); break;
430 default: impossible("quest_chat: Unknown quest character %s.",
431 mon_nam(mtmp));
435 void
436 quest_talk(mtmp)
437 register struct monst *mtmp;
439 if (mtmp->m_id == Qstat(leader_m_id)) {
440 leader_speaks(mtmp);
441 return;
443 switch(mtmp->data->msound) {
444 case MS_NEMESIS: nemesis_speaks(); break;
445 case MS_DJINNI: prisoner_speaks(mtmp); break;
446 default: break;
450 void
451 quest_stat_check(mtmp)
452 struct monst *mtmp;
454 if(mtmp->data->msound == MS_NEMESIS)
455 Qstat(in_battle) = (mtmp->mcanmove && !mtmp->msleeping &&
456 monnear(mtmp, u.ux, u.uy));
459 /*quest.c*/