Mercurial > hg > early-roguelike
view urogue/command.c @ 302:fa70bba6bb3f rel2021.03
Update the README.
author | John "Elwin" Edwards |
---|---|
date | Thu, 18 Mar 2021 20:53:49 -0400 |
parents | 4573b355cdc1 |
children | e52a8a7ad4c5 |
line wrap: on
line source
/* command.c - Read and execute the user commands UltraRogue: The Ultimate Adventure in the Dungeons of Doom Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong All rights reserved. Based on "Advanced Rogue" Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka 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 <string.h> #include <stdlib.h> #include <ctype.h> #include "rogue.h" /* command() Process the user commands */ void command(void) { static char repcommand; /* Command to repeat if we are repeating */ static int fight_to_death; /* Flags if we are fighting to death */ static coord dir; /* Last direction specified */ object *obj; char ch; int ntimes = 1; /* Number of player moves */ coord nullcoord; nullcoord.x = nullcoord.y = 0; if (on(player, CANFLY) && rnd(2)) ntimes++; if (on(player, ISHASTE)) ntimes++; if (fighting && att_bonus()) ntimes *= 2; if (on(player, ISSLOW)) { if (player.t_turn != TRUE) ntimes--; player.t_turn ^= TRUE; } if (ntimes == 0) return; while (ntimes--) { moving = FALSE; /* If player is infested, take off a hit point */ if (on(player, HASINFEST) && !is_wearing(R_HEALTH)) { if ((pstats.s_hpt -= infest_dam) <= 0) { death(D_INFESTATION); return; } } look(after); if (!running) door_stop = FALSE; status(FALSE); wmove(cw, hero.y, hero.x); if (!((running || count) && jump)) wrefresh(cw); /* Draw screen */ take = 0; after = TRUE; /* * Read command or continue run */ if (!no_command) { if (fighting) { ch = (fight_to_death) ? 'F' : 'f'; } else if (running) { /* * If in a corridor, if we are at a turn with * only one way to go, turn that way. */ if ((winat(hero.y, hero.x) == PASSAGE) && off(player, ISHUH) && (off(player, ISBLIND))) switch (runch) { case 'h': corr_move(0, -1); break; case 'j': corr_move(1, 0); break; case 'k': corr_move(-1, 0); break; case 'l': corr_move(0, 1); break; } ch = runch; } else if (count) ch = repcommand; else { ch = readchar(); if (mpos != 0 && !running) msg(""); /* Erase message if its there */ } } else { ch = '.'; fighting = moving = FALSE; } if (no_command) { if (--no_command == 0) msg("You can move again."); } else { /* * check for prefixes */ if (isdigit(ch)) { count = 0; while (isdigit(ch)) { count = count * 10 + (ch - '0'); ch = readcharw(cw); } repcommand = ch; /* * Preserve count for commands which can be * repeated. */ 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 'm': 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': runch = ch; break; case 'H': case 'J': case 'K': case 'L': case 'Y': case 'U': case 'B': case 'N': runch = (char) tolower(ch); break; } /* * execute a command */ if (count && !running) count--; switch(ch) { /* * Movement and combat commands */ case 'h': do_move(0,-1); break; case 'j': do_move(1, 0); break; case 'k': do_move(-1, 0); break; case 'l': do_move(0, 1); break; case 'y': do_move(-1, -1); break; case 'u': do_move(-1, 1); break; case 'b': do_move(1, -1); break; case 'n': do_move(1, 1); break; case 'H': do_run('h'); break; case 'J': do_run('j'); break; case 'K': do_run('k'); break; case 'L': do_run('l'); break; case 'Y': do_run('y'); break; case 'U': do_run('u'); break; case 'B': do_run('b'); break; case 'N': do_run('n'); break; case 'm': moving = TRUE; if (!get_dir()) { after = FALSE; break; } do_move(delta.y, delta.x); break; case 'F': case 'f': fight_to_death = (ch == 'F'); if (!fighting) { if (get_dir()) { dir = delta; beast = NULL; } else { after = FALSE; break; } } do_fight(dir, (ch == 'F') ? TRUE : FALSE); break; case 't': if (get_dir()) missile(delta.y, delta.x, get_item("throw", 0), &player); else after = FALSE; /* * Informational commands - Do not do * after daemons */ break; case 0x7f: /* sometime generated by */ /* suspend/foreground */ case ESCAPE: case ' ': after = FALSE; /* do nothing */ break; case 'Q': after = FALSE; quit(); break; case 'i': after = FALSE; inventory(pack, '*'); break; case 'I': after = FALSE; inventory(pack, 0); break; case '~': after = FALSE; next_exp_level(MESSAGE); break; case '>': after = FALSE; d_level(); break; case '<': after = FALSE; u_level(); break; case '?': after = FALSE; help(); break; case '/': after = FALSE; identify(); break; case 'v': after = FALSE; msg("UltraRogue Version %s.", release); break; case 'o': after = FALSE; option(); strcpy(fd_data[1].mi_name, fruit); break; case 12: /* ctrl-l */ case 18: /* ctrl-r */ after = FALSE; clearok(cw, TRUE); wrefresh(cw); break; case 16: /* ctrl-p */ { int decrement = FALSE; after = FALSE; if (mpos == 0) decrement = TRUE; msg_index = (msg_index + 9) % 10; msg(msgbuf[msg_index]); if (decrement) msg_index = (msg_index + 9) % 10; } break; case 'S': after = FALSE; if (save_game()) { wclear(cw); wrefresh(cw); endwin(); printf("\n"); exit(0); } break; /* * Other misc commands */ case '.': break; /* rest */ case ',': add_pack(NULL, NOMESSAGE); break; case 'q': quaff(&player, -1, ISNORMAL); break; case 'r': read_scroll(&player, -1, ISNORMAL); break; case 'd': drop(NULL); break; case '^': set_trap(&player, hero.y, hero.x); break; case 'c': incant(&player, nullcoord); break; case 'D': dip_it(); break; case 'e': eat(); break; case '=': listen(); break; case 'A': apply(); break; case 'w': wield(); break; case 'W': wear(); break; case 'T': take_off(); break; case 'P': ring_on(); break; case 'R': ring_off(); break; case 'p': prayer(); break; case 'C': call(FALSE); break; case 'M': call(TRUE); break; case 's': search(FALSE); break; /* * Directional commands - get_dir sets delta */ case 20: /* ctrl-t */ if (get_dir()) steal(); else after = FALSE; break; case 'z': if (get_dir()) do_zap(&player, -1, ISNORMAL); else after = FALSE; break; case 'a': if (get_dir()) affect(); else after = FALSE; touchwin(cw); break; /* * wizard commands */ #ifdef WIZARD case 0x17: /* ctrl-w */ after = FALSE; if (!wizard) { if (!canwizard) { msg("Illegal command '^W'."); break; } if (passwd()) { msg("Welcome, oh mighty wizard."); wizard = waswizard = TRUE; } else { msg("Incorrect password."); break; } } msg("Wizard command: "); mpos = 0; ch = readchar(); switch (ch) { case 'v': wiz_verbose = !wiz_verbose; break; case 'e': wizard = FALSE; msg("Not wizard any more."); break; case 's': activity(); break; case 't': teleport(); break; case 'm': overlay(mw, cw); break; case 'f': overlay(stdscr, cw); break; case 'i': inventory(lvl_obj, 0); break; case 'c': buy_it('\0', ISNORMAL); break; case 'I': whatis(NULL); break; case 'F': msg("food left: %d\tfood level: %d", food_left,foodlev); break; case 'M': creat_mons(&player, get_monster_number("create"), MESSAGE); break; case 'r': msg("rnd(4)%d, rnd(40)%d, rnd(100)%d", rnd(4), rnd(40), rnd(100)); break; case 'C': obj = get_object(pack, "charge", STICK, NULL); if (obj != NULL) obj->o_charges = 10000; break; case 'w': obj = get_object(pack, "price", 0, NULL); if (obj != NULL) msg("Worth %d.", get_worth(obj)); break; case 'g': { int tlev; prbuf[0] = '\0'; msg("Which level? "); if (get_string(prbuf, cw) == NORM) { msg(""); if ((tlev = atoi(prbuf)) < 1) msg("Illegal level."); else if (tlev > 3000) { levtype = THRONE; level = tlev - 3000; } else if (tlev > 2000) { levtype = MAZELEV; level = tlev - 2000; } else if (tlev > 1000) { levtype = POSTLEV; level = tlev - 1000; } else { levtype = NORMLEV; level = tlev; } new_level(levtype,0); } } break; case 'o': make_omnipotent(); break; case ESCAPE: /* Escape */ door_stop = FALSE; count = 0; after = FALSE; break; default: msg("Illegal wizard command '%s', %d.", unctrl(ch), ch); count = 0; break; } break; #endif default: msg("Illegal command '%s', %d.", unctrl(ch), ch); count = 0; after = FALSE; break; } /* * turn off flags if no longer needed */ if (!running) door_stop = FALSE; } /* * If he ran into something to take, let him pick it up. */ if (take != 0) if (!moving) pick_up(take); else show_floor(); if (!running) door_stop = FALSE; } /* end while */ } void do_after_effects(void) { int i; /* Kick off the rest of the daemons and fuses */ look(FALSE); do_daemons(AFTER); do_fuses(AFTER); /* Special abilities */ if ((player.t_ctype == C_THIEF || player.t_ctype == C_ASSASIN || player.t_ctype == C_NINJA || player.t_ctype == C_RANGER) && (rnd(100) < (2 * pstats.s_dext + 5 * pstats.s_lvl))) search(TRUE); for (i = 0; i < ring_value(R_SEARCH); i++) search(FALSE); if (is_wearing(R_TELEPORT) && rnd(50) < 2) { teleport(); if (off(player, ISCLEAR)) { if (on(player, ISHUH)) lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION); else light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER); turn_on(player, ISHUH); } else msg("You feel dizzy for a moment, but it quickly passes."); } /* accidents and general clumsiness */ if (fighting && rnd(50) == 0) { msg("You become tired of this nonsense."); fighting = after = FALSE; } if (on(player, ISELECTRIC)) electrificate(); if (!fighting && (no_command == 0) && cur_weapon != NULL && rnd(on(player, STUMBLER) ? 399 : 9999) == 0 && rnd(pstats.s_dext) < 2 - hitweight() + (on(player, STUMBLER) ? 4 : 0)) { msg("You trip and stumble over your weapon."); running = after = FALSE; if (rnd(8) == 0 && (pstats.s_hpt -= roll(1, 10)) <= 0) { msg("You break your neck and die."); death(D_FALL); return; } else if (cur_weapon->o_flags & ISPOISON && rnd(4) == 0) { msg("You are cut by your %s!", inv_name(cur_weapon, LOWERCASE)); if (player.t_ctype != C_PALADIN && !(player.t_ctype == C_NINJA && pstats.s_lvl > 12) && !save(VS_POISON)) { if (pstats.s_hpt == 1) { msg("You die from the poison in the cut."); death(D_POISON); return; } else { msg("You feel very sick now."); pstats.s_hpt /= 2; chg_str(-2, FALSE, FALSE); } } } } /* Time to enforce weapon and armor restrictions */ if (rnd(9999) == 0) if (((cur_weapon == NULL) || (wield_ok(&player, cur_weapon, NOMESSAGE))) && ((cur_armor == NULL) || (wear_ok(&player, cur_armor, NOMESSAGE)))) { switch (player.t_ctype) { case C_CLERIC: case C_DRUID: case C_RANGER: case C_PALADIN: if (rnd(luck) != 0) /* You better have done * little wrong */ goto bad_cleric; msg("You are enraptured by the renewed " "power of your god."); break; case C_MAGICIAN: case C_ILLUSION: msg("You become in tune with the universe."); break; case C_THIEF: case C_NINJA: case C_ASSASIN: msg("You become supernaly sensitive to your " "surroundings."); break; case C_FIGHTER: msg("You catch your second wind."); break; default: msg("What a strange type you are!"); break; } pstats.s_hpt = max_stats.s_hpt += rnd(pstats.s_lvl) + 1; pstats.s_power = max_stats.s_power += rnd(pstats.s_lvl) + 1; } else { /* he blew it - make him pay */ int death_cause = 0; switch (player.t_ctype) { case C_CLERIC: case C_DRUID: case C_RANGER: case C_PALADIN: bad_cleric: msg("Your god scourges you for your misdeeds."); death_cause = D_GODWRATH; break; case C_MAGICIAN: case C_ILLUSION: msg("You short out your manna on the unfamiliar %s.", (cur_armor != NULL ? "armor" : "weapon")); death_cause = D_SPELLFUMBLE; break; case C_THIEF: case C_NINJA: case C_ASSASIN: msg("You trip and fall because of the unfamiliar %s.", (cur_armor != NULL ? "armor" : "weapon")); death_cause = D_CLUMSY; break; case C_FIGHTER: debug("Fighter getting raw deal?"); break; default: msg("What a strange type you are!"); break; } aggravate(); pstats.s_power /= 2; pstats.s_hpt /= 2; player.t_no_move++; if ((pstats.s_hpt -= rnd(pstats.s_lvl)) <= 0) { death(death_cause); } } if (rnd(500000) == 0) { new_level(THRONE,0); fighting = running = after = FALSE; command(); } } void make_omnipotent(void) { int i; struct linked_list *item; struct object *obj; for (i = 0; i < 20; i++) raise_level(); max_stats.s_hpt += 1000; max_stats.s_power += 1000; pstats.s_hpt = max_stats.s_hpt; pstats.s_power = max_stats.s_power; max_stats.s_str = pstats.s_str = 25; max_stats.s_intel = pstats.s_intel = 25; max_stats.s_wisdom = pstats.s_wisdom = 25; max_stats.s_dext = pstats.s_dext = 25; max_stats.s_const = pstats.s_const = 25; if (cur_weapon == NULL || cur_weapon->o_which != CLAYMORE) { item = spec_item(WEAPON, CLAYMORE, 10, 10); cur_weapon = OBJPTR(item); cur_weapon->o_flags |= ISKNOW; add_pack(item, NOMESSAGE); } /* and a kill-o-zap stick */ item = spec_item(STICK, WS_DISINTEGRATE, 10000, 0); obj = OBJPTR(item); obj->o_flags |= ISKNOW; know_items[TYP_STICK][WS_DISINTEGRATE] = TRUE; if (guess_items[TYP_STICK][WS_DISINTEGRATE]) { ur_free(guess_items[TYP_STICK][WS_DISINTEGRATE]); guess_items[TYP_STICK][WS_DISINTEGRATE] = NULL; } add_pack(item, NOMESSAGE); /* and his suit of armor */ if (cur_armor == NULL || !(cur_armor->o_which == CRYSTAL_ARMOR ||