Wikihack
Advertisement

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

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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)pri.c	3.0	89/06/16
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    /* block some unused #defines to avoid overloading some cpp's */
6.    #define MONATTK_H
7.    #include "hack.h"
8.    #include <ctype.h>  /* for isalpha() */
9.    
10.   static void hilite P((uchar, uchar));
11.   static void cornbot P((int));
12.   static boolean ismnst P((char));
13.   #if !defined(DECRAINBOW) && !defined(UNIX)
14.   #  define g_putch  (void) putchar
15.   #endif
16.   
17.   #ifndef g_putch
18.   static boolean GFlag = FALSE; /* graphic flag */
19.   #endif
20.   
21.   /* 100 suffices for bot(); must be larger than COLNO */
22.   #define MAXCO 100
23.   static char oldbot1[MAXCO], newbot1[MAXCO];
24.   static char oldbot2[MAXCO], newbot2[MAXCO];
25.   static const char *dispst = "*0#@#0#*0#@#0#*0#@#0#*0#@#0#*0#@#0#*";
26.   static int mrank_sz = 0;  /* loaded by max_rank_sz (called in u_init) */
27.   
28.   void
29.   swallowed(first)
30.   register int first;
31.   {
32.   	if(first) cls();
33.   	else {
34.   		curs(u.ustuck->mdx-1, u.ustuck->mdy+1);
35.   		(void) fputs("   ", stdout);
36.   		curx = u.ustuck->mdx+2;
37.   		curs(u.ustuck->mdx-1, u.ustuck->mdy+2);
38.   		(void) fputs("   ", stdout);
39.   		curx = u.ustuck->mdx+2;
40.   		curs(u.ustuck->mdx-1, u.ustuck->mdy+3);
41.   		(void) fputs("   ", stdout);
42.   		curx = u.ustuck->mdx+2;
43.   	}
44.   	curs(u.ux-1, u.uy+1);
45.   	(void) fputs("/-\\", stdout);
46.   	curx = u.ux+2;
47.   	curs(u.ux-1, u.uy+2);
48.   	(void) putchar('|');
49.   	hilite(u.usym, AT_MON);
50.   	(void) putchar('|');
51.   	curx = u.ux+2;
52.   	curs(u.ux-1, u.uy+3);
53.   	(void) fputs("\\-/", stdout);
54.   	curx = u.ux+2;
55.   	u.udispl = 1;
56.   	u.udisx = u.ux;
57.   	u.udisy = u.uy;
58.   }
59.   
60.   void
61.   setclipped()
62.   {
63.   	error("NetHack needs a screen of size at least %d by %d.\n",
64.   		ROWNO+3, COLNO);
65.   }
66.   
67.   /*
68.    *  Allow for a different implementation than this...
69.    */
70.   
71.   #ifndef g_putch
72.   
73.   static void
74.   g_putch(ch)
75.   uchar ch;
76.   {
77.   	if (ch & 0x80) {
78.   		if (!GFlag) {
79.   			graph_on();
80.   			GFlag = TRUE;
81.   		}
82.   		(void) putchar(ch ^ 0x80); /* Strip 8th bit */
83.   	} else {
84.   		if (GFlag) {
85.   			graph_off();
86.   			GFlag = FALSE;
87.   		}
88.   		(void) putchar(ch);
89.   	}
90.   }
91.   
92.   #endif
93.   
94.   static boolean
95.   showmon(mon)
96.   register struct monst *mon;
97.   {
98.   	register boolean show = (Blind && Telepat) || canseemon(mon);
99.   
100.  	if (!show && (HTelepat & WORN_HELMET))
101.  		show = (dist(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM));
102.  	return(show);
103.  }
104.  
105.  void
106.  at(x,y,ch,typ)
107.  register xchar x,y;
108.  uchar ch,typ;
109.  {
110.  #ifndef LINT
111.  	/* if xchar is unsigned, lint will complain about  if(x < 0)  */
112.  	if(x < 0 || x > COLNO-1 || y < 0 || y > ROWNO-1) {
113.  		impossible("At gets 0%o at %d %d.", ch, x, y);
114.  		return;
115.  	}
116.  #endif
117.  	if(!ch) {
118.  		impossible("At gets null at %d %d.", x, y);
119.  		return;
120.  	}
121.  
122.  	if (typ == AT_APP
123.  #ifndef MSDOS
124.  	    && flags.standout
125.  #endif
126.  	   )
127.  		/* don't hilite if this isn't a monster or object.
128.  		 *
129.  		 * not complete; a scroll dropped by some monster
130.  		 * on an unseen doorway which is later magic mapped
131.  		 * will still hilite the doorway symbol.  -3.
132.  		 */
133.  		if (!vism_at(x,y) &&
134.  		    (!levl[x][y].omask && !levl[x][y].gmask || is_pool(x,y)))
135.  		    typ = AT_MAP;
136.  
137.  	y += 2;
138.  	curs(x,y);
139.  
140.  	hilite(ch,typ);
141.  	curx++;
142.  }
143.  
144.  void
145.  prme(){
146.  	if(!Invisible
147.  #ifdef POLYSELF
148.  			&& !u.uundetected
149.  #endif
150.  					) at(u.ux,u.uy,u.usym,AT_U);
151.  }
152.  
153.  void
154.  shieldeff(x, y)		/* produce a magical shield effect at x,y */
155.  	register xchar x, y;
156.  {
157.  	register char *ch;
158.  	register struct monst *mtmp = 0;
159.  
160.  	if((x != u.ux) || (y != u.uy)) {
161.  	    if(!(mtmp = m_at(x, y))) {
162.  
163.  		impossible("shield effect at %d,%d", x, y);
164.  		return;
165.  	    }
166.  	    if(!showmon(mtmp)) return;
167.  	}
168.  
169.  	for(ch = dispst; *ch; ch++)  {
170.  		at(x, y, (uchar) *ch, AT_ZAP);
171.  		(void) fflush(stdout);
172.  		delay_output();
173.  		delay_output();
174.  	}
175.  
176.  	nomul(0);
177.  	if(!mtmp) {
178.  		if(Invisible) {
179.  			prl(x, y);
180.  			at(x, y, levl[x][y].scrsym, AT_APP);
181.  		} else prme();
182.  	} else {
183.  		mtmp->mdispl = 0;	/* make sure it gets redrawn */
184.  		prl(x, y);
185.  		if(mtmp->minvis)
186.  			at(x, y, levl[x][y].scrsym, AT_APP);
187.  		else	at(x, y, (uchar) mtmp->data->mlet, AT_MON);
188.  	}
189.  
190.  	return;
191.  }
192.  
193.  int
194.  doredraw()
195.  {
196.  	docrt();
197.  	return 0;
198.  }
199.  
200.  void
201.  docrt()
202.  {
203.  	register int x,y;
204.  	register struct rm *room;
205.  	register struct monst *mtmp;
206.  
207.  	if(u.uswallow) {
208.  		swallowed(1);
209.  		return;
210.  	}
211.  	cls();
212.  
213.  /* Some ridiculous code to get display of @ and monsters (almost) right */
214.  	if(!Invisible
215.  #ifdef POLYSELF
216.  			|| u.uundetected
217.  #endif
218.  					) {
219.  		levl[(u.udisx = u.ux)][(u.udisy = u.uy)].scrsym = u.usym;
220.  		levl[u.udisx][u.udisy].seen = 1;
221.  		u.udispl = 1;
222.  	} else	u.udispl = 0;
223.  
224.  	seemons();	/* reset old positions */
225.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
226.  		mtmp->mdispl = 0;
227.  	seemons();	/* force new positions to be shown */
228.  
229.  #if defined(DGK) && !defined(MSDOSCOLOR)
230.  	/* Otherwise, line buffer the output to do the redraw in
231.  	 * about 2/3 of the time.
232.  	 */
233.  		for(y = 0; y < ROWNO; y++) {
234.  			char buf[COLNO+1];
235.  			int start, end;
236.  #ifdef TOS
237.  			setmem(buf, COLNO, ' ');
238.  #else
239.  			memset(buf, ' ', COLNO);
240.  #endif /* TOS */
241.  			for(x = 0, start = -1, end = -1; x < COLNO; x++)
242.  				if((room = &levl[x][y])->new) {
243.  					room->new = 0;
244.  					buf[x] = room->scrsym;
245.  					if (start < 0)
246.  						start = x;
247.  					end = x;
248.  				} else if(room->seen) {
249.  					buf[x] = room->scrsym;
250.  					if (start < 0)
251.  						start = x;
252.  					end = x;
253.  				}
254.  			if (end >= 0) {
255.  				buf[end + 1] = '\0';
256.  				curs(start, y + 2);
257.  				(void) fputs(buf + start, stdout);
258.  				curx = end + 1;
259.  			}
260.  		}
261.  #else /* DGK && !MSDOSCOLOR */
262.  	for(y = 0; y < ROWNO; y++)
263.  		for(x = 0; x < COLNO; x++)
264.  			if((room = &levl[x][y])->new) {
265.  				room->new = 0;
266.  				at(x,y,room->scrsym,AT_APP);
267.  			} else if(room->seen)
268.  				at(x,y,room->scrsym,AT_APP);
269.  #endif /* DGK && !MSDOSCOLOR */
270.  #ifndef g_putch
271.  	if (GFlag) {
272.  		graph_off();
273.  		GFlag = FALSE;
274.  	}
275.  #endif
276.  	scrlx = COLNO;
277.  	scrly = ROWNO;
278.  	scrhx = scrhy = 0;
279.  	cornbot(0);
280.  	bot();
281.  }
282.  
283.  static void
284.  cornbot(lth)
285.  register int lth;
286.  {
287.  	oldbot1[lth] = 0;
288.  	oldbot2[lth] = 0;
289.  	flags.botl = 1;
290.  }
291.  
292.  void
293.  docorner(xmin, ymax)
294.  register int xmin, ymax;
295.  {
296.  	register int x, y;
297.  	register struct rm *room;
298.  	register struct monst *mtmp;
299.  
300.  	if(u.uswallow) {	/* Can be done more efficiently */
301.  		swallowed(1);
302.  		return;
303.  	}
304.  
305.  	seemons();	/* reset old positions */
306.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
307.  	    if(mtmp->mx >= xmin && mtmp->my < ymax)
308.  		mtmp->mdispl = 0;
309.  	seemons();	/* force new positions to be shown */
310.  
311.  	for(y = 0; y < ymax; y++) {
312.  		if(y > ROWNO+1 && CD) break;
313.  		curs(xmin,y+2);
314.  		cl_end();
315.  		if(y < ROWNO) {
316.  		    for(x = xmin; x < COLNO; x++) {
317.  			if((room = &levl[x][y])->new) {
318.  				room->new = 0;
319.  				at(x,y,room->scrsym,AT_APP);
320.  			} else
321.  				if(room->seen)
322.  					at(x,y,room->scrsym,AT_APP);
323.  		    }
324.  		}
325.  	}
326.  #ifndef g_putch
327.  	if (GFlag) {
328.  		graph_off();
329.  		GFlag = FALSE;
330.  	}
331.  #endif
332.  	/* Note:          y values: 0 to ymax-1
333.  	 * screen positions from y: 2 to ymax+1
334.  	 *            whole screen: 1 to ROWNO+3
335.  	 *                top line: 1
336.  	 *         dungeon display: 2 to ROWNO+1
337.  	 *       first bottom line: ROWNO+2
338.  	 *      second bottom line: ROWNO+3
339.  	 *         lines on screen: ROWNO+3
340.  	 */
341.  	if(ymax > ROWNO) {
342.  		cornbot(xmin-1);
343.  		if(ymax > ROWNO+2 && CD) {	/* clear portion of long */
344.  			curs(1,ROWNO+4);	/* screen below status lines */
345.  			cl_eos();
346.  		}
347.  	}
348.  }
349.  
350.  void
351.  seeglds()
352.  {
353.  	register struct gold *gold, *gold2;
354.  
355.  	for(gold = fgold; gold; gold = gold2) {
356.  	    gold2 = gold->ngold;
357.  	    if(Hallucination && cansee(gold->gx,gold->gy))
358.  		if(!(gold->gx == u.ux && gold->gy == u.uy) || Invisible)
359.  		    atl(gold->gx,gold->gy,rndobjsym());
360.  	}
361.  }
362.  
363.  /* Trolls now regenerate thanks to KAA */
364.  
365.  void
366.  seeobjs()
367.  {
368.  	register struct obj *obj, *obj2;
369.  
370.  	for(obj = fobj; obj; obj = obj2) {
371.  	    obj2 = obj->nobj;
372.  
373.  	    if(Hallucination && cansee(obj->ox,obj->oy))
374.  		if(!(obj->ox == u.ux && obj->oy == u.uy) || Invisible)
375.  		    atl(obj->ox,obj->oy,rndobjsym());
376.  
377.  	    if(obj->olet == FOOD_SYM && obj->otyp == CORPSE) {
378.  
379.  		if(mons[obj->corpsenm].mlet == S_TROLL &&
380.  		    obj->age + 20 < moves) {
381.  			boolean visible = cansee(obj->ox,obj->oy);
382.  			struct monst *mtmp = revive(obj, FALSE);
383.  
384.  			if (mtmp && visible)
385.  				pline("%s rises from the dead!", Monnam(mtmp));
386.  		} else if (obj->age + 250 < moves) delobj(obj);
387.  	    }
388.  	}
389.  
390.  	for(obj = invent; obj; obj = obj2) {
391.  	    obj2 = obj->nobj;
392.  	    if(obj->otyp == CORPSE) {
393.  		if(mons[obj->corpsenm].mlet == S_TROLL
394.  			    && obj->age + 20 < moves) {
395.  		    boolean wielded = (obj==uwep);
396.  		    struct monst *mtmp = revive(obj, TRUE);
397.  
398.  		    if (mtmp && wielded)
399.  			pline("The %s %s writhes out of your grasp!",
400.  				mtmp->data->mname, xname(obj));
401.  		    else if (mtmp)
402.  			You("feel squirming in your backpack!");
403.  		} else if (obj->age + 250 < moves) useup(obj);
404.  	    }
405.  	}
406.  }
407.  
408.  void
409.  seemons()
410.  {
411.  	register struct monst *mtmp;
412.  
413.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
414.  	    if(mtmp->data->mlet == S_EEL)
415.  		mtmp->minvis = (u.ustuck != mtmp && is_pool(mtmp->mx,mtmp->my));
416.  	    pmon(mtmp);
417.  #ifdef WORM
418.  	    if(mtmp->wormno) wormsee(mtmp->wormno);
419.  #endif
420.  	}
421.  }
422.  
423.  void
424.  pmon(mon)
425.  register struct monst *mon;
426.  {
427.  	register int show = showmon(mon);
428.  
429.  	if(mon->mdispl)
430.  	    if(mon->mdx != mon->mx || mon->mdy != mon->my || !show)
431.  		unpmon(mon);
432.  
433.  /* If you're hallucinating, the monster must be redrawn even if it has
434.   * already been printed.
435.   */
436.  	if(show && (!mon->mdispl || Hallucination)) {
437.  	    if (Hallucination)
438.  	    atl(mon->mx,mon->my,
439.  		(char) ((!mon->mimic || Protection_from_shape_changers) ?
440.  		rndmonsym() : (mon->mappearance == DOOR_SYM) ?
441.  		DOOR_SYM : rndobjsym()));
442.  	    else
443.  
444.  		atl(mon->mx,mon->my,
445.  		    (!mon->mappearance ||
446.  		     Protection_from_shape_changers) ?
447.  		     mon->data->mlet : mon->mappearance);
448.  		mon->mdispl = 1;
449.  		mon->mdx = mon->mx;
450.  		mon->mdy = mon->my;
451.  	}
452.  #ifndef g_putch
453.  	if (GFlag) {
454.  		graph_off();
455.  		GFlag = FALSE;
456.  	}
457.  #endif
458.  }
459.  
460.  void
461.  unpmon(mon)
462.  register struct monst *mon;
463.  {
464.  	if(mon->mdispl) {
465.  		newsym(mon->mdx, mon->mdy);
466.  		mon->mdispl = 0;
467.  	}
468.  }
469.  
470.  void
471.  nscr() {
472.  	register int x, y;
473.  	register struct rm *room;
474.  
475.  	if(u.uswallow || u.ux == FAR || flags.nscrinh) return;
476.  	pru();
477.  	for(y = scrly; y <= scrhy; y++)
478.  		for(x = scrlx; x <= scrhx; x++)
479.  			if((room = &levl[x][y])->new) {
480.  				room->new = 0;
481.  				at(x,y,room->scrsym,AT_APP);
482.  			}
483.  #ifndef g_putch
484.  	if (GFlag) {
485.  		graph_off();
486.  		GFlag = FALSE;
487.  	}
488.  #endif
489.  	scrhx = scrhy = 0;
490.  	scrlx = COLNO;
491.  	scrly = ROWNO;
492.  }
493.  
494.  /* Make sure that there are 18 entries in the rank arrays. */
495.  /* 0 and even entries are male ranks, odd entries are female. */
496.  
497.  static const char *mage_ranks[] = {
498.  	"Evoker",
499.  	"Evoker",
500.  	"Conjurer",
501.  	"Conjurer",
502.  	"Thaumaturge",
503.  	"Thaumaturge",
504.  	"Magician",
505.  	"Magician",
506.  	"Enchanter",
507.  	"Enchanter",
508.  	"Sorcerer",
509.  	"Sorceress",
510.  	"Necromancer",
511.  	"Necromancer",
512.  	"Wizard",
513.  	"Wizard",
514.  	"Mage",
515.  	"Mage"
516.  };
517.  
518.  static const char *priest_ranks[] = {
519.  	"Aspirant",
520.  	"Aspirant",
521.  	"Acolyte",
522.  	"Acolyte",
523.  	"Adept",
524.  	"Adept",
525.  	"Priest",
526.  	"Priestess",
527.  	"Curate",
528.  	"Curate",
529.  	"Canon",
530.  	"Canoness",
531.  	"Lama",
532.  	"Lama",
533.  	"Patriarch",
534.  	"Matriarch",
535.  	"High Priest",
536.  	"High Priestess"
537.  };
538.  
539.  static const char *thief_ranks[] = {
540.  	"Footpad",
541.  	"Footpad",
542.  	"Cutpurse",
543.  	"Cutpurse",
544.  	"Rogue",
545.  	"Rogue",
546.  	"Pilferer",
547.  	"Pilferer",
548.  	"Robber",
549.  	"Robber",
550.  	"Burglar",
551.  	"Burglar",
552.  	"Filcher",
553.  	"Filcher",
554.  	"Magsman",
555.  	"Magswoman",
556.  	"Thief",
557.  	"Thief"
558.  };
559.  
560.  static const char *fighter_ranks[] = {
561.  	"Stripling",
562.  	"Stripling",
563.  	"Skirmisher",
564.  	"Skirmisher",
565.  	"Fighter",
566.  	"Fighter",
567.  	"Man-at-arms",
568.  	"Woman-at-arms",
569.  	"Warrior",
570.  	"Warrior",
571.  	"Swashbuckler",
572.  	"Swashbuckler",
573.  	"Hero",
574.  	"Heroine",
575.  	"Champion",
576.  	"Champion",
577.  	"Lord",
578.  	"Lady"
579.  };
580.  
581.  static const char *tourist_ranks[] = {
582.  	"Rambler",
583.  	"Rambler",
584.  	"Sightseer",
585.  	"Sightseer",
586.  	"Excursionist",
587.  	"Excursionist",
588.  	"Peregrinator",
589.  	"Peregrinator",
590.  	"Traveler",
591.  	"Traveler",
592.  	"Journeyer",
593.  	"Journeyer",
594.  	"Voyager",
595.  	"Voyager",
596.  	"Explorer",
597.  	"Explorer",
598.  	"Adventurer",
599.  	"Adventurer"
600.  };
601.  
602.  static const char *nomad_ranks[] = {
603.  	"Troglodyte",
604.  	"Troglodyte",
605.  	"Aborigine",
606.  	"Aborigine",
607.  	"Wanderer",
608.  	"Wanderer",
609.  	"Vagrant",
610.  	"Vagrant",
611.  	"Wayfarer",
612.  	"Wayfarer",
613.  	"Roamer",
614.  	"Roamer",
615.  	"Nomad",
616.  	"Nomad",
617.  	"Rover",
618.  	"Rover",
619.  	"Pioneer",
620.  	"Pioneer"
621.  };
622.  
623.  static const char *knight_ranks[] = {
624.  	"Gallant",
625.  	"Gallant",
626.  	"Esquire",
627.  	"Esquire",
628.  	"Bachelor",
629.  	"Bachelor",
630.  	"Sergeant",
631.  	"Sergeant",
632.  	"Knight",
633.  	"Knight",
634.  	"Banneret",
635.  	"Banneret",
636.  	"Chevalier",
637.  	"Chevalier",
638.  	"Seignieur",
639.  	"Seignieur",
640.  	"Paladin",
641.  	"Paladin"
642.  };
643.  
644.  static const char *archeo_ranks[] = {
645.  	"Digger",
646.  	"Digger",
647.  	"Field Worker",
648.  	"Field Worker",
649.  	"Investigator",
650.  	"Investigator",
651.  	"Exhumer",
652.  	"Exhumer",
653.  	"Excavator",
654.  	"Excavator",
655.  	"Spelunker",
656.  	"Spelunker",
657.  	"Speleologist",
658.  	"Speleologist",
659.  	"Collector",
660.  	"Collector",
661.  	"Curator",
662.  	"Curator"
663.  };
664.  
665.  static const char *healer_ranks[] = {
666.  	"Pre-Med",
667.  	"Pre-Med",
668.  	"Med Student",
669.  	"Med Student",
670.  	"Medic",
671.  	"Medic",
672.  	"Intern",
673.  	"Intern",
674.  	"Doctor",
675.  	"Doctor",
676.  	"Physician",
677.  	"Physician",
678.  	"Specialist",
679.  	"Specialist",
680.  	"Surgeon",
681.  	"Surgeon",
682.  	"Chief Surgeon",
683.  	"Chief Surgeon"
684.  };
685.  
686.  static const char *barbarian_ranks[] = {
687.  	"Plunderer",
688.  	"Plunderess",
689.  	"Pillager",
690.  	"Pillager",
691.  	"Bandit",
692.  	"Bandit",
693.  	"Brigand",
694.  	"Brigand",
695.  	"Raider",
696.  	"Raider",
697.  	"Reaver",
698.  	"Reaver",
699.  	"Slayer",
700.  	"Slayer",
701.  	"Chieftain",
702.  	"Chieftainess",
703.  	"Conqueror",
704.  	"Conqueress"
705.  };
706.  
707.  static const char *ninja_ranks[] = {
708.  	"Chigo",
709.  	"Chigo",
710.  	"Bushi",
711.  	"Bushi",
712.  	"Genin",
713.  	"Genin",
714.  	"Genin",
715.  	"Genin",
716.  	"Chunin",
717.  	"Chunin",
718.  	"Chunin",
719.  	"Chunin",
720.  	"Jonin",
721.  	"Jonin",
722.  	"Jonin",
723.  	"Jonin",
724.  	"Jonin",
725.  	"Jonin",
726.  };
727.  
728.  static const char *elf_ranks[] = {
729.  	"Edhel",
730.  	"Elleth",
731.  	"Edhel",
732.  	"Elleth", 	/* elf-maid */
733.  	"Ohtar", 	/* warrior */
734.  	"Ohtie",
735.  	"Kano", 	/* commander (Q.) ['a] */
736.  	"Kanie", 	/* educated guess, until further research- SAC */
737.  	"Arandur", 	/* king's servant, minister (Q.) - educated guess */
738.  	"Aranduriel", 	/* educated guess */
739.  	"Hir", 		/* lord (S.) */
740.  	"Hiril", 	/* lady (S.) ['ir] */
741.  	"Aredhel", 	/* noble elf (S.) */
742.  	"Arwen", 	/* noble maiden (S.) */
743.  	"Ernil", 	/* prince (S.) */
744.  	"Elentariel", 	/* elf-maiden (Q.) */
745.  	"Elentar", 	/* Star-king (Q.) */
746.  	"Elentari", 	/* Star-queen (Q.) */ /* Elbereth (S.) */
747.  };
748.  
749.  static const char **
750.  rank_array() {
751.  	register const char **ranks;
752.  
753.  	switch(pl_character[0]) {
754.  		case 'A':  ranks = archeo_ranks; break;
755.  		case 'B':  ranks = barbarian_ranks; break;
756.  		case 'C':  ranks = nomad_ranks; break;
757.  		case 'E':  ranks = elf_ranks; break;
758.  		case 'H':  ranks = healer_ranks; break;
759.  		case 'K':  ranks = knight_ranks; break;
760.  		case 'P':  ranks = priest_ranks; break;
761.  		case 'R':  ranks = thief_ranks; break;
762.  		case 'S':  ranks = ninja_ranks; break;
763.  		case 'T':  ranks = tourist_ranks; break;
764.  		case 'V':  ranks = fighter_ranks; break;
765.  		case 'W':  ranks = mage_ranks; break;
766.  		default:   ranks = 0; break;
767.  	}
768.  	return(ranks);
769.  }
770.  
771.  static char *
772.  rank() {
773.  	register int place;
774.  	register const char **ranks = rank_array();
775.  
776.  	if(u.ulevel < 3) place = 0;
777.  	else if(u.ulevel <  6) place =  2;
778.  	else if(u.ulevel < 10) place =  4;
779.  	else if(u.ulevel < 14) place =  6;
780.  	else if(u.ulevel < 18) place =  8;
781.  	else if(u.ulevel < 22) place = 10;
782.  	else if(u.ulevel < 26) place = 12;
783.  	else if(u.ulevel < 30) place = 14;
784.  	else place = 16;
785.  	if(flags.female) place++;
786.  
787.  	if (!!ranks) return(ranks[place]);
788.  	return(pl_character);
789.  }
790.  
791.  void
792.  max_rank_sz() {
793.  	register int i, maxr = 0;
794.  	register const char **ranks = rank_array();
795.  
796.  	if (!!ranks) {
797.  		for(i = flags.female; i < 18; i += 2)
798.  			if(strlen(ranks[i]) > maxr) maxr = strlen(ranks[i]);
799.  		mrank_sz = maxr;
800.  	}
801.  	else mrank_sz = strlen(pl_character);
802.  }
803.  
804.  static void
805.  fillbot(row,oldbot,newbot)
806.  int row;
807.  char *oldbot, *newbot;
808.  {
809.  	register char *ob = oldbot, *nb = newbot;
810.  	register int i;
811.  	int fillcol;
812.  
813.  	fillcol = min(CO, MAXCO-1);
814.  
815.  	/* compress in case line too long */
816.  	if(strlen(newbot) >= fillcol) {
817.  		register char *bp0 = newbot, *bp1 = newbot;
818.  
819.  		do {
820.  			if(*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ')
821.  				*bp1++ = *bp0;
822.  		} while(*bp0++);
823.  	}
824.  	newbot[fillcol] = '\0';
825.  
826.  	for(i = 1; i < fillcol; i++) {
827.  		if(!*nb) {
828.  			if(*ob || flags.botlx) {
829.  				/* last char printed may be in middle of line */
830.  				curs(strlen(newbot)+1,row);
831.  				cl_end();
832.  			}
833.  			break;
834.  		}
835.  		if(*ob != *nb) {
836.  			curs(i,row);
837.  			(void) putchar(*nb);
838.  			curx++;
839.  		}
840.  		if(*ob) ob++;
841.  		nb++;
842.  	}
843.  	Strcpy(oldbot, newbot);
844.  }
845.  
846.  static void
847.  bot1()
848.  {
849.  	register int i,j;
850.  
851.  	Strcpy(newbot1, plname);
852.  	if('a' <= newbot1[0] && newbot1[0] <= 'z') newbot1[0] += 'A'-'a';
853.  	newbot1[10] = 0;
854.  	Sprintf(eos(newbot1)," the ");
855.  #ifdef POLYSELF
856.  	if (u.mtimedone) {
857.  		char mbot[BUFSZ];
858.  		int k = 0;
859.  
860.  		Strcpy(mbot, mons[u.umonnum].mname);
861.  		while(mbot[k] != 0) {
862.  		    if ((k == 0 || (k > 0 && mbot[k-1] == ' ')) &&
863.  					'a' <= mbot[k] && mbot[k] <= 'z')
864.  			mbot[k] += 'A' - 'a';
865.  		    k++;
866.  		}
867.  		Sprintf(eos(newbot1), mbot);
868.  	} else
869.  		Sprintf(eos(newbot1), rank());
870.  #else
871.  	Sprintf(eos(newbot1), rank());
872.  #endif
873.  	Sprintf(eos(newbot1),"  ");
874.  	i = mrank_sz + 15;
875.  	j = strlen(newbot1);
876.  	if((i - j) > 0)
877.  	      do { Sprintf(eos(newbot1)," "); /* pad with spaces */
878.  		   i--;
879.  	      } while((i - j) > 0);
880.  	if(ACURR(A_STR)>18) {
881.  		if(ACURR(A_STR)>118)
882.  		    Sprintf(eos(newbot1),"St:%2d ",ACURR(A_STR)-100);
883.  		else if(ACURR(A_STR)<118)
884.  		    Sprintf(eos(newbot1), "St:18/%02d ",ACURR(A_STR)-18);
885.  		else
886.  		    Sprintf(eos(newbot1),"St:18/** ");
887.  	} else
888.  		Sprintf(eos(newbot1), "St:%-1d ",ACURR(A_STR));
889.  	Sprintf(eos(newbot1),
890.  		"Dx:%-1d Co:%-1d In:%-1d Wi:%-1d Ch:%-1d",
891.  		ACURR(A_DEX), ACURR(A_CON), ACURR(A_INT), ACURR(A_WIS), ACURR(A_CHA));
892.  	Sprintf(eos(newbot1), (u.ualigntyp == U_CHAOTIC) ? "  Chaotic" :
893.  			(u.ualigntyp == U_NEUTRAL) ? "  Neutral" : "  Lawful");
894.  #ifdef SCORE_ON_BOTL
895.  	Sprintf(eos(newbot1)," S:%lu"
896.  	    ,(u.ugold - u.ugold0 > 0 ? u.ugold - u.ugold0 : 0)
897.  	    + u.urexp + (50 * maxdlevel)
898.  	    + (maxdlevel > 20? 1000*((maxdlevel > 30) ? 10 : maxdlevel - 20) :0));
899.  #endif
900.  	fillbot(ROWNO+2, oldbot1, newbot1);
901.  }
902.  
903.  static void
904.  bot2()
905.  {
906.  #ifdef ENDGAME
907.  	if(dlevel == ENDLEVEL)
908.  		Sprintf(newbot2, "EndLevel ");
909.  	else
910.  #endif
911.  #ifdef SPELLS
912.  		Sprintf(newbot2, "Dlvl:%-2d ", dlevel);
913.  #else
914.  		Sprintf(newbot2, "Level:%-1d ", dlevel);
915.  #endif
916.  	Sprintf(eos(newbot2),
917.  #ifdef SPELLS
918.  		"G:%-2ld HP:%d(%d) Pw:%d(%d) AC:%-2d",
919.  		u.ugold,
920.  # ifdef POLYSELF
921.  		u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax : u.uhpmax,
922.  		u.uen, u.uenmax, u.uac);
923.  # else
924.  		u.uhp, u.uhpmax, u.uen, u.uenmax, u.uac);
925.  # endif
926.  #else
927.  		"Gold:%-1lu HP:%d(%d) AC:%-1d",
928.  		u.ugold,
929.  # ifdef POLYSELF
930.  		u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax : u.uhpmax,
931.  		u.uac);
932.  # else
933.  		u.uhp, u.uhpmax, u.uac);
934.  # endif
935.  #endif
936.  #ifdef POLYSELF
937.  	if (u.mtimedone)
938.  		Sprintf(eos(newbot2), " HD:%d", mons[u.umonnum].mlevel);
939.  	else
940.  #endif
941.  #ifdef EXP_ON_BOTL
942.  	Sprintf(eos(newbot2), " Xp:%u/%-1ld", u.ulevel,u.uexp);
943.  #else
944.  	Sprintf(eos(newbot2), " Exp:%u", u.ulevel);
945.  #endif
946.  	if(flags.time)
947.  	    Sprintf(eos(newbot2), " T:%ld", moves);
948.  	if(strcmp(hu_stat[u.uhs], "        ")) {
949.  		Sprintf(eos(newbot2), " ");
950.  		Strcat(newbot2, hu_stat[u.uhs]);
951.  	}
952.  	if(Confusion)	   Sprintf(eos(newbot2), " Conf");
953.  	if(Sick)	   Sprintf(eos(newbot2), " Sick");
954.  	if(Blinded)	   Sprintf(eos(newbot2), " Blind");
955.  	if(Stunned)	   Sprintf(eos(newbot2), " Stun");
956.  	if(Hallucination)  Sprintf(eos(newbot2), " Hallu");
957.  	fillbot(ROWNO+3, oldbot2, newbot2);
958.  }
959.  
960.  void
961.  bot() {
962.  register char *ob1 = oldbot1, *ob2 = oldbot2;
963.  	if(flags.botlx) *ob1 = *ob2 = 0;
964.  	bot1();
965.  	bot2();
966.  	flags.botl = flags.botlx = 0;
967.  }
968.  
969.  
970.  void
971.  mstatusline(mtmp)
972.  register struct monst *mtmp;
973.  {
974.  	pline("Status of %s (%s): ", mon_nam(mtmp),
975.  		(mtmp->data->maligntyp <= -1) ? "chaotic" :
976.  		mtmp->data->maligntyp ? "lawful" : "neutral");
977.  	pline("Level %d  Gold %lu  HP %d(%d)",
978.  	    mtmp->m_lev, mtmp->mgold, mtmp->mhp, mtmp->mhpmax);
979.  	pline("AC %d%s%s", mtmp->data->ac,
980.  	    mtmp->mcan ? ", cancelled" : "" ,mtmp->mtame ? ", tame" : "");
981.  }
982.  
983.  void
984.  ustatusline()
985.  {
986.  	pline("Status of %s (%s%s):", plname,
987.  		(u.ualign > 3) ? "stridently " :
988.  		(u.ualign == 3) ? "" :
989.  		(u.ualign >= 1) ? "haltingly " :
990.  		(u.ualign == 0) ? "nominally " :
991.  				"insufficiently ",
992.  		(u.ualigntyp == U_CHAOTIC) ? "chaotic" :
993.  		u.ualigntyp ? "lawful" : "neutral");
994.  	pline("Level %d  Gold %lu  HP %d(%d)  AC %d",
995.  # ifdef POLYSELF
996.  		u.mtimedone ? mons[u.umonnum].mlevel : u.ulevel,
997.  		u.ugold, u.mtimedone ? u.mh : u.uhp,
998.  		u.mtimedone ? u.mhmax : u.uhpmax, u.uac);
999.  # else
1000. 		u.ulevel, u.ugold, u.uhp, u.uhpmax, u.uac);
1001. # endif
1002. }
1003. 
1004. void
1005. cls()
1006. {
1007. 	extern xchar tlx, tly;
1008. 
1009. 	if(flags.toplin == 1)
1010. 		more();
1011. 	flags.toplin = 0;
1012. 
1013. 	clear_screen();
1014. 
1015. 	tlx = tly = 1;
1016. 
1017. 	flags.botlx = 1;
1018. }
1019. 
1020. char
1021. rndmonsym()
1022. {
1023. 	return(mons[rn2(NUMMONS - 1)].mlet);
1024. }
1025. 
1026. static const char objsyms[] = {
1027. 	WEAPON_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM, WAND_SYM,
1028. #ifdef SPELLS
1029. 	SPBOOK_SYM,
1030. #endif
1031. 	RING_SYM, AMULET_SYM, FOOD_SYM, TOOL_SYM, GEM_SYM, GOLD_SYM, ROCK_SYM };
1032. 
1033. char
1034. rndobjsym()
1035. {
1036. 	return objsyms[rn2(SIZE(objsyms))];
1037. }
1038. 
1039. static const char *hcolors[] = {
1040. 			"ultraviolet", "infrared", "hot pink", "psychedelic",
1041. 			"bluish-orange", "reddish-green", "dark white",
1042. 			"light black", "loud", "salty", "sweet", "sour",
1043. 			"bitter", "luminescent", "striped", "polka-dotted",
1044. 			"square", "round", "triangular", "brilliant",
1045. 			"navy blue", "cerise", "chartreuse", "mauve",
1046. 			"lime green", "copper", "sea green", "spiral",
1047. 			"swirly", "blotchy", "fluorescent green",
1048. 			"burnt orange", "indigo", "amber", "tan",
1049. 			"sky blue-pink", "lemon yellow", "off-white",
1050. 			"paisley", "plaid", "argyle", "incandescent"};
1051. 
1052. const char *
1053. hcolor()
1054. {
1055. 	return hcolors[rn2(SIZE(hcolors))];
1056. }
1057. 
1058. /*  Bug: if a level character is the same as an object/monster, it may be
1059.  *  hilited, because we use a kludge to figure out if a character is an
1060.  *  object/monster symbol.  It's smarter than it was in 2.3, but you
1061.  *  can still fool it (ex. if an object is in a doorway you have not seen,
1062.  *  and you look at a map, the '+' will be taken as a spellbook symbol).
1063.  *
1064.  *  The problem is that whenever a portion of the map needs to be redrawn
1065.  *  (by ^R, after an inventory dropover, after regurgitation...), the
1066.  *  levl[][].scrsym field is used to redraw the map.  A great duplication
1067.  *  of code would be needed to trace back every scrsym to find out what color
1068.  *  it should be.
1069.  *
1070.  *  What is really needed is a levl[][].color field; the color be figured
1071.  *  out at the same time as the screen symbol, and be restored with
1072.  *  redraws.  Unfortunately, as this requires much time and testing,
1073.  *  it will have to wait for NetHack 3.1.  -3.
1074.  */
1075. 
1076. static void
1077. hilite(let,typ)
1078. uchar let, typ;
1079. {
1080. 
1081. 	if (let == ' '
1082. #ifndef MSDOS
1083. 	    || !flags.standout
1084. #endif
1085. 	    ) {
1086. 		/* don't hilite spaces; it's pointless colorwise,
1087. 		   and also hilites secret corridors and dark areas. -3. */
1088. 		g_putch(let);
1089. 		return;
1090. 	}
1091. 
1092. 	if (!typ) {
1093. 		char *isobjct = index(obj_symbols, (char) let);
1094. 
1095. 		if (let == GOLD_SYM)
1096. 			typ = AT_GLD;
1097. #ifdef MSDOSCOLOR
1098. 		else if (let == POOL_SYM)
1099. 			if (HI_BLUE == HI) typ = AT_MAP;
1100. 			else typ = AT_BLUE;
1101. #endif
1102. 		else if (isobjct != NULL || let == S_MIMIC_DEF)
1103. 			/* is an object */
1104. 			typ = AT_OBJ;
1105. 		else if (ismnst((char) let))
1106. 			/* is a monster */
1107. 			typ = AT_MON;
1108. 	}
1109. #ifndef MSDOSCOLOR
1110. 	if (typ == AT_MON) revbeg();
1111. #else
1112. 	switch (typ) {
1113. 	    case AT_MON:
1114. 		xputs(let != S_MIMIC_DEF ? HI_MON : HI_OBJ);
1115. 		break;
1116. 	    case AT_OBJ:
1117. 		xputs(let == GOLD_SYM ? HI_GOLD : HI_OBJ);
1118. 		break;
1119. 	    case AT_MAP:
1120. 		if (!(typ = (let == POOL_SYM)))
1121. 		    break;
1122. 	    case AT_BLUE:
1123. 		xputs(HI_BLUE);
1124. 		break;
1125. 	    case AT_ZAP:
1126. 		xputs(HI_ZAP);
1127. 		break;
1128. 	    case AT_RED:
1129. 		xputs(HI_RED);
1130. 		break;
1131. 	    case AT_WHITE:
1132. 		xputs(HI_WHITE);
1133. 		break;
1134. 	}
1135. #endif
1136. 
1137. 	g_putch(let);
1138. 
1139. #ifdef MSDOSCOLOR
1140. 	if (typ) xputs(HE);
1141. #else
1142. 	if (typ == AT_MON) m_end();
1143. #endif
1144. }
1145. 
1146. static boolean
1147. ismnst(let)
1148. char let;
1149. {
1150. 	register int ct;
1151. 	register struct permonst *ptr;
1152. 
1153. 	if (let & 0x80) return 0;
1154. 	if (isalpha(let)) return 1; /* for speed */
1155. 
1156. 	for (ct = 0 ; ct < NUMMONS; ct++) {
1157. 		ptr = &mons[ct];
1158. 		if(ptr->mlet == let) return 1;
1159. 	}
1160. #ifdef WORM
1161. 	if (let == S_WORM_TAIL) return 1;
1162. #endif
1163. 	return 0;
1164. }
Advertisement