/*      SCCS Id: @(#)allmain.c  3.1     93/06/16        */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed.  See license for details. */

/* various code that was replicated in *main.c */

#include "hack.h"

#ifndef NO_SIGNAL
#include <signal.h>
#endif

#ifdef OVL0

void
moveloop()
{
#ifdef MICRO
	char ch;
	int abort_lev;
#endif
	char    c;
	int moverate = 0;
	boolean didmove = 0;

	/* Note:  these initializers don't do anything except guarantee that
		we're linked properly.
	*/
	decl_init();
	monst_init();
	monstr_init();  /* monster strengths */
	objects_init();

	(void) encumber_msg(); /* in case they auto-picked up something */

	for(;;) {
#ifdef CLIPPING
		cliparound(u.ux, u.uy);
#endif
#if defined(MAC_MPW32) && !defined(MODEL_FAR)
		UnloadAllSegments();  /* Marks non-resident segments as purgeable */
#endif
		get_nh_event();

		didmove = flags.move;
		if(flags.move) {        /* actual time passed */
#ifdef POLYSELF
		    int oldmtimedone;
#endif
		    int wtcap;

		    if (u.utotype) deferred_goto();
		    wtcap = encumber_msg();
#ifdef POLYSELF
		    oldmtimedone = u.mtimedone;
#endif

#ifdef SOUNDS
		    dosounds();
#endif

		    if(moverate <= 0) {
			/* calculate how much time passed. */
			int moveamt = 0;
			if(Fast & ~INTRINSIC) moveamt = 6;
			else if(Fast) {
				if (pl_character[0] == 'M') {
					moveamt = 12 - (u.ulevel/2);
					if (moveamt < 6) moveamt = 6;
				} else moveamt = 8;
			} else moveamt = 12;

			switch(wtcap) {
			case UNENCUMBERED: break;
			case SLT_ENCUMBER: moveamt = (moveamt * 4) / 3; break;
			case MOD_ENCUMBER: moveamt *= 2; break;
			case HVY_ENCUMBER: moveamt *= 4; break;
			default: moveamt *= 12; break;
			}
			moverate += moveamt;
			settrack();
		    }

		    if(moverate > 0) {
			movemon();
			/* a monster may have levteleported player -dlc */
			if (u.utotype) deferred_goto();
			if(!rn2(u.uevent.udemigod ? 25 :
				(depth(&u.uz) >
				 depth(&stronghold_level))
				? 50 : 70)) {
#ifdef BLACKMARKET
/* random monster creation disabled in black market */
			  if (!Is_blackmarket(&u.uz))
#endif /* BLACKMARKET */
			    (void) makemon((struct permonst *)0, 0, 0);
			  }
			++monstermoves;
			remove_cadavers(&fobj);
			remove_cadavers(&invent);
			moverate -= 12;
		    }
		    if(Glib) glibr();
		    nh_timeout();
		    ++moves;
		    if (u.ublesscnt)  u.ublesscnt--;
		    if (u.usacrifice && !(moves%250)) {
		    u.usacrifice--;
#ifdef WIZARD
		    if (wizard) pline("Sacrifice: %d", u.usacrifice);
#endif
		    }                        
		    if(flags.time) flags.botl = 1;
		    /* One possible result of prayer is healing.  Whether or
		     * not you get healed depends on your current hit points.
		     * If you are allowed to regenerate during the prayer, the
		     * end-of-prayer calculation messes up on this.
		     */
		    if (u.uinvulnerable)
			;
		    else
#ifdef POLYSELF
		    if (u.mtimedone && u.mh < u.mhmax) {
			if (u.mh < 1) {
			    rehumanize();
			    moverate = 0;
			} else if (Regeneration ||
				 (wtcap < MOD_ENCUMBER && !(moves%20))) {
			    flags.botl = 1;
			    u.mh++;
			}
		    } else
#endif
/* STEPHEN WHITE'S NEW CODE
 * [Tom] overhauled the healing code
 * with a CON of 25, heal 0.25% per turn. others proportional.

   stone of healing:  x1.5
   stone of rotting:  divided by 1.5
   regeneration:      x2.5

  also, since release #3 of slash, made hp heal 1.5 times faster. :)

*/
    if(u.uhp < u.uhpmax) {
       int healtime;
       float healpercent;
       int heal_turn;
       int turn_interval;
       int total_points;
       int per_turn;
       float remainder;
       healpercent = (float)(ACURR(A_CON)+25);
       healpercent /= 75.0;
       if (HRegeneration) healpercent *= 2.5;
       if (carrying(STONE_OF_HEALTH)) healpercent *= 1.5;
       if (carrying(STONE_OF_ROTTING)) healpercent /= 1.5;
       if (healpercent < 0.05) healpercent = 0.05;
       /* convert to true percentage */
       healpercent /= 100.0;
       /* how many points you heal a turn (if 1 or greater) */
       heal_turn = (int)((float)u.uhpmax * healpercent);
       if (heal_turn < 1) { /* less than 1 point a turn */
	 /* over 1000 turns, how many points do you heal? */
	 total_points = (int)(u.uhpmax * healpercent * 1000);
	 turn_interval = (int)(1000/total_points);
	 if (!(moves%turn_interval)) {
	    u.uhp++;
	    flags.botl = 1;
	 }
       }
       else {
	  per_turn = (int)(heal_turn+0.5);
	  remainder = ((float)per_turn - ((float)u.uhpmax * healpercent));
	  flags.botl = 1;
	  u.uhp += per_turn;
	  total_points = (int)(remainder * 1000);
	  turn_interval = (int)(1000/total_points);
	  if (!(moves%turn_interval)) u.uhp++;
       }
       if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
    }
		    if (wtcap > MOD_ENCUMBER && flags.mv) {
			if(!(wtcap < EXT_ENCUMBER ? moves%30 : moves%10)) {
			    if(u.uhp > 1) {
				u.uhp--;
			    } else {
				pline("You pass out from exertion!");
				exercise(A_CON, FALSE);
				nomul(-10);
				u.usleep = 1;
			    }
			}
		    }
/* STEPHEN WHITE'S NEW CODE */
		    if ((u.uen < u.uenmax) &&
			((wtcap < MOD_ENCUMBER &&
			  (!(moves%((MAXULEV + 15 - u.ulevel) *
				    (pl_character[0] == 'W' ? 3 : 4) / 2))))
			 || Energy_regeneration)) {
			u.uen +=
			    rn1((int)(ACURR(A_WIS) + ACURR(A_INT)) / 10 + 1,1);
			if (u.uen > u.uenmax)  u.uen = u.uenmax;
			flags.botl = 1;
		    }

		    if(!u.uinvulnerable) {
			if(Teleportation && !rn2(85)) {
#ifdef REDO                 /* clear doagain keystrokes */
			    pushch(0);
			    savech(0);
#endif
			    tele();
			}
#ifdef POLYSELF
			/* [Tom] Dopplegangers don't polymorph unless they
			    want to... */
			if(Polymorph && !rn2(100) && pl_character[0] != 'D') {

			  if (pl_character[0] == 'D' && rn2(6))
			      c = yn("Do you want to polymorph?");
			  else c = 'y';

			  if (c == 'y') {
			      if (multi >= 0) {
				  if (occupation)
				      stop_occupation();
				  else
				      nomul(0);
			      }
			      polyself();
			      moverate = 0;
			  }

			} else if (u.ulycn >= 0 && !rn2(80 - (20 * night()))
				   && !pl_character[0] == 'L') {
			    if (multi >= 0) {
				if (occupation)
				    stop_occupation();
				else
				    nomul(0);
			    }
			    you_were();
			    moverate = 0;
			}
#endif
		    }

		    if(Searching && multi >= 0) (void) dosearch0(1);
		    do_storms();
		    hatch_eggs();
		    burn_lamps();
		    gethungry();
		    exerchk();
		    invault();
		    amulet();
		    if (!rn2(40+(int)(ACURR(A_DEX)*3)))
			u_wipe_engr(rnd(3));
		    if (u.uevent.udemigod && !u.uinvulnerable) {
			if (u.udg_cnt) u.udg_cnt--;
			if (!u.udg_cnt) {
			    intervene();
			    u.udg_cnt = rn1(200, 50);
			}
		    }
		    restore_attrib();
		    /* underwater and waterlevel vision are done here */
		    if (Is_waterlevel(&u.uz))
			movebubbles();
		    else if (Underwater)
			under_water(0);

#ifdef POLYSELF
		    if ((oldmtimedone && !u.mtimedone) ||
			(!oldmtimedone && u.mtimedone)) moverate = 0;
#endif
		}
		if(multi < 0) {
			if(!++multi){
				pline(nomovemsg ? nomovemsg :
					(const char *)"You can move again.");
				nomovemsg = 0;
				u.usleep = 0;
				if(afternmv) (*afternmv)();
				afternmv = 0;
			}
		}

		find_ac();
		if(!flags.mv || Blind) {
		    /* redo monsters if hallu or wearing a helm of telepathy */
		    if (Hallucination ||
			(HTelepat & (WORN_HELMET|WORN_AMUL|W_ART)) ||
			(u.mtimedone && (u.umonnum == PM_MIND_FLAYER ||
			 u.umonnum == PM_FLOATING_EYE)))
				see_monsters();

		    /* redo objects if hallucinating */
		    if (Hallucination) see_objects();

		    /* update swallowed display */
		    if (Hallucination && u.uswallow) swallowed(0);

		    if (vision_full_recalc) vision_recalc(0);   /* vision! */
		}
		if(flags.botl || flags.botlx) bot();

		flags.move = 1;

		if(multi >= 0 && occupation) {
#ifdef MICRO
			abort_lev = 0;
			if (kbhit()) {
				if ((ch = Getchar()) == ABORT)
					abort_lev++;
# ifdef REDO
				else
					pushch(ch);
# endif /* REDO */
			}
			if (!abort_lev && (*occupation)() == 0)
#else
			if ((*occupation)() == 0)
#endif
				occupation = 0;
			if(
#ifdef MICRO
			   abort_lev ||
#endif
			   monster_nearby()) {
				stop_occupation();
				reset_eat();
			}
#ifdef MICRO
			if (!(++occtime % 7))
				display_nhwindow(WIN_MAP, FALSE);
#endif
			continue;
		}

		if((u.uhave.amulet || Clairvoyant) && !In_endgame(&u.uz) &&
						!(moves%15) && !rn2(2))
			do_vicinity_map();

		if(u.utrap && u.utraptype == TT_LAVA) {
		    if(!is_lava(u.ux,u.uy))
			u.utrap = 0;
		    else {
			u.utrap -= 1<<8;
			if(u.utrap < 1<<8) {
			    killer_format = KILLED_BY;
			    killer = "molten lava";
			    You("sink below the surface and suffocate.");
			    done(DROWNING); /*whatever*/
			} else if(didmove && !u.umoved) {
			    Norep("You sink deeper into the lava.");
			    u.utrap += rnd(4);
			}
		    }
		}

		u.umoved = FALSE;
		if(!didmove || moverate <= 0) {
		    if(multi > 0) {
			lookaround();
			if(!multi) {    /* lookaround may clear multi */
				flags.move = 0;
				continue;
			}
			if(flags.mv) {
				if(multi < COLNO && !--multi)
					flags.mv = flags.run = 0;
				domove();
			} else {
				--multi;
				rhack(save_cm);
			}
		    } else if(multi == 0) {
#ifdef MAIL
			ckmailstatus();
#endif
			rhack(NULL);
		    }
		}
		if (vision_full_recalc) vision_recalc(0);       /* vision! */
		if(multi && multi%7 == 0)
			display_nhwindow(WIN_MAP, FALSE);
	}
}

