Source:NetHack 3.4.3/src/allmain.c

From NetHackWiki
Revision as of 23:42, 14 June 2006 by Jaytbot (talk | contribs) (Automated import of articles)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Below is the full text to src/allmain.c from NetHack 3.4.3. To link to a particular line, write [[allmain.c#line123]], for example.

1.    /*	SCCS Id: @(#)allmain.c	3.4	2003/04/02	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    /* various code that was replicated in *main.c */
6.    
7.    #include "hack.h"
8.    
9.    #ifndef NO_SIGNAL
10.   #include <signal.h>
11.   #endif
12.   
13.   #ifdef POSITIONBAR
14.   STATIC_DCL void NDECL(do_positionbar);
15.   #endif
16.   
17.   #ifdef OVL0
18.   
19.   void
20.   moveloop()
21.   {
22.   #if defined(MICRO) || defined(WIN32)
23.       char ch;
24.       int abort_lev;
25.   #endif
26.       int moveamt = 0, wtcap = 0, change = 0;
27.       boolean didmove = FALSE, monscanmove = FALSE;
28.   
29.       flags.moonphase = phase_of_the_moon();
30.       if(flags.moonphase == FULL_MOON) {
31.   	You("are lucky!  Full moon tonight.");
32.   	change_luck(1);
33.       } else if(flags.moonphase == NEW_MOON) {
34.   	pline("Be careful!  New moon tonight.");
35.       }
36.       flags.friday13 = friday_13th();
37.       if (flags.friday13) {
38.   	pline("Watch out!  Bad things can happen on Friday the 13th.");
39.   	change_luck(-1);
40.       }
41.   
42.       initrack();
43.   
44.   
45.       /* Note:  these initializers don't do anything except guarantee that
46.   	    we're linked properly.
47.       */
48.       decl_init();
49.       monst_init();
50.       monstr_init();	/* monster strengths */
51.       objects_init();
52.   
53.   #ifdef WIZARD
54.       if (wizard) add_debug_extended_commands();
55.   #endif
56.   
57.       (void) encumber_msg(); /* in case they auto-picked up something */
58.   
59.       u.uz0.dlevel = u.uz.dlevel;
60.       youmonst.movement = NORMAL_SPEED;	/* give the hero some movement points */
61.   
62.       for(;;) {
63.   	get_nh_event();
64.   #ifdef POSITIONBAR
65.   	do_positionbar();
66.   #endif
67.   
68.   	didmove = flags.move;
69.   	if(didmove) {
70.   	    /* actual time passed */
71.   	    youmonst.movement -= NORMAL_SPEED;
72.   
73.   	    do { /* hero can't move this turn loop */
74.   		wtcap = encumber_msg();
75.   
76.   		flags.mon_moving = TRUE;
77.   		do {
78.   		    monscanmove = movemon();
79.   		    if (youmonst.movement > NORMAL_SPEED)
80.   			break;	/* it's now your turn */
81.   		} while (monscanmove);
82.   		flags.mon_moving = FALSE;
83.   
84.   		if (!monscanmove && youmonst.movement < NORMAL_SPEED) {
85.   		    /* both you and the monsters are out of steam this round */
86.   		    /* set up for a new turn */
87.   		    struct monst *mtmp;
88.   		    mcalcdistress();	/* adjust monsters' trap, blind, etc */
89.   
90.   		    /* reallocate movement rations to monsters */
91.   		    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
92.   			mtmp->movement += mcalcmove(mtmp);
93.   
94.   		    if(!rn2(u.uevent.udemigod ? 25 :
95.   			    (depth(&u.uz) > depth(&stronghold_level)) ? 50 : 70))
96.   			(void) makemon((struct permonst *)0, 0, 0, NO_MM_FLAGS);
97.   
98.   		    /* calculate how much time passed. */
99.   #ifdef STEED
100.  		    if (u.usteed && u.umoved) {
101.  			/* your speed doesn't augment steed's speed */
102.  			moveamt = mcalcmove(u.usteed);
103.  		    } else
104.  #endif
105.  		    {
106.  			moveamt = youmonst.data->mmove;
107.  
108.  			if (Very_fast) {	/* speed boots or potion */
109.  			    /* average movement is 1.67 times normal */
110.  			    moveamt += NORMAL_SPEED / 2;
111.  			    if (rn2(3) == 0) moveamt += NORMAL_SPEED / 2;
112.  			} else if (Fast) {
113.  			    /* average movement is 1.33 times normal */
114.  			    if (rn2(3) != 0) moveamt += NORMAL_SPEED / 2;
115.  			}
116.  		    }
117.  
118.  		    switch (wtcap) {
119.  			case UNENCUMBERED: break;
120.  			case SLT_ENCUMBER: moveamt -= (moveamt / 4); break;
121.  			case MOD_ENCUMBER: moveamt -= (moveamt / 2); break;
122.  			case HVY_ENCUMBER: moveamt -= ((moveamt * 3) / 4); break;
123.  			case EXT_ENCUMBER: moveamt -= ((moveamt * 7) / 8); break;
124.  			default: break;
125.  		    }
126.  
127.  		    youmonst.movement += moveamt;
128.  		    if (youmonst.movement < 0) youmonst.movement = 0;
129.  		    settrack();
130.  
131.  		    monstermoves++;
132.  		    moves++;
133.  
134.  		    /********************************/
135.  		    /* once-per-turn things go here */
136.  		    /********************************/
137.  
138.  		    if (flags.bypasses) clear_bypasses();
139.  		    if(Glib) glibr();
140.  		    nh_timeout();
141.  		    run_regions();
142.  
143.  		    if (u.ublesscnt)  u.ublesscnt--;
144.  		    if(flags.time && !flags.run)
145.  			flags.botl = 1;
146.  
147.  		    /* One possible result of prayer is healing.  Whether or
148.  		     * not you get healed depends on your current hit points.
149.  		     * If you are allowed to regenerate during the prayer, the
150.  		     * end-of-prayer calculation messes up on this.
151.  		     * Another possible result is rehumanization, which requires
152.  		     * that encumbrance and movement rate be recalculated.
153.  		     */
154.  		    if (u.uinvulnerable) {
155.  			/* for the moment at least, you're in tiptop shape */
156.  			wtcap = UNENCUMBERED;
157.  		    } else if (Upolyd && youmonst.data->mlet == S_EEL && !is_pool(u.ux,u.uy) && !Is_waterlevel(&u.uz)) {
158.  			if (u.mh > 1) {
159.  			    u.mh--;
160.  			    flags.botl = 1;
161.  			} else if (u.mh < 1)
162.  			    rehumanize();
163.  		    } else if (Upolyd && u.mh < u.mhmax) {
164.  			if (u.mh < 1)
165.  			    rehumanize();
166.  			else if (Regeneration ||
167.  				    (wtcap < MOD_ENCUMBER && !(moves%20))) {
168.  			    flags.botl = 1;
169.  			    u.mh++;
170.  			}
171.  		    } else if (u.uhp < u.uhpmax &&
172.  			 (wtcap < MOD_ENCUMBER || !u.umoved || Regeneration)) {
173.  			if (u.ulevel > 9 && !(moves % 3)) {
174.  			    int heal, Con = (int) ACURR(A_CON);
175.  
176.  			    if (Con <= 12) {
177.  				heal = 1;
178.  			    } else {
179.  				heal = rnd(Con);
180.  				if (heal > u.ulevel-9) heal = u.ulevel-9;
181.  			    }
182.  			    flags.botl = 1;
183.  			    u.uhp += heal;
184.  			    if(u.uhp > u.uhpmax)
185.  				u.uhp = u.uhpmax;
186.  			} else if (Regeneration ||
187.  			     (u.ulevel <= 9 &&
188.  			      !(moves % ((MAXULEV+12) / (u.ulevel+2) + 1)))) {
189.  			    flags.botl = 1;
190.  			    u.uhp++;
191.  			}
192.  		    }
193.  
194.  		    /* moving around while encumbered is hard work */
195.  		    if (wtcap > MOD_ENCUMBER && u.umoved) {
196.  			if(!(wtcap < EXT_ENCUMBER ? moves%30 : moves%10)) {
197.  			    if (Upolyd && u.mh > 1) {
198.  				u.mh--;
199.  			    } else if (!Upolyd && u.uhp > 1) {
200.  				u.uhp--;
201.  			    } else {
202.  				You("pass out from exertion!");
203.  				exercise(A_CON, FALSE);
204.  				fall_asleep(-10, FALSE);
205.  			    }
206.  			}
207.  		    }
208.  
209.  		    if ((u.uen < u.uenmax) &&
210.  			((wtcap < MOD_ENCUMBER &&
211.  			  (!(moves%((MAXULEV + 8 - u.ulevel) *
212.  				    (Role_if(PM_WIZARD) ? 3 : 4) / 6))))
213.  			 || Energy_regeneration)) {
214.  			u.uen += rn1((int)(ACURR(A_WIS) + ACURR(A_INT)) / 15 + 1,1);
215.  			if (u.uen > u.uenmax)  u.uen = u.uenmax;
216.  			flags.botl = 1;
217.  		    }
218.  
219.  		    if(!u.uinvulnerable) {
220.  			if(Teleportation && !rn2(85)) {
221.  			    xchar old_ux = u.ux, old_uy = u.uy;
222.  			    tele();
223.  			    if (u.ux != old_ux || u.uy != old_uy) {
224.  				if (!next_to_u()) {
225.  				    check_leash(old_ux, old_uy);
226.  				}
227.  #ifdef REDO
228.  				/* clear doagain keystrokes */
229.  				pushch(0);
230.  				savech(0);
231.  #endif
232.  			    }
233.  			}
234.  			/* delayed change may not be valid anymore */
235.  			if ((change == 1 && !Polymorph) ||
236.  			    (change == 2 && u.ulycn == NON_PM))
237.  			    change = 0;
238.  			if(Polymorph && !rn2(100))
239.  			    change = 1;
240.  			else if (u.ulycn >= LOW_PM && !Upolyd &&
241.  				 !rn2(80 - (20 * night())))
242.  			    change = 2;
243.  			if (change && !Unchanging) {
244.  			    if (multi >= 0) {
245.  				if (occupation)
246.  				    stop_occupation();
247.  				else
248.  				    nomul(0);
249.  				if (change == 1) polyself(FALSE);
250.  				else you_were();
251.  				change = 0;
252.  			    }
253.  			}
254.  		    }
255.  
256.  		    if(Searching && multi >= 0) (void) dosearch0(1);
257.  		    dosounds();
258.  		    do_storms();
259.  		    gethungry();
260.  		    age_spells();
261.  		    exerchk();
262.  		    invault();
263.  		    if (u.uhave.amulet) amulet();
264.  		    if (!rn2(40+(int)(ACURR(A_DEX)*3)))
265.  			u_wipe_engr(rnd(3));
266.  		    if (u.uevent.udemigod && !u.uinvulnerable) {
267.  			if (u.udg_cnt) u.udg_cnt--;
268.  			if (!u.udg_cnt) {
269.  			    intervene();
270.  			    u.udg_cnt = rn1(200, 50);
271.  			}
272.  		    }
273.  		    restore_attrib();
274.  		    /* underwater and waterlevel vision are done here */
275.  		    if (Is_waterlevel(&u.uz))
276.  			movebubbles();
277.  		    else if (Underwater)
278.  			under_water(0);
279.  		    /* vision while buried done here */
280.  		    else if (u.uburied) under_ground(0);
281.  
282.  		    /* when immobile, count is in turns */
283.  		    if(multi < 0) {
284.  			if (++multi == 0) {	/* finished yet? */
285.  			    unmul((char *)0);
286.  			    /* if unmul caused a level change, take it now */
287.  			    if (u.utotype) deferred_goto();
288.  			}
289.  		    }
290.  		}
291.  	    } while (youmonst.movement<NORMAL_SPEED); /* hero can't move loop */
292.  
293.  	    /******************************************/
294.  	    /* once-per-hero-took-time things go here */
295.  	    /******************************************/
296.  
297.  
298.  	} /* actual time passed */
299.  
300.  	/****************************************/
301.  	/* once-per-player-input things go here */
302.  	/****************************************/
303.  
304.  	find_ac();
305.  	if(!flags.mv || Blind) {
306.  	    /* redo monsters if hallu or wearing a helm of telepathy */
307.  	    if (Hallucination) {	/* update screen randomly */
308.  		see_monsters();
309.  		see_objects();
310.  		see_traps();
311.  		if (u.uswallow) swallowed(0);
312.  	    } else if (Unblind_telepat) {
313.  		see_monsters();
314.  	    } else if (Warning || Warn_of_mon)
315.  	     	see_monsters();
316.  
317.  	    if (vision_full_recalc) vision_recalc(0);	/* vision! */
318.  	}
319.  	if(flags.botl || flags.botlx) bot();
320.  
321.  	flags.move = 1;
322.  
323.  	if(multi >= 0 && occupation) {
324.  #if defined(MICRO) || defined(WIN32)
325.  	    abort_lev = 0;
326.  	    if (kbhit()) {
327.  		if ((ch = Getchar()) == ABORT)
328.  		    abort_lev++;
329.  # ifdef REDO
330.  		else
331.  		    pushch(ch);
332.  # endif /* REDO */
333.  	    }
334.  	    if (!abort_lev && (*occupation)() == 0)
335.  #else
336.  	    if ((*occupation)() == 0)
337.  #endif
338.  		occupation = 0;
339.  	    if(
340.  #if defined(MICRO) || defined(WIN32)
341.  		   abort_lev ||
342.  #endif
343.  		   monster_nearby()) {
344.  		stop_occupation();
345.  		reset_eat();
346.  	    }
347.  #if defined(MICRO) || defined(WIN32)
348.  	    if (!(++occtime % 7))
349.  		display_nhwindow(WIN_MAP, FALSE);
350.  #endif
351.  	    continue;
352.  	}
353.  
354.  	if ((u.uhave.amulet || Clairvoyant) &&
355.  	    !In_endgame(&u.uz) && !BClairvoyant &&
356.  	    !(moves % 15) && !rn2(2))
357.  		do_vicinity_map();
358.  
359.  	if(u.utrap && u.utraptype == TT_LAVA) {
360.  	    if(!is_lava(u.ux,u.uy))
361.  		u.utrap = 0;
362.  	    else if (!u.uinvulnerable) {
363.  		u.utrap -= 1<<8;
364.  		if(u.utrap < 1<<8) {
365.  		    killer_format = KILLED_BY;
366.  		    killer = "molten lava";
367.  		    You("sink below the surface and die.");
368.  		    done(DISSOLVED);
369.  		} else if(didmove && !u.umoved) {
370.  		    Norep("You sink deeper into the lava.");
371.  		    u.utrap += rnd(4);
372.  		}
373.  	    }
374.  	}
375.  
376.  #ifdef WIZARD
377.  	if (iflags.sanity_check)
378.  	    sanity_check();
379.  #endif
380.  
381.  #ifdef CLIPPING
382.  	/* just before rhack */
383.  	cliparound(u.ux, u.uy);
384.  #endif
385.  
386.  	u.umoved = FALSE;
387.  
388.  	if (multi > 0) {
389.  	    lookaround();
390.  	    if (!multi) {
391.  		/* lookaround may clear multi */
392.  		flags.move = 0;
393.  		if (flags.time) flags.botl = 1;
394.  		continue;
395.  	    }
396.  	    if (flags.mv) {
397.  		if(multi < COLNO && !--multi)
398.  		    flags.travel = iflags.travel1 = flags.mv = flags.run = 0;
399.  		domove();
400.  	    } else {
401.  		--multi;
402.  		rhack(save_cm);
403.  	    }
404.  	} else if (multi == 0) {
405.  #ifdef MAIL
406.  	    ckmailstatus();
407.  #endif
408.  	    rhack((char *)0);
409.  	}
410.  	if (u.utotype)		/* change dungeon level */
411.  	    deferred_goto();	/* after rhack() */
412.  	/* !flags.move here: multiple movement command stopped */
413.  	else if (flags.time && (!flags.move || !flags.mv))
414.  	    flags.botl = 1;
415.  
416.  	if (vision_full_recalc) vision_recalc(0);	/* vision! */
417.  	/* when running in non-tport mode, this gets done through domove() */
418.  	if ((!flags.run || iflags.runmode == RUN_TPORT) &&
419.  		(multi && (!flags.travel ? !(multi % 7) : !(moves % 7L)))) {
420.  	    if (flags.time && flags.run) flags.botl = 1;
421.  	    display_nhwindow(WIN_MAP, FALSE);
422.  	}
423.      }
424.  }
425.  
426.  #endif /* OVL0 */
427.  #ifdef OVL1
428.  
429.  void
430.  stop_occupation()
431.  {
432.  	if(occupation) {
433.  		if (!maybe_finished_meal(TRUE))
434.  		    You("stop %s.", occtxt);
435.  		occupation = 0;
436.  		flags.botl = 1; /* in case u.uhs changed */
437.  /* fainting stops your occupation, there's no reason to sync.
438.  		sync_hunger();
439.  */
440.  #ifdef REDO
441.  		nomul(0);
442.  		pushch(0);
443.  #endif
444.  	}
445.  }
446.  
447.  #endif /* OVL1 */
448.  #ifdef OVLB
449.  
450.  void
451.  display_gamewindows()
452.  {
453.      WIN_MESSAGE = create_nhwindow(NHW_MESSAGE);
454.      WIN_STATUS = create_nhwindow(NHW_STATUS);
455.      WIN_MAP = create_nhwindow(NHW_MAP);
456.      WIN_INVEN = create_nhwindow(NHW_MENU);
457.  
458.  #ifdef MAC
459.      /*
460.       * This _is_ the right place for this - maybe we will
461.       * have to split display_gamewindows into create_gamewindows
462.       * and show_gamewindows to get rid of this ifdef...
463.       */
464.  	if ( ! strcmp ( windowprocs . name , "mac" ) ) {
465.  	    SanePositions ( ) ;
466.  	}
467.  #endif
468.  
469.      /*
470.       * The mac port is not DEPENDENT on the order of these
471.       * displays, but it looks a lot better this way...
472.       */
473.      display_nhwindow(WIN_STATUS, FALSE);
474.      display_nhwindow(WIN_MESSAGE, FALSE);
475.      clear_glyph_buffer();
476.      display_nhwindow(WIN_MAP, FALSE);
477.  }
478.  
479.  void
480.  newgame()
481.  {
482.  	int i;
483.  
484.  #ifdef MFLOPPY
485.  	gameDiskPrompt();
486.  #endif
487.  
488.  	flags.ident = 1;
489.  
490.  	for (i = 0; i < NUMMONS; i++)
491.  		mvitals[i].mvflags = mons[i].geno & G_NOCORPSE;
492.  
493.  	init_objects();		/* must be before u_init() */
494.  
495.  	flags.pantheon = -1;	/* role_init() will reset this */
496.  	role_init();		/* must be before init_dungeons(), u_init(),
497.  				 * and init_artifacts() */
498.  
499.  	init_dungeons();	/* must be before u_init() to avoid rndmonst()
500.  				 * creating odd monsters for any tins and eggs
501.  				 * in hero's initial inventory */
502.  	init_artifacts();	/* before u_init() in case $WIZKIT specifies
503.  				 * any artifacts */
504.  	u_init();
505.  
506.  #ifndef NO_SIGNAL
507.  	(void) signal(SIGINT, (SIG_RET_TYPE) done1);
508.  #endif
509.  #ifdef NEWS
510.  	if(iflags.news) display_file(NEWS, FALSE);
511.  #endif
512.  	load_qtlist();	/* load up the quest text info */
513.  /*	quest_init();*/	/* Now part of role_init() */
514.  
515.  	mklev();
516.  	u_on_upstairs();
517.  	vision_reset();		/* set up internals for level (after mklev) */
518.  	check_special_room(FALSE);
519.  
520.  	flags.botlx = 1;
521.  
522.  	/* Move the monster from under you or else
523.  	 * makedog() will fail when it calls makemon().
524.  	 *			- ucsfcgl!kneller
525.  	 */
526.  	if(MON_AT(u.ux, u.uy)) mnexto(m_at(u.ux, u.uy));
527.  	(void) makedog();
528.  	docrt();
529.  
530.  	if (flags.legacy) {
531.  		flush_screen(1);
532.  		com_pager(1);
533.  	}
534.  
535.  #ifdef INSURANCE
536.  	save_currentstate();
537.  #endif
538.  	program_state.something_worth_saving++;	/* useful data now exists */
539.  
540.  	/* Success! */
541.  	welcome(TRUE);
542.  	return;
543.  }
544.  
545.  /* show "welcome [back] to nethack" message at program startup */
546.  void
547.  welcome(new_game)
548.  boolean new_game;	/* false => restoring an old game */
549.  {
550.      char buf[BUFSZ];
551.      boolean currentgend = Upolyd ? u.mfemale : flags.female;
552.  
553.      /*
554.       * The "welcome back" message always describes your innate form
555.       * even when polymorphed or wearing a helm of opposite alignment.
556.       * Alignment is shown unconditionally for new games; for restores
557.       * it's only shown if it has changed from its original value.
558.       * Sex is shown for new games except when it is redundant; for
559.       * restores it's only shown if different from its original value.
560.       */
561.      *buf = '\0';
562.      if (new_game || u.ualignbase[A_ORIGINAL] != u.ualignbase[A_CURRENT])
563.  	Sprintf(eos(buf), " %s", align_str(u.ualignbase[A_ORIGINAL]));
564.      if (!urole.name.f &&
565.  	    (new_game ? (urole.allow & ROLE_GENDMASK) == (ROLE_MALE|ROLE_FEMALE) :
566.  	     currentgend != flags.initgend))
567.  	Sprintf(eos(buf), " %s", genders[currentgend].adj);
568.  
569.      pline(new_game ? "%s %s, welcome to NetHack!  You are a%s %s %s."
570.  		   : "%s %s, the%s %s %s, welcome back to NetHack!",
571.  	  Hello((struct monst *) 0), plname, buf, urace.adj,
572.  	  (currentgend && urole.name.f) ? urole.name.f : urole.name.m);
573.  }
574.  
575.  #ifdef POSITIONBAR
576.  STATIC_DCL void
577.  do_positionbar()
578.  {
579.  	static char pbar[COLNO];
580.  	char *p;
581.  	
582.  	p = pbar;
583.  	/* up stairway */
584.  	if (upstair.sx &&
585.  	   (glyph_to_cmap(level.locations[upstair.sx][upstair.sy].glyph) ==
586.  	    S_upstair ||
587.   	    glyph_to_cmap(level.locations[upstair.sx][upstair.sy].glyph) ==
588.  	    S_upladder)) {
589.  		*p++ = '<';
590.  		*p++ = upstair.sx;
591.  	}
592.  	if (sstairs.sx &&
593.  	   (glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph) ==
594.  	    S_upstair ||
595.   	    glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph) ==
596.  	    S_upladder)) {
597.  		*p++ = '<';
598.  		*p++ = sstairs.sx;
599.  	}
600.  
601.  	/* down stairway */
602.  	if (dnstair.sx &&
603.  	   (glyph_to_cmap(level.locations[dnstair.sx][dnstair.sy].glyph) ==
604.  	    S_dnstair ||
605.   	    glyph_to_cmap(level.locations[dnstair.sx][dnstair.sy].glyph) ==
606.  	    S_dnladder)) {
607.  		*p++ = '>';
608.  		*p++ = dnstair.sx;
609.  	}
610.  	if (sstairs.sx &&
611.  	   (glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph) ==
612.  	    S_dnstair ||
613.   	    glyph_to_cmap(level.locations[sstairs.sx][sstairs.sy].glyph) ==
614.  	    S_dnladder)) {
615.  		*p++ = '>';
616.  		*p++ = sstairs.sx;
617.  	}
618.  
619.  	/* hero location */
620.  	if (u.ux) {
621.  		*p++ = '@';
622.  		*p++ = u.ux;
623.  	}
624.  	/* fence post */
625.  	*p = 0;
626.  
627.  	update_positionbar(pbar);
628.  }
629.  #endif
630.  
631.  #endif /* OVLB */
632.  
633.  /*allmain.c*/