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 15STATIC_DCL void NDECL(on_start); 16STATIC_DCL void NDECL(on_locate); 17STATIC_DCL void NDECL(on_goal); 18STATIC_DCL boolean NDECL(not_capable); 19STATIC_DCL int FDECL(is_pure, (BOOLEAN_P)); 20STATIC_DCL void FDECL(expulsion, (BOOLEAN_P)); 21STATIC_DCL void NDECL(chat_with_leader); 22STATIC_DCL void NDECL(chat_with_nemesis); 23STATIC_DCL void NDECL(chat_with_guardian); 24STATIC_DCL void FDECL(prisoner_speaks, (struct monst *)); 25 26 27STATIC_OVL void 28on_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 39STATIC_OVL void 40on_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 49STATIC_OVL void 50on_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 63void 64onquest() 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 75void 76nemdead() 77{ 78 if(!Qstat(killed_nemesis)) { 79 Qstat(killed_nemesis) = TRUE; 80 qt_pager(QT_KILLEDNEM); 81 } 82} 83 84void 85artitouch() 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) */ 95boolean 96ok_to_quest() 97{ 98 return((boolean)((Qstat(got_quest) || Qstat(got_thanks))) 99 && (is_pure(FALSE) > 0)); 100} 101 102STATIC_OVL boolean 103not_capable() 104{ 105 return((boolean)(u.ulevel < MIN_QUEST_LEVEL)); 106} 107 108STATIC_OVL int 109is_pure(talk) 110boolean 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 */ 143STATIC_OVL void 144expulsion(seal) 145boolean 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. */ 176void 177finish_quest(obj) 178struct 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 205STATIC_OVL void 206chat_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 272void 273leader_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 291STATIC_OVL void 292chat_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 299void 300nemesis_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 315STATIC_OVL void 316chat_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 325STATIC_OVL void 326prisoner_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 347void 348quest_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 363void 364quest_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 378void 379quest_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*/ 388