#endif /* OVL0 */
#ifdef OVL1

void
stop_occupation()
{
	if(occupation) {
		You("stop %s.", occtxt);
		occupation = 0;
/* fainting stops your occupation, there's no reason to sync.
		sync_hunger();
*/
#ifdef REDO
		nomul(0);
		pushch(0);
#endif
	}
}

#endif /* OVL1 */
#ifdef OVLB

void
display_gamewindows()
{
    WIN_MESSAGE = create_nhwindow(NHW_MESSAGE);
    WIN_STATUS = create_nhwindow(NHW_STATUS);
    WIN_MAP = create_nhwindow(NHW_MAP);
    WIN_INVEN = create_nhwindow(NHW_MENU);

#ifdef MAC
    /*
     * This _is_ the right place for this - maybe we will
     * have to split display_gamewindows into create_gamewindows
     * and show_gamewindows to get rid of this ifdef...
     */
	if ( ! strcmp ( windowprocs . name , "mac" ) ) {
	    SanePositions ( ) ;
	}
#endif

    /*
     * The mac port is not DEPENDENT on the order of these
     * displays, but it looks a lot better this way...
     */
    display_nhwindow(WIN_STATUS, FALSE);
    display_nhwindow(WIN_MESSAGE, FALSE);
    clear_glyph_buffer();
    display_nhwindow(WIN_MAP, FALSE);
}

