view arogue5/command.c @ 107:f2951c4e28d9

Rename daemon() to start_daemon(). daemon() conflicted with the standard library function, which is included by default on OS X.
author John "Elwin" Edwards
date Sat, 07 Sep 2013 08:08:00 -0400
parents dfeed24bb616
children a0a57cf42810
line wrap: on
line source

/*
 * Read and execute the user commands
 *
 * Advanced Rogue
 * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
 * All rights reserved.
 *
 * Based on "Rogue: Exploring the Dungeons of Doom"
 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
 * All rights reserved.
 *
 * See the file LICENSE.TXT for full copyright and licensing information.
 */

#include "curses.h"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <signal.h>
#include "rogue.h"
#include "mach_dep.h"

/*
 * command:
 *	Process the user commands
 */

command()
{
    register char ch;
    register int ntimes = 1;			/* Number of player moves */
    static char countch, direction, newcount = FALSE;
    struct linked_list *item;
    bool an_after = FALSE;

    if (on(player, ISHASTE)) {
	ntimes++;
	turns--;	/* correct for later */
    }
    if (on(player, ISSLOW) || on(player, ISDANCE)) {
	if (player.t_turn != TRUE) {
	    ntimes--;
	    turns++;
	    an_after = TRUE;
	}
	player.t_turn ^= TRUE;
    }

    /*
     * Let the daemons start up
     */
    do_daemons(BEFORE);
    do_fuses(BEFORE);
    while (ntimes-- > 0)
    {	
	/* One more tick of the clock. */
	if ((++turns % DAYLENGTH) == 0) {
	    daytime ^= TRUE;
	    if (levtype == OUTSIDE) {
		if (daytime) msg("The sun rises above the horizon");
		else msg("The sun sinks below the horizon");
	    }
	    light(&hero);
	}

	look(after, FALSE);
	if (!running) door_stop = FALSE;
	lastscore = purse;
	wmove(cw, hero.y, hero.x);
	if (!((running || count) && jump)) {
	    status(FALSE);
	    wmove(cw, hero.y, hero.x);
	    draw(cw);			/* Draw screen */
	}
	take = 0;
	after = TRUE;
	/*
	 * Read command or continue run
	 */
	if (!no_command)
	{
	    if (running) {
		/* If in a corridor or maze, if we are at a turn with only one
		 * way to go, turn that way.
		 */
		if ((winat(hero.y, hero.x) == PASSAGE || levtype == MAZELEV) &&
		    off(player, ISHUH) && (off(player, ISBLIND))) {
		    int y, x;
		    if (getdelta(runch, &y, &x) == TRUE) {
			corr_move(y, x);
		    }
		}
	        ch = runch;
	    }
	    else if (count) ch = countch;
	    else
	    {
		ch = readchar();
		if (mpos != 0 && !running)	/* Erase message if its there */
		    msg("");
	    }
	}
	else ch = '.';
	if (no_command)
	{
	    if (--no_command == 0)
		msg("You can move again.");
	}
	else
	{
	    /*
	     * check for prefixes
	     */
	    if (isdigit(ch))
	    {
		count = 0;
		newcount = TRUE;
		while (isdigit(ch))
		{
		    count = count * 10 + (ch - '0');
		    if (count > 255)
			count = 255;
		    ch = readchar();
		}
		countch = ch;
		/*
		 * turn off count for commands which don't make sense
		 * to repeat
		 */
		switch (ch) {
		    case 'h': case 'j': case 'k': case 'l':
		    case 'y': case 'u': case 'b': case 'n':
		    case 'H': case 'J': case 'K': case 'L':
		    case 'Y': case 'U': case 'B': case 'N':
		    case 'q': case 'r': case 's': case 'f':
		    case 't': case 'C': case 'I': case '.':
		    case 'z': case 'p':
			break;
		    default:
			count = 0;
		}
	    }

	    /* Save current direction */
	    if (!running) /* If running, it is already saved */
	    switch (ch) {
		case 'h': case 'j': case 'k': case 'l':
		case 'y': case 'u': case 'b': case 'n':
		case 'H': case 'J': case 'K': case 'L':
		case 'Y': case 'U': case 'B': case 'N':
		    runch = tolower(ch);
	    }

	    /* Perform the action */
	    switch (ch) {
		case 'f':
		    if (!on(player, ISBLIND))
		    {
			door_stop = TRUE;
			firstmove = TRUE;
		    }
		    if (count && !newcount)
			ch = direction;
		    else
			ch = readchar();
		    switch (ch)
		    {
			case 'h': case 'j': case 'k': case 'l':
			case 'y': case 'u': case 'b': case 'n':
			    ch = toupper(ch);
		    }
		    direction = ch;
	    }
	    newcount = FALSE;
	    /*
	     * execute a command
	     */
	    if (count && !running)
		count--;
	    switch (ch)
	    {
		case '!' : shell();
		when 'h' : do_move(0, -1);
		when 'j' : do_move(1, 0);
		when 'k' : do_move(-1, 0);
		when 'l' : do_move(0, 1);
		when 'y' : do_move(-1, -1);
		when 'u' : do_move(-1, 1);
		when 'b' : do_move(1, -1);
		when 'n' : do_move(1, 1);
		when 'H' : do_run('h');
		when 'J' : do_run('j');
		when 'K' : do_run('k');
		when 'L' : do_run('l');
		when 'Y' : do_run('y');
		when 'U' : do_run('u');
		when 'B' : do_run('b');
		when 'N' : do_run('n');
		when 't':
		    if((item=get_item(pack,"throw", ALL)) != NULL && get_dir())
			missile(delta.y, delta.x, item, &player);
		    else
			after = FALSE;
		when 'Q' : after = FALSE; quit(-1);
		when 'i' : after = FALSE; inventory(pack, ALL);
		when 'I' : after = FALSE; picky_inven();
		when 'd' : drop(NULL);
		when 'P' : grab(hero.y, hero.x);
		when 'q' : quaff(-1, NULL, TRUE);
		when 'r' : read_scroll(-1, NULL, TRUE);
		when 'e' : eat();
		when 'w' : wield();
		when 'W' : wear();
		when 'T' : take_off();
		when 'o' : option();
		when 'c' : call(FALSE);
		when 'm' : call(TRUE);
		when '>' : after = FALSE; d_level();
		when '<' : after = FALSE; u_level();
		when '?' : after = FALSE; help();
		when '/' : after = FALSE; identify();
		when CTRL('U') : use_mm(-1);
		when CTRL('T') :
		    if (get_dir()) steal();
		    else after = FALSE;
		when 'D' : dip_it();
		when 'G' : gsense();
		when '^' : set_trap(&player, hero.y, hero.x);
		when 's' : search(FALSE, FALSE);
		when 'z' : if (!do_zap(TRUE, NULL, FALSE))
				after=FALSE;
		when 'p' : pray();
		when 'C' : cast();
		when 'a' :
		    if (get_dir())
			affect();
		    else after = FALSE;
		when 'v' : after = FALSE;
			   msg("Advanced Rogue Version %s.",
				release);
		when CTRL('L') : after = FALSE; clearok(curscr, TRUE);
				touchwin(cw); /* MMMMMMMMMM */
		when CTRL('R') : after = FALSE; msg(huh);
		when 'S' : 
		    after = FALSE;
		    if (save_game())
		    {
			wclear(cw);
			draw(cw);
			endwin();
			printf("\n");
			exit(0);
		    }
		when '.' : ;			/* Rest command */
		when ' ' : after = FALSE;	/* Do Nothing */
#ifdef WIZARD
		when CTRL('P') :
		    after = FALSE;
		    if (wizard)
		    {
			wizard = FALSE;
			trader = 0;
			msg("Not wizard any more");
		    }
		    else
		    {
			if (waswizard || passwd())
			{
			    msg("Welcome, oh mighty wizard.");
			    wizard = waswizard = TRUE;
			}
			else
			    msg("Sorry");
		    }
#endif
		when ESCAPE :	/* Escape */
		    door_stop = FALSE;
		    count = 0;
		    after = FALSE;
		when '#':
		    if (levtype == POSTLEV)		/* buy something */
			buy_it();
		    after = FALSE;
		when '$':
		    if (levtype == POSTLEV)		/* price something */
			price_it();
		    after = FALSE;
		when '%':
		    if (levtype == POSTLEV)		/* sell something */
			sell_it();
		    after = FALSE;
		otherwise :
		    after = FALSE;
#ifdef WIZARD
		    if (wizard) switch (ch)
		    {
			case 'M' : create_obj(TRUE, 0, 0);
			when CTRL('W') : wanderer();
			when CTRL('I') : inventory(lvl_obj, ALL);
			when CTRL('Z') : whatis(NULL);
			when CTRL('D') : level++; new_level(NORMLEV);
			when CTRL('F') : overlay(stdscr,cw);
			when CTRL('X') : overlay(mw,cw);
			when CTRL('J') : teleport();
			when CTRL('E') : sprintf(outstring,"food left: %d\tfood level: %d", 
						food_left, foodlev);
				       msg(outstring);
			when CTRL('A') : activity();
			when CTRL('C') : 
			{
			    int tlev;
			    prbuf[0] = '\0';
			    msg("Which level? ");
			    if(get_str(prbuf, msgw) == NORM) {
				tlev = atoi(prbuf);
				if(tlev < 1) {
				    mpos = 0;
				    msg("Illegal level.");
				}
				else if (tlev > 199) {
					levtype = MAZELEV;
					level = tlev - 200 + 1;
				}
				else if (tlev > 99) {
					levtype = POSTLEV;
					level = tlev - 100 + 1;
				} 
				else {
					levtype = NORMLEV;
					level = tlev;
				}
				new_level(levtype);
			    }
			}
			when CTRL('N') :
			{
			    if ((item=get_item(pack, "charge", STICK)) != NULL){
				(OBJPTR(item))->o_charges=10000;
			    }
			}
			when CTRL('H') :
			{
			    register int i;
			    register struct object *obj;

			    for (i = 0; i < 9; i++)
				raise_level(TRUE);
			    /*
			     * Give the rogue a sword 
			     */
			    if(cur_weapon==NULL || cur_weapon->o_type!=RELIC) {
				item = spec_item(WEAPON, TWOSWORD, 5, 5);
				add_pack(item, TRUE, NULL);
				cur_weapon = OBJPTR(item);
				cur_weapon->o_flags |= (ISKNOW | ISPROT);
			    }
			    /*
			     * And his suit of armor
			     */
			    if (player.t_ctype == C_THIEF)
				item = spec_item(ARMOR, STUDDED_LEATHER, 10, 0);
			    else
				item = spec_item(ARMOR, PLATE_ARMOR, 7, 0);
			    obj = OBJPTR(item);
			    obj->o_flags |= (ISKNOW | ISPROT);
			    obj->o_weight = armors[PLATE_ARMOR].a_wght;
			    cur_armor = obj;
			    add_pack(item, TRUE, NULL);
			    purse += 20000;
			}
			otherwise :
			    msg("Illegal command '%s'.", unctrl(ch));
			    count = 0;
		    }
		    else
#endif
		    {
			msg("Illegal command '%s'.", unctrl(ch));
			count = 0;
			after = FALSE;
		    }
	    }
	    /*
	     * turn off flags if no longer needed
	     */
	    if (!running)
		door_stop = FALSE;
	}
	/*
	 * If he ran into something to take, let him pick it up.
	 * unless its a trading post
	 */
	if (auto_pickup && take != 0 && levtype != POSTLEV)
	    pick_up(take);
	if (!running)
	    door_stop = FALSE;

	/* If after is true, mark an_after as true so that if
	 * we are hasted, the first "after" will be noted.
	 * if after is FALSE then stay in this loop
	 */
	if (after) an_after = TRUE;
	else ntimes++;
    }

    /*
     * Kick off the rest if the daemons and fuses
     */
    if (an_after)
    {
	/* 
	 * If player is infested, take off a hit point 
	 */
	if (on(player, HASINFEST)) {
	    if ((pstats.s_hpt -= infest_dam) <= 0) death(D_INFESTATION);
	}
	/* 
	 * if player has body rot then take off five hits 
	 */
	if (on(player, DOROT)) {
	     if ((pstats.s_hpt -= 5) <= 0) death(D_ROT);
	}
	do_daemons(AFTER);
	do_fuses(AFTER);
	if (!((running || count) && jump)) look(FALSE, FALSE);


    }
    t_free_list(monst_dead);
}

/*
 * quit:
 *	Have player make certain, then exit.
 */

void
quit(int sig)
{
    NOOP(sig);

    /*
     * Reset the signal in case we got here via an interrupt
     */
    if (signal(SIGINT, &quit) != &quit)
	mpos = 0;
    msg("Really quit? ");
    draw(cw);
    if (readchar() == 'y')
    {
	clear();
	move(LINES-1, 0);
	draw(stdscr);
	writelog(pstats.s_exp + (long) purse, CHICKEN, 0);
	score(pstats.s_exp + (long) purse, CHICKEN, 0);
	exit(0);
    }
    else
    {
	signal(SIGINT, quit);
	wmove(cw, 0, 0);
	wclrtoeol(cw);
	status(FALSE);
	draw(cw);
	mpos = 0;
	count = 0;
	running = FALSE;
    }
}

/*
 * bugkill:
 *	killed by a program bug instead of voluntarily.
 */

void
bugkill(sig)
int sig;
{
    signal(sig, quit);	/* If we get it again, give up */
    death(D_SIGNAL);	/* Killed by a bug */
}


/*
 * search:
 *	Player gropes about him to find hidden things.
 */

search(is_thief, door_chime)
register bool is_thief, door_chime;
{
    register int x