Source:NetHack 3.4.0/allmain.c

From NetHackWiki
Revision as of 12:20, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.4.0/allmain.c moved to Source:NetHack 3.4.0/allmain.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Below is the full text to allmain.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/allmain.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.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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