void
newgame()
{
#ifdef MFLOPPY
	gameDiskPrompt();
#endif

	fobj = invent = level.buriedobjlist = migrating_objs = (struct obj *)0;
	fmon = migrating_mons = (struct monst *)0;
	ftrap = 0;
	flags.ident = 1;

	init_objects();         /* must be before u_init() */
	u_init();
	/* [Tom] moved down here so Drow quest is initialized right...
	   seems to have no ill effects... */
	if(wiz1_level.dlevel == 0) init_dungeons();
	init_artifacts();       /* must be after u_init() */

#ifndef NO_SIGNAL
	(void) signal(SIGINT, (SIG_RET_TYPE) done1);
#endif
#ifdef NEWS
	if(flags.news) display_file(NEWS, FALSE);
#endif
#ifdef MULDGN
	load_qtlist();  /* load up the quest text info */
	quest_init();
	if(flags.legacy && moves == 1) com_pager(1);
#endif
	mklev();
	u_on_upstairs();
	check_special_room(FALSE);
	vision_reset();         /* set up internals for level (after mklev) */

	flags.botlx = 1;

	/* Move the monster from under you or else
	 * makedog() will fail when it calls makemon().
	 *                      - ucsfcgl!kneller
	 */
	if(MON_AT(u.ux, u.uy)) mnexto(m_at(u.ux, u.uy));

#ifdef CLIPPING
	cliparound(u.ux, u.uy);
#endif
	(void) makedog();
	docrt();

#ifdef INSURANCE
	save_currentstate();
#endif
	return;
}

#endif /* OVLB */

/*allmain.c*/
