Couple of extra nethack->anethack
[aNetHack.git] / src / quest.c
blobf23d0d07baa82d54b183fc1258257200835692cd
1 /* aNetHack 0.0.1 quest.c $ANH-Date: 1446191878 2015/10/30 07:57:58 $ $ANH-Branch: master $:$ANH-Revision: 1.20 $ */
2 /* Copyright 1991, M. Stephenson */
3 /* aNetHack 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 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 *));
26 STATIC_OVL void
27 on_start()
29 if (!Qstat(first_start)) {
30 qt_pager(QT_FIRSTTIME);
31 Qstat(first_start) = TRUE;
32 } else if ((u.uz0.dnum != u.uz.dnum) || (u.uz0.dlevel < u.uz.dlevel)) {
33 if (Qstat(not_ready) <= 2)
34 qt_pager(QT_NEXTTIME);
35 else
36 qt_pager(QT_OTHERTIME);
40 STATIC_OVL void
41 on_locate()
43 /* the locate messages are phrased in a manner such that they only
44 make sense when arriving on the level from above */
45 boolean from_above = (u.uz0.dlevel < u.uz.dlevel);
47 if (Qstat(killed_nemesis)) {
48 return;
49 } else if (!Qstat(first_locate)) {
50 if (from_above)
51 qt_pager(QT_FIRSTLOCATE);
52 /* if we've arrived from below this will be a lie, but there won't
53 be any point in delivering the message upon a return visit from
54 above later since the level has now been seen */
55 Qstat(first_locate) = TRUE;
56 } else {
57 if (from_above)
58 qt_pager(QT_NEXTLOCATE);
62 STATIC_OVL void
63 on_goal()
65 if (Qstat(killed_nemesis)) {
66 return;
67 } else if (!Qstat(made_goal)) {
68 qt_pager(QT_FIRSTGOAL);
69 Qstat(made_goal) = 1;
70 } else {
71 qt_pager(QT_NEXTGOAL);
72 if (Qstat(made_goal) < 7)
73 Qstat(made_goal)++;
77 void
78 onquest()
80 if (u.uevent.qcompleted || Not_firsttime)
81 return;
82 if (!Is_special(&u.uz))
83 return;
85 if (Is_qstart(&u.uz))
86 on_start();
87 else if (Is_qlocate(&u.uz))
88 on_locate();
89 else if (Is_nemesis(&u.uz))
90 on_goal();
91 return;
94 void
95 nemdead()
97 if (!Qstat(killed_nemesis)) {
98 Qstat(killed_nemesis) = TRUE;
99 qt_pager(QT_KILLEDNEM);
103 void
104 artitouch(obj)
105 struct obj *obj;
107 if (!Qstat(touched_artifact)) {
108 /* in case we haven't seen the item yet (ie, currently blinded),
109 this quest message describes it by name so mark it as seen */
110 obj->dknown = 1;
111 /* only give this message once */
112 Qstat(touched_artifact) = TRUE;
113 qt_pager(QT_GOTIT);
114 exercise(A_WIS, TRUE);
118 /* external hook for do.c (level change check) */
119 boolean
120 ok_to_quest()
122 return (boolean) ((Qstat(got_quest) || Qstat(got_thanks))
123 && is_pure(FALSE) > 0);
126 STATIC_OVL boolean
127 not_capable()
129 return (boolean) (u.ulevel < MIN_QUEST_LEVEL);
132 STATIC_OVL int
133 is_pure(talk)
134 boolean talk;
136 int purity;
137 aligntyp original_alignment = u.ualignbase[A_ORIGINAL];
139 if (wizard && talk) {
140 if (u.ualign.type != original_alignment) {
141 You("are currently %s instead of %s.", align_str(u.ualign.type),
142 align_str(original_alignment));
143 } else if (u.ualignbase[A_CURRENT] != original_alignment) {
144 You("have converted.");
145 } else if (u.ualign.record < MIN_QUEST_ALIGN) {
146 You("are currently %d and require %d.", u.ualign.record,
147 MIN_QUEST_ALIGN);
148 if (yn_function("adjust?", (char *) 0, 'y') == 'y')
149 u.ualign.record = MIN_QUEST_ALIGN;
152 purity = (u.ualign.record >= MIN_QUEST_ALIGN
153 && u.ualign.type == original_alignment
154 && u.ualignbase[A_CURRENT] == original_alignment)
156 : (u.ualignbase[A_CURRENT] != original_alignment) ? -1 : 0;
157 return purity;
161 * Expel the player to the stairs on the parent of the quest dungeon.
163 * This assumes that the hero is currently _in_ the quest dungeon and that
164 * there is a single branch to and from it.
166 STATIC_OVL void
167 expulsion(seal)
168 boolean seal;
170 branch *br;
171 d_level *dest;
172 struct trap *t;
173 int portal_flag;
175 br = dungeon_branch("The Quest");
176 dest = (br->end1.dnum == u.uz.dnum) ? &br->end2 : &br->end1;
177 portal_flag = u.uevent.qexpelled ? 0 /* returned via artifact? */
178 : !seal ? 1 : -1;
179 schedule_goto(dest, FALSE, FALSE, portal_flag, (char *) 0, (char *) 0);
180 if (seal) { /* remove the portal to the quest - sealing it off */
181 int reexpelled = u.uevent.qexpelled;
182 u.uevent.qexpelled = 1;
183 remdun_mapseen(quest_dnum);
184 /* Delete the near portal now; the far (main dungeon side)
185 portal will be deleted as part of arrival on that level.
186 If monster movement is in progress, any who haven't moved
187 yet will now miss out on a chance to wander through it... */
188 for (t = ftrap; t; t = t->ntrap)
189 if (t->ttyp == MAGIC_PORTAL)
190 break;
191 if (t)
192 deltrap(t); /* (display might be briefly out of sync) */
193 else if (!reexpelled)
194 impossible("quest portal already gone?");
198 /* Either you've returned to quest leader while carrying the quest
199 artifact or you've just thrown it to/at him or her. If quest
200 completion text hasn't been given yet, give it now. Otherwise
201 give another message about the character keeping the artifact
202 and using the magic portal to return to the dungeon. */
203 void
204 finish_quest(obj)
205 struct obj *obj; /* quest artifact; possibly null if carrying Amulet */
207 struct obj *otmp;
209 if (u.uhave.amulet) { /* unlikely but not impossible */
210 qt_pager(QT_HASAMULET);
211 /* leader IDs the real amulet but ignores any fakes */
212 if ((otmp = carrying(AMULET_OF_YENDOR)) != 0)
213 fully_identify_obj(otmp);
214 } else {
215 qt_pager(!Qstat(got_thanks) ? QT_OFFEREDIT : QT_OFFEREDIT2);
216 /* should have obtained bell during quest;
217 if not, suggest returning for it now */
218 if ((otmp = carrying(BELL_OF_OPENING)) == 0)
219 com_pager(5);
221 Qstat(got_thanks) = TRUE;
223 if (obj) {
224 u.uevent.qcompleted = 1; /* you did it! */
225 /* behave as if leader imparts sufficient info about the
226 quest artifact */
227 fully_identify_obj(obj);
228 update_inventory();
232 STATIC_OVL void
233 chat_with_leader()
235 /* Rule 0: Cheater checks. */
236 if (u.uhave.questart && !Qstat(met_nemesis))
237 Qstat(cheater) = TRUE;
239 /* It is possible for you to get the amulet without completing
240 * the quest. If so, try to induce the player to quest.
242 if (Qstat(got_thanks)) {
243 /* Rule 1: You've gone back with/without the amulet. */
244 if (u.uhave.amulet)
245 finish_quest((struct obj *) 0);
247 /* Rule 2: You've gone back before going for the amulet. */
248 else
249 qt_pager(QT_POSTHANKS);
251 /* Rule 3: You've got the artifact and are back to return it. */
252 } else if (u.uhave.questart) {
253 struct obj *otmp;
255 for (otmp = invent; otmp; otmp = otmp->nobj)
256 if (is_quest_artifact(otmp))
257 break;
259 finish_quest(otmp);
261 /* Rule 4: You haven't got the artifact yet. */
262 } else if (Qstat(got_quest)) {
263 qt_pager(rn1(10, QT_ENCOURAGE));
265 /* Rule 5: You aren't yet acceptable - or are you? */
266 } else {
267 if (!Qstat(met_leader)) {
268 qt_pager(QT_FIRSTLEADER);
269 Qstat(met_leader) = TRUE;
270 Qstat(not_ready) = 0;
271 } else
272 qt_pager(QT_NEXTLEADER);
274 /* the quest leader might have passed through the portal into
275 the regular dungeon; none of the remaining make sense there */
276 if (!on_level(&u.uz, &qstart_level))
277 return;
279 if (not_capable()) {
280 qt_pager(QT_BADLEVEL);
281 exercise(A_WIS, TRUE);
282 expulsion(FALSE);
283 } else if (is_pure(TRUE) < 0) {
284 com_pager(QT_BANISHED);
285 expulsion(TRUE);
286 } else if (is_pure(TRUE) == 0) {
287 qt_pager(QT_BADALIGN);
288 if (Qstat(not_ready) == MAX_QUEST_TRIES) {
289 qt_pager(QT_LASTLEADER);
290 expulsion(TRUE);
291 } else {
292 Qstat(not_ready)++;
293 exercise(A_WIS, TRUE);
294 expulsion(FALSE);
296 } else { /* You are worthy! */
297 qt_pager(QT_ASSIGNQUEST);
298 exercise(A_WIS, TRUE);
299 Qstat(got_quest) = TRUE;
304 void
305 leader_speaks(mtmp)
306 struct monst *mtmp;
308 /* maybe you attacked leader? */
309 if (!mtmp->mpeaceful) {
310 Qstat(pissed_off) = TRUE;
311 mtmp->mstrategy &= ~STRAT_WAITMASK; /* end the inaction */
313 /* the quest leader might have passed through the portal into the
314 regular dungeon; if so, mustn't perform "backwards expulsion" */
315 if (!on_level(&u.uz, &qstart_level))
316 return;
318 if (Qstat(pissed_off)) {
319 qt_pager(QT_LASTLEADER);
320 expulsion(TRUE);
321 } else
322 chat_with_leader();
325 STATIC_OVL void
326 chat_with_nemesis()
328 /* The nemesis will do most of the talking, but... */
329 qt_pager(rn1(10, QT_DISCOURAGE));
330 if (!Qstat(met_nemesis))
331 Qstat(met_nemesis++);
334 void
335 nemesis_speaks()
337 if (!Qstat(in_battle)) {
338 if (u.uhave.questart)
339 qt_pager(QT_NEMWANTSIT);
340 else if (Qstat(made_goal) == 1 || !Qstat(met_nemesis))
341 qt_pager(QT_FIRSTNEMESIS);
342 else if (Qstat(made_goal) < 4)
343 qt_pager(QT_NEXTNEMESIS);
344 else if (Qstat(made_goal) < 7)
345 qt_pager(QT_OTHERNEMESIS);
346 else if (!rn2(5))
347 qt_pager(rn1(10, QT_DISCOURAGE));
348 if (Qstat(made_goal) < 7)
349 Qstat(made_goal)++;
350 Qstat(met_nemesis) = TRUE;
351 } else /* he will spit out random maledictions */
352 if (!rn2(5))
353 qt_pager(rn1(10, QT_DISCOURAGE));
356 STATIC_OVL void
357 chat_with_guardian()
359 /* These guys/gals really don't have much to say... */
360 if (u.uhave.questart && Qstat(killed_nemesis))
361 qt_pager(rn1(5, QT_GUARDTALK2));
362 else
363 qt_pager(rn1(5, QT_GUARDTALK));
366 STATIC_OVL void
367 prisoner_speaks(mtmp)
368 struct monst *mtmp;
370 if (mtmp->data == &mons[PM_PRISONER]
371 && (mtmp->mstrategy & STRAT_WAITMASK)) {
372 /* Awaken the prisoner */
373 if (canseemon(mtmp))
374 pline("%s speaks:", Monnam(mtmp));
375 verbalize("I'm finally free!");
376 mtmp->mstrategy &= ~STRAT_WAITMASK;
377 mtmp->mpeaceful = 1;
379 /* Your god is happy... */
380 adjalign(3);
382 /* ...But the guards are not */
383 (void) angry_guards(FALSE);
385 return;
388 void
389 quest_chat(mtmp)
390 register struct monst *mtmp;
392 if (mtmp->m_id == Qstat(leader_m_id)) {
393 chat_with_leader();
394 return;
396 switch (mtmp->data->msound) {
397 case MS_NEMESIS:
398 chat_with_nemesis();
399 break;
400 case MS_GUARDIAN:
401 chat_with_guardian();
402 break;
403 default:
404 impossible("quest_chat: Unknown quest character %s.", mon_nam(mtmp));
408 void
409 quest_talk(mtmp)
410 struct monst *mtmp;
412 if (mtmp->m_id == Qstat(leader_m_id)) {
413 leader_speaks(mtmp);
414 return;
416 switch (mtmp->data->msound) {
417 case MS_NEMESIS:
418 nemesis_speaks();
419 break;
420 case MS_DJINNI:
421 prisoner_speaks(mtmp);
422 break;
423 default:
424 break;
428 void
429 quest_stat_check(mtmp)
430 struct monst *mtmp;
432 if (mtmp->data->msound == MS_NEMESIS)
433 Qstat(in_battle) = (mtmp->mcanmove && !mtmp->msleeping
434 && monnear(mtmp, u.ux, u.uy));
437 /*quest.c*/