Mercurial > hg > early-roguelike
diff srogue/move.c @ 36:2128c7dc8a40
Import Super-Rogue 9.0 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Thu, 25 Nov 2010 12:21:41 +0000 |
parents | |
children | 94a0d9dd5ce1 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/move.c Thu Nov 25 12:21:41 2010 +0000 @@ -0,0 +1,740 @@ +/* + * Hero movement commands + * + * @(#)move.c 9.0 (rdk) 7/17/84 + * + * Super-Rogue + * Copyright (C) 1984 Robert D. Kindelberger + * 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 <ctype.h> +#include "rogue.h" +#include "rogue.ext" + +/* + * Used to hold the new hero position + */ + +struct coord nh; + +/* + * do_run: + * Start the hero running + */ + +do_run(ch) +char ch; +{ + running = TRUE; + after = FALSE; + runch = ch; +} + +/* + * do_move: + * Check to see that a move is legal. If it is handle the + * consequences (fighting, picking up, etc.) + */ + +do_move(dy, dx) +int dy, dx; +{ + reg int ch; + reg struct room *rp; + + firstmove = FALSE; + curprice = -1; + inpool = FALSE; + + if (player.t_nomove > 0) { + player.t_nomove -= 1; + msg("You are still stuck in the bear trap."); + return; + } + /* + * Do a confused move (maybe) + */ + if ((rnd(100) < 80 && pl_on(ISHUH)) || + (iswearing(R_DELUS) && rnd(100) < 25)) + nh = *rndmove(&player); + else { + nh.y = hero.y + dy; + nh.x = hero.x + dx; + } + /* + * Check if he tried to move off the screen or make + * an illegal diagonal move, and stop him if he did. + */ + if (!cordok(nh.y, nh.x) || + (pl_off(ISETHER) && !diag_ok(&hero, &nh))) { + after = running = FALSE; + return; + } + if (running) { + ch = winat(nh.y, nh.x); + if (dead_end(ch)) { + reg int gox, goy, apsg, whichway; + + gox = goy = apsg = 0; + if (dy == 0) { + ch = show(hero.y+1,hero.x); + if (ch == PASSAGE) { + apsg += 1; + goy = 1; + } + ch = show(hero.y-1,hero.x); + if (ch == PASSAGE) { + apsg += 1; + goy = -1; + } + } + else if (dx == 0) { + ch = show(hero.y,hero.x+1); + if (ch == PASSAGE) { + gox = 1; + apsg += 1; + } + ch = show(hero.y,hero.x-1); + if (ch == PASSAGE) { + gox = -1; + apsg += 1; + } + } + if (apsg != 1) { + running = after = FALSE; + return; + } + else { /* can still run here */ + nh.y = hero.y + goy; + nh.x = hero.x + gox; + whichway = (goy + 1) * 3 + gox + 1; + switch(whichway) { + case 0: runch = 'y'; + when 1: runch = 'k'; + when 2: runch = 'u'; + when 3: runch = 'h'; + when 4: runch = '.'; /* shouldn't do */ + when 5: runch = 'l'; + when 6: runch = 'b'; + when 7: runch = 'j'; + when 8: runch = 'n'; + } + } + } + } + if (running && ce(hero, nh)) + after = running = FALSE; + ch = winat(nh.y, nh.x); + if (pl_on(ISHELD) && ch != 'F' && ch != 'd') { + msg("You are being held."); + return; + } + if (pl_off(ISETHER)) { + if (isatrap(ch)) { + ch = be_trapped(&nh, &player); + if (nlmove) { + nlmove = FALSE; + return; + } + else if (ch == POOL) + inpool = TRUE; + } + else if (dead_end(ch)) { + after = running = FALSE; + return; + } + else { + switch(ch) { + case GOLD: case POTION: case SCROLL: + case FOOD: case WEAPON: case ARMOR: + case RING: case AMULET: case STICK: + running = FALSE; + take = ch; + default: + if (illeg_ch(ch)) { + running = FALSE; + mvaddch(nh.y, nh.x, FLOOR); + teleport(rndspot, &player); + light(&nh); + msg("The spatial warp disappears !"); + return; + } + } + } + } + rp = roomin(&nh); + if (ch == DOOR) { /* just stepped on a door */ + running = FALSE; + if (rp != NULL && rf_on(rp, ISTREAS)) { + struct linked_list *item; + struct thing *tp; + + for (item = mlist; item != NULL; item = next(item)) { + tp = THINGPTR(item); + if (tp->t_room == rp) + runto(&tp->t_pos, &hero); + } + } + } + else if (ch == STAIRS && pl_off(ISETHER)) + running = FALSE; + else if (isalpha(ch) && pl_off(ISETHER)) { + running = FALSE; + fight(&nh, cur_weapon, FALSE); + return; + } + if (rp == NULL && player.t_room != NULL) + light(&hero); /* exiting a room */ + else if (rp != NULL && player.t_room == NULL) + light(&nh); /* just entering a room */ + if (pl_on(ISBLIND)) + ch = ' '; + else + ch = player.t_oldch; + mvwaddch(cw, hero.y, hero.x, ch); + mvwaddch(cw, nh.y, nh.x, PLAYER); + hero = nh; + player.t_room = rp; + player.t_oldch = mvinch(hero.y, hero.x); +} + +/* + * Called to illuminate a room. + * If it is dark, remove anything that might move. + */ +light(cp) +struct coord *cp; +{ + reg struct room *rp; + reg int j, k, x, y; + reg char ch, rch; + reg struct linked_list *item; + + rp = roomin(cp); + if (rp == NULL) + return; + if (pl_on(ISBLIND)) { + for (j = 0; j < rp->r_max.y; j += 1) { + for (k = 0; k < rp->r_max.x; k += 1) { + y = rp->r_pos.y + j; + x = rp->r_pos.x + k; + mvwaddch(cw, y, x, ' '); + } + } + look(FALSE); + return; + } + if (iswearing(R_LIGHT)) + rp->r_flags &= ~ISDARK; + for (j = 0; j < rp->r_max.y; j += 1) { + for (k = 0; k < rp->r_max.x; k += 1) { + y = rp->r_pos.y + j; + x = rp->r_pos.x + k; + if (levtype == MAZELEV && !cansee(y, x)) + continue; + ch = show(y, x); + wmove(cw, y, x); + /* + * Figure out how to display a secret door + */ + if (ch == SECRETDOOR) { + if (j == 0 || j == rp->r_max.y - 1) + ch = '-'; + else + ch = '|'; + } + if (isalpha(ch)) { + struct thing *mit; + + item = wake_monster(y, x); + if (item == NULL) { + ch = FLOOR; + mvaddch(y, x, ch); + } + else { + mit = THINGPTR(item); + if (mit->t_oldch == ' ') + if (!rf_on(rp,ISDARK)) + mit->t_oldch = mvinch(y, x); + if (levtype == MAZELEV) + ch = mvinch(y, x); + } + } + if (rf_on(rp,ISDARK)) { + rch = mvwinch(cw, y, x); + if (isatrap(rch)) { + ch = rch; /* if its a trap */ + } + else { /* try other things */ + switch (rch) { + case DOOR: case STAIRS: case '|': + case '-': + ch = rch; + otherwise: + ch = ' '; + } + } + } + mvwaddch(cw, y, x, ch); + } + } +} + +/* + * show: + * returns what a certain thing will display as to the un-initiated + */ +show(y, x) +int y, x; +{ + reg char ch = winat(y, x); + reg struct linked_list *it; + reg struct thing *tp; + reg struct trap *ta; + + if (isatrap(ch)) { + if ((ta = trap_at(y, x)) == NULL) + return FLOOR; + if (iswearing(R_FTRAPS)) + ta->tr_flags |= ISFOUND; + return ((ta->tr_flags & ISFOUND) ? ta->tr_type : FLOOR); + } + if (ch == SECRETDOOR && iswearing(R_FTRAPS)) { + mvaddch(y,x,DOOR); + return DOOR; + } + if ((it = find_mons(y, x)) != NULL) { /* maybe a monster */ + tp = THINGPTR(it); + if (ch == 'M' || (tp->t_flags & ISINVIS)) { + if (ch == 'M') + ch = tp->t_disguise; + else if (pl_off(CANSEE)) { + if (ch == 's') + ch = ' '; /* shadows show as a blank */ + else + ch = mvinch(y, x); /* hide invisibles */ + } + } + } + return ch; +} + +/* + * be_trapped: + * Hero or monster stepped on a trap. + */ +be_trapped(tc, th) +struct thing *th; +struct coord *tc; +{ + reg struct trap *trp; + reg int ch, ishero; + struct linked_list *mon; + char stuckee[35], seeit, sayso; + + if ((trp = trap_at(tc->y, tc->x)) == NULL) + return; + ishero = (th == &player); + if (ishero) { + strcpy(stuckee, "You"); + count = running = FALSE; + } + else { + sprintf(stuckee, "The %s", monsters[th->t_indx].m_name); + } + seeit = cansee(tc->y, tc->x); + if (seeit) + mvwaddch(cw, tc->y, tc->x, trp->tr_type); + trp->tr_flags |= ISFOUND; + sayso = TRUE; + switch (ch = trp->tr_type) { + case POST: + if (ishero) { + nlmove = TRUE; + new_level(POSTLEV); + } + else + goto goner; + when MAZETRAP: + if (ishero) { + nlmove = TRUE; + level += 1; + new_level(MAZELEV); + msg("You are surrounded by twisty passages!"); + } + else + goto goner; + when TELTRAP: + nlmove = TRUE; + teleport(trp->tr_goto, th); + when TRAPDOOR: + if (ishero) { + level += 1; + new_level(NORMLEV); + } + else { /* monsters get lost */ +goner: + ch = GONER; + } + nlmove = TRUE; + if (seeit && sayso) + msg("%s fell into a trap!", stuckee); + when BEARTRAP: + th->t_nomove += BEARTIME; + if (seeit) { + strcat(stuckee, (ishero ? " are" : " is")); + msg("%s caught in a bear trap.", stuckee); + } + when SLEEPTRAP: + if (ishero && pl_on(ISINVINC)) + msg("You feel momentarily dizzy."); + else { + if (ishero) + th->t_nocmd += SLEEPTIME; + else + th->t_nomove += SLEEPTIME; + if (seeit) + msg("%s fall%s asleep in a strange white mist.", + stuckee, (ishero ? "":"s")); + } + when ARROWTRAP: { + int resist, ac; + struct stats *it; + + stuckee[0] = tolower(stuckee[0]); + it = &th->t_stats; + if (ishero && cur_armor != NULL) + ac = cur_armor->o_ac; + else + ac = it->s_arm; + resist = ac + getpdex(it, FALSE); + if (ishero && pl_on(ISINVINC)) + resist = -100; /* invincible is impossible to hit */ + if (swing(3 + (level / 4), resist, 1)) { + if (seeit) + msg("%sAn arrow shot %s.", (ishero ? "Oh no! " : ""), + stuckee); + if (ishero) + chg_hpt(-roll(1,6),FALSE,K_ARROW); + else { + it->s_hpt -= roll(1,6); + if (it->s_hpt < 1) { + sayso = FALSE; + goto goner; + } + } + } + else { + struct linked_list *item; + struct object *arrow; + + if (seeit) + msg("An arrow shoots past %s.", stuckee); + item = new_thing(FALSE, WEAPON, ARROW); + arrow = OBJPTR(item); + arrow->o_hplus = 3; + arrow->o_dplus = rnd(2); + arrow->o_count = 1; + arrow->o_pos = th->t_pos; + fall(item, FALSE); + } + } + when DARTTRAP: { + int resist, ac; + struct stats *it; + + stuckee[0] = tolower(stuckee[0]); + it = &th->t_stats; + if (ishero && cur_armor != NULL) + ac = cur_armor->o_ac; + else + ac = it->s_arm; + resist = ac + getpdex(it, FALSE); + if (ishero && pl_on(ISINVINC)) + resist = -100; /* invincible is impossible to hit */ + if (swing(3 + (level / 4), resist, 0)) { + if (seeit) + msg("A small dart just hit %s.", stuckee); + if (ishero) { + if (!save(VS_POISON)) + chg_abil(CON,-1,TRUE); + if (!iswearing(R_SUSTSTR)) + chg_abil(STR,-1,TRUE); + chg_hpt(-roll(1, 4),FALSE,K_DART); + } + else { + if (!save_throw(VS_POISON, th)) + it->s_ef.a_str -= 1; + it->s_hpt -= roll(1, 4); + if (it->s_hpt < 1) { + sayso = FALSE; + goto goner; + } + } + } + else if (seeit) + msg("A small dart whizzes by %s.", stuckee); + } + when POOL: + if (!ishero && rnd(100) < 10) { + if (seeit) + msg("The %s drowns !!", stuckee); + goto goner; + } + if ((trp->tr_flags & ISGONE) && rnd(100) < 10) { + nlmove = TRUE; + if (rnd(100) < 15) + teleport(rndspot); /* teleport away */ + else if(rnd(100) < 15 && level > 2) { + level -= rnd(2) + 1; + new_level(NORMLEV); + msg("You here a faint groan from below."); + } + else if(rnd(100) < 40) { + level += rnd(4); + new_level(NORMLEV); + msg("You find yourself in strange surroundings."); + } + else if(rnd(100) < 6 && pl_off(ISINVINC)) { + msg("Oh no!!! You drown in the pool!!! --More--"); + wait_for(cw, ' '); + death(K_POOL); + } + else + nlmove = FALSE; + } + } + flushinp(); /* flush typeahead */ + return ch; +} + +/* + * dip_it: + * Dip an object into a magic pool + */ +dip_it() +{ + reg struct linked_list *what; + reg struct object *ob; + reg struct trap *tp; + reg int wh; + + tp = trap_at(hero.y,hero.x); + if (tp == NULL || inpool == FALSE || (tp->tr_flags & ISGONE)) + return; + + if ((what = get_item("dip",0)) == NULL) + return; + ob = OBJPTR(what); + mpos = 0; + /* + * If hero is trying to dip an object OTHER than his + * current weapon, make sure that he could drop his + * current weapon + */ + if (ob != cur_weapon) { + if (cur_weapon != NULL && o_on(cur_weapon, ISCURSED)) { + msg("You are unable to release your weapon."); + after = FALSE; + return; + } + } + if (ob == cur_armor) { + msg("You have to take off your armor before you can dip it."); + after = FALSE; + return; + } + else if (ob == cur_ring[LEFT] || ob == cur_ring[RIGHT]) { + msg("You have to take that ring off before you can dip it."); + after = FALSE; + return; + } + wh = ob->o_which; + tp->tr_flags |= ISGONE; + if (ob != NULL && o_off(ob,ISPROT)) { + setoflg(ob,ISKNOW); + switch(ob->o_type) { + case WEAPON: + if(rnd(100) < 20) { /* enchant weapon here */ + if (o_off(ob,ISCURSED)) { + ob->o_hplus += 1; + ob->o_dplus += 1; + } + else { /* weapon was prev cursed here */ + ob->o_hplus = rnd(2); + ob->o_dplus = rnd(2); + } + resoflg(ob,ISCURSED); + } + else if(rnd(100) < 10) { /* curse weapon here */ + if (o_off(ob,ISCURSED)) { + ob->o_hplus = -(rnd(2)+1); + ob->o_dplus = -(rnd(2)+1); + } + else { /* if already cursed */ + ob->o_hplus--; + ob->o_dplus--; + } + setoflg(ob,ISCURSED); + } + msg("The %s glows for a moment.",w_magic[wh].mi_name); + when ARMOR: + if (rnd(100) < 30) { /* enchant armor */ + if(o_off(ob,ISCURSED)) + ob->o_ac -= rnd(2) + 1; + else + ob->o_ac = -rnd(3)+ armors[wh].a_class; + resoflg(ob,ISCURSED); + } + else if(rnd(100) < 15){ /* curse armor */ + if (o_off(ob,ISCURSED)) + ob->o_ac = rnd(3)+ armors[wh].a_class; + else + ob->o_ac += rnd(2) + 1; + setoflg(ob,ISCURSED); + } + msg("The %s glows for a moment.",a_magic[wh].mi_name); + when STICK: { + int i; + struct rod *rd; + + i = rnd(8) + 1; + if(rnd(100) < 25) /* add charges */ + ob->o_charges += i; + else if(rnd(100) < 10) { /* remove charges */ + if ((ob->o_charges -= i) < 0) + ob->o_charges = 0; + } + ws_know[wh] = TRUE; + rd = &ws_stuff[wh]; + msg("The %s %s glows for a moment.",rd->ws_made,rd->ws_type); + } + when SCROLL: + s_know[wh] = TRUE; + msg("The '%s' scroll unfurls.",s_names[wh]); + when POTION: + p_know[wh] = TRUE; + msg("The %s potion bubbles for a moment.",p_colors[wh]); + when RING: + r_know[wh] = TRUE; + if (magring(ob)) { + if(rnd(100) < 25) { /* enchant ring */ + if (o_off(ob,ISCURSED)) + ob->o_ac += rnd(2) + 1; + else + ob->o_ac = rnd(2) + 1; + resoflg(ob,ISCURSED); + } + else if(rnd(100) < 10) { /* curse ring */ + if (o_off(ob,ISCURSED)) + ob->o_ac = -(rnd(2) + 1); + else + ob->o_ac -= (rnd(2) + 1); + setoflg(ob,ISCURSED); + } + } + msg("The %s ring vibrates for a moment.",r_stones[wh]); + otherwise: + msg("The pool bubbles for a moment."); + } + } + cur_weapon = ob; /* hero has to weild item to dip it */ +} + + +/* + * trap_at: + * Find the trap at (y,x) on screen. + */ +struct trap * +trap_at(y, x) +int y, x; +{ + reg struct trap *tp, *ep; + + ep = &traps[ntraps]; + for (tp = traps; tp < ep; tp += 1) + if (tp->tr_pos.y == y && tp->tr_pos.x == x) + break; + if (tp >= ep) + tp = NULL; + return tp; +} + +/* + * rndmove: + * move in a random direction if the monster/person is confused + */ +struct coord * +rndmove(who) +struct thing *who; +{ + reg int x, y, ex, ey, ch; + int nopen = 0; + struct linked_list *item; + static struct coord ret; /* what we will be returning */ + static struct coord dest; + + ret = who->t_pos; + /* + * Now go through the spaces surrounding the player and + * set that place in the array to true if the space can be + * moved into + */ + ey = ret.y + 1; + ex = ret.x + 1; + for (y = who->t_pos.y - 1; y <= ey; y += 1) { + for (x = who->t_pos.x - 1; x <= ex; x += 1) { + if (!cordok(y, x)) + continue; + ch = winat(y, x);