Source:NetHack 3.2.0/quest.c

Below is the full text to quest.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/quest.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)quest.c	3.2	96/03/15	*/ 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 void NDECL(on_start); 16.  static void NDECL(on_locate); 17.  static void NDECL(on_goal); 18.  static boolean NDECL(not_capable); 19.  static boolean FDECL(is_pure, (BOOLEAN_P)); 20.  static void FDECL(expulsion, (BOOLEAN_P)); 21.  static void NDECL(chat_with_leader); 22.  static void NDECL(chat_with_nemesis); 23.  static void NDECL(chat_with_guardian); 24.   25.   static void 26.  on_start 27.  {  28.     if(!Qstat(first_start)) { 29.      qt_pager(QT_FIRSTTIME); 30.      Qstat(first_start) = TRUE; 31.    } else if((u.uz0.dnum != u.uz.dnum) || (u.uz0.dlevel < u.uz.dlevel)) { 32.      if(Qstat(not_ready) <= 2) qt_pager(QT_NEXTTIME); 33.      else	qt_pager(QT_OTHERTIME); 34.    }  35.   }  36.    37.   static void 38.  on_locate 39.  {  40.     if(!Qstat(first_locate)) { 41.      qt_pager(QT_FIRSTLOCATE); 42.      Qstat(first_locate) = TRUE; 43.    } else if(u.uz0.dlevel < u.uz.dlevel) 44.  	qt_pager(QT_NEXTLOCATE); 45.  }  46.    47.   static void 48.  on_goal 49.  {  50.     if (Qstat(killed_nemesis)) { 51.      return; 52.    } else if (!Qstat(made_goal)) { 53.      qt_pager(QT_FIRSTGOAL); 54.      Qstat(made_goal) = 1; 55.    } else { 56.      qt_pager(QT_NEXTGOAL); 57.      if(Qstat(made_goal) < 7) Qstat(made_goal)++; 58.    }  59.   }  60.    61.   void 62.  quest_init 63.  {  64.   /*  65.    *	Special setup modifications here: 66.   *  67.    *	Unfortunately, this is going to have to be done 68.   *	on each newgame or restore, because you lose the permonst mods 69.   *	across a save/restore :-)  70.    *  71.    *	1 - The Rogue Leader is the Tourist Nemesis.  72.    *	2 - Priests start with a random alignment - convert the leader and  73.    *	    guardians here.  74.    *	3 - Elves can have one of two different leaders, but can't work it  75.    *	    out here because it requires hacking the level file data (see 76.   *	    sp_lev.c).  77.    */  78.   #ifdef TOURIST  79.       if (Role_is('T')) {  80.   	mons[PM_MASTER_OF_THIEVES].msound = MS_NEMESIS;  81.   	mons[PM_MASTER_OF_THIEVES].mflags2 &= ~(M2_PEACEFUL);  82.   	mons[PM_MASTER_OF_THIEVES].mflags2 |= (M2_NASTY|M2_STALK|M2_HOSTILE);  83.   	mons[PM_MASTER_OF_THIEVES].mflags3 = M3_WANTSARTI | M3_WAITFORU;  84.       } else  85.   #endif  86.       if (Role_is('P')) {  87.   	mons[PM_ARCH_PRIEST].maligntyp = u.ualignbase[1]*3;  88.   	mons[PM_ACOLYTE].maligntyp = u.ualignbase[1]*3;  89.       }  90.   }  91.    92.   void  93.   onquest  94.   {  95.   	if(u.uevent.qcompleted || Not_firsttime) return;  96.   	if(!Is_special(&u.uz)) return;  97.    98.   	if(Is_qstart(&u.uz)) on_start;  99.   	else if(Is_qlocate(&u.uz) && u.uz.dlevel > u.uz0.dlevel) on_locate;  100.  	else if(Is_nemesis(&u.uz)) on_goal;  101.  	return;  102.  }  103. 104. void 105. nemdead 106. {  107.  	if(!Qstat(killed_nemesis)) { 108. 	    Qstat(killed_nemesis) = TRUE; 109. 	    qt_pager(QT_KILLEDNEM); 110. 	}  111.  }  112.   113.  void 114. artitouch 115. {  116.  	if(!Qstat(touched_artifact)) { 117. 	    Qstat(touched_artifact) = TRUE; 118. 	    qt_pager(QT_GOTIT); 119. 	    exercise(A_WIS, TRUE); 120. 	}  121.  }  122.   123.  /* external hook for do.c (level change check) */ 124. boolean 125. ok_to_quest 126. {  127.  	return((boolean)((Qstat(got_quest) || Qstat(got_thanks)))  128.  			&& is_pure(FALSE)); 129. }  130.   131.  static boolean 132. not_capable 133. {  134.  	return((boolean)(u.ulevel < MIN_QUEST_LEVEL)); 135. }  136.   137.  static boolean 138. is_pure(talk) 139. boolean talk; 140. {  141.      aligntyp original_alignment = u.ualignbase[1]; 142.  143.  #ifdef WIZARD 144.     if (wizard && talk) { 145. 	if (u.ualign.type != original_alignment) { 146. 	    You("are currently %s instead of %s.",  147.  		align_str(u.ualign.type), align_str(original_alignment)); 148. 	} else if (u.ualignbase[0] != original_alignment) { 149. 	    You("have converted."); 150. 	} else if (u.ualign.record < MIN_QUEST_ALIGN) { 151. 	    You("are currently %d and require %d.",  152.  		u.ualign.record, MIN_QUEST_ALIGN); 153. 	    if (yn_function("adjust?", (char *)0, 'y') == 'y') 154. 		u.ualign.record = MIN_QUEST_ALIGN; 155. 	}  156.      }  157.  #endif 158.     return (boolean)(u.ualign.record >= MIN_QUEST_ALIGN &&  159.  		     u.ualign.type == original_alignment &&  160.  		     u.ualignbase[0] == original_alignment); 161. }  162.   163.  /*  164.   * Expell the player to the stairs on the parent of the quest dungeon. 165.  *  166.   * This assumes that the hero is currently _in_ the quest dungeon and that 167.  * there is a single branch to and from it. 168.  */  169.  static void 170. expulsion(seal) 171. boolean seal; 172. {  173.      branch *br; 174.     d_level *dest; 175.     int portal_flag; 176.  177.      br = dungeon_branch("The Quest"); 178.     dest = (br->end1.dnum == u.uz.dnum) ? &br->end2 : &br->end1; 179.     portal_flag = u.uevent.qexpelled ? 0 :	/* returned via artifact? */ 180.  		  !seal ? 1 : -1; 181.      schedule_goto(dest, FALSE, FALSE, portal_flag, (char *)0, (char *)0); 182.     if (seal)	/* remove the portal to the quest - sealing it off */ 183. 	u.uevent.qexpelled = 1; 184. }  185.   186.  static void 187. chat_with_leader 188. {  189.  /*	Rule 0:	Cheater checks. */ 190.  	if(u.uhave.questart && !Qstat(met_nemesis)) 191. 	    Qstat(cheater) = TRUE; 192.  193.  /*	It is possible for you to get the amulet without completing 194.  *	the quest. If so, try to induce the player to quest. 195.  */  196.  	if(Qstat(got_thanks)) { 197. /*	Rule 1:	You've gone back with/without the amulet. */ 198.  	    if(u.uhave.amulet)	qt_pager(QT_HASAMULET); 199.  200.  /*	Rule 2:	You've gone back before going for the amulet. */ 201.  	    else		qt_pager(QT_POSTHANKS); 202. 	}  203.   204.  /*	Rule 3: You've got the artifact and are back to return it. */ 205.  	  else if(u.uhave.questart) { 206. 	    if(u.uhave.amulet)	qt_pager(QT_HASAMULET); 207. 	    else		qt_pager(QT_OFFEREDIT); 208. 	    Qstat(got_thanks) = TRUE; 209. 	    u.uevent.qcompleted = 1;	/* you did it! */ 210.   211.  /*	Rule 4: You haven't got the artifact yet. */ 212.  	} else if(Qstat(got_quest)) qt_pager(rn1(10, QT_ENCOURAGE)); 213.  214.  /*	Rule 5: You aren't yet acceptable - or are you? */ 215.  	else { 216. 	  if(!Qstat(met_leader)) { 217. 	    qt_pager(QT_FIRSTLEADER); 218. 	    Qstat(met_leader) = TRUE; 219. 	    Qstat(not_ready) = 0; 220. 	  } else qt_pager(QT_NEXTLEADER); 221. 	  /* the quest leader might have passed through the portal into 222. 	     the regular dungeon; none of the remaining make sense there */ 223. 	  if (!on_level(&u.uz, &qstart_level)) return; 224.  225.  	  if(not_capable) { 226. 	    qt_pager(QT_BADLEVEL); 227. 	    exercise(A_WIS, TRUE); 228. 	    expulsion(FALSE); 229. 	  } else if(!is_pure(TRUE)) { 230. 	    qt_pager(QT_BADALIGN); 231. 	    if(Qstat(not_ready) == MAX_QUEST_TRIES) { 232. 	      qt_pager(QT_LASTLEADER); 233. 	      expulsion(TRUE); 234. 	    } else { 235. 	      Qstat(not_ready)++; 236. 	      exercise(A_WIS, TRUE); 237. 	      expulsion(FALSE); 238. 	    }  239.  	  } else {	/* You are worthy! */ 240.  	    qt_pager(QT_ASSIGNQUEST); 241. 	    exercise(A_WIS, TRUE); 242. 	    Qstat(got_quest) = TRUE; 243. 	  }  244.  	}  245.  }  246.   247.  void 248. leader_speaks(mtmp) 249. 	register struct monst *mtmp; 250. {  251.  	/* maybe you attacked leader? */ 252.  	if(!mtmp->mpeaceful) { 253. 		Qstat(pissed_off) = TRUE; 254. 		mtmp->mstrategy &= ~STRAT_WAITMASK;	/* end the inaction */ 255. 	}  256.  	/* the quest leader might have passed through the portal into the 257. 	   regular dungeon; if so, mustn't perform "backwards expulsion" */ 258. 	if (!on_level(&u.uz, &qstart_level)) return; 259.  260.  	if(Qstat(pissed_off)) { 261. 	  qt_pager(QT_LASTLEADER); 262. 	  expulsion(TRUE); 263. 	} else chat_with_leader; 264. }  265.   266.  static void 267. chat_with_nemesis 268. {  269.  /*	The nemesis will do most of the talking, but... */ 270.  	qt_pager(rn1(10, QT_DISCOURAGE)); 271. 	if(!Qstat(met_nemesis)) Qstat(met_nemesis++); 272. }  273.   274.  void 275. nemesis_speaks 276. {  277.  	if(!Qstat(in_battle)) { 278. 	  if(u.uhave.questart) qt_pager(QT_NEMWANTSIT); 279. 	  else if(!Qstat(made_goal)) qt_pager(QT_FIRSTNEMESIS); 280. 	  else if(Qstat(made_goal) < 3) qt_pager(QT_NEXTNEMESIS); 281. 	  else if(Qstat(made_goal) < 7) qt_pager(QT_OTHERNEMESIS); 282. 	  else if(!rn2(5))	qt_pager(rn1(10, QT_DISCOURAGE)); 283. 	  if(Qstat(made_goal) < 7) Qstat(made_goal)++; 284. 	  Qstat(met_nemesis) = TRUE; 285. 	} else /* he will spit out random maledictions */ 286. 	  if(!rn2(5))	qt_pager(rn1(10, QT_DISCOURAGE)); 287. }  288.   289.  static void 290. chat_with_guardian 291. {  292.  /*	These guys/gals really don't have much to say... */ 293.  	qt_pager(rn1(5, QT_GUARDTALK)); 294. }  295.   296.  void 297. quest_chat(mtmp) 298. 	register struct monst *mtmp; 299. {  300.      switch(mtmp->data->msound) { 301. 	    case MS_LEADER:	chat_with_leader; break; 302. 	    case MS_NEMESIS:	chat_with_nemesis; break; 303. 	    case MS_GUARDIAN:	chat_with_guardian; break; 304. 	    default:	impossible("quest_chat: Unknown quest character %s.",  305.  				   mon_nam(mtmp)); 306. 	}  307.  }  308.   309.  void 310. quest_talk(mtmp) 311. 	register struct monst *mtmp; 312. {  313.      switch(mtmp->data->msound) { 314. 	    case MS_LEADER:	leader_speaks(mtmp); break; 315. 	    case MS_NEMESIS:	nemesis_speaks; break; 316. 	    default:		break; 317. 	}  318.  }  319.   320.  void 321. quest_stat_check(mtmp) 322. 	struct monst *mtmp; 323. {  324.      if(mtmp->data->msound == MS_NEMESIS) 325. 	Qstat(in_battle) = 326. 	    (mtmp->mcanmove && !mtmp->msleep && monnear(mtmp, u.ux, u.uy)); 327. }  328.   329.  /*quest.c*/