Mercurial > hg > early-roguelike
comparison xrogue/bolt.c @ 133:e6179860cb76
Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
| author | John "Elwin" Edwards |
|---|---|
| date | Tue, 21 Apr 2015 08:55:20 -0400 |
| parents | |
| children | f54901b9c39b |
comparison
equal
deleted
inserted
replaced
| 124:d10fc4a065ac | 133:e6179860cb76 |
|---|---|
| 1 /* | |
| 2 bolt.c - functions shooting an object across the room | |
| 3 | |
| 4 XRogue: Expeditions into the Dungeons of Doom | |
| 5 Copyright (C) 1991 Robert Pietkivitch | |
| 6 All rights reserved. | |
| 7 | |
| 8 Based on "Advanced Rogue" | |
| 9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T | |
| 10 All rights reserved. | |
| 11 | |
| 12 Based on "Rogue: Exploring the Dungeons of Doom" | |
| 13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
| 14 All rights reserved. | |
| 15 | |
| 16 See the file LICENSE.TXT for full copyright and licensing information. | |
| 17 */ | |
| 18 | |
| 19 #include <curses.h> | |
| 20 #include <ctype.h> | |
| 21 #include "rogue.h" | |
| 22 | |
| 23 /* | |
| 24 * shoot_bolt fires a bolt from the given starting point in the | |
| 25 * given direction | |
| 26 */ | |
| 27 | |
| 28 shoot_bolt(shooter, start, dir, get_points, reason, name, damage) | |
| 29 struct thing *shooter; | |
| 30 coord start, dir; | |
| 31 bool get_points; | |
| 32 short reason; | |
| 33 char *name; | |
| 34 int damage; | |
| 35 { | |
| 36 unsigned char dirch = 0, ch; | |
| 37 bool used, change, see_him; | |
| 38 short y, x, bounces; | |
| 39 coord pos; | |
| 40 struct linked_list *target=NULL; | |
| 41 struct { | |
| 42 coord place; | |
| 43 char oldch; | |
| 44 } spotpos[BOLT_LENGTH]; | |
| 45 | |
| 46 switch (dir.y + dir.x) { | |
| 47 case 0: dirch = '/'; | |
| 48 when 1: case -1: dirch = (dir.y == 0 ? '-' : '|'); | |
| 49 when 2: case -2: dirch = '\\'; | |
| 50 } | |
| 51 pos.y = start.y + dir.y; | |
| 52 pos.x = start.x + dir.x; | |
| 53 used = FALSE; | |
| 54 change = FALSE; | |
| 55 | |
| 56 bounces = 0; /* No bounces yet */ | |
| 57 nofont(cw); | |
| 58 for (y = 0; y < BOLT_LENGTH && !used; y++) { | |
| 59 ch = winat(pos.y, pos.x); | |
| 60 spotpos[y].place = pos; | |
| 61 spotpos[y].oldch = mvwinch(cw, pos.y, pos.x); | |
| 62 | |
| 63 /* Are we at hero? */ | |
| 64 if (ce(pos, hero)) goto at_hero; | |
| 65 | |
| 66 switch (ch) { | |
| 67 case SECRETDOOR: | |
| 68 case VERTWALL: | |
| 69 case HORZWALL: | |
| 70 case ' ': | |
| 71 if (dirch == '-' || dirch == '|') { | |
| 72 dir.y = -dir.y; | |
| 73 dir.x = -dir.x; | |
| 74 } | |
| 75 else { | |
| 76 unsigned char chx = mvinch(pos.y-dir.y, pos.x), | |
| 77 chy = mvinch(pos.y, pos.x-dir.x); | |
| 78 bool anychange = FALSE; /* Did we change anthing */ | |
| 79 | |
| 80 if (chy == WALL || chy == SECRETDOOR || | |
| 81 chy == HORZWALL || chy == VERTWALL) { | |
| 82 dir.y = -dir.y; | |
| 83 change ^= TRUE; /* Change at least one direction */ | |
| 84 anychange = TRUE; | |
| 85 } | |
| 86 if (chx == WALL || chx == SECRETDOOR || | |
| 87 chx == HORZWALL || chx == VERTWALL) { | |
| 88 dir.x = -dir.x; | |
| 89 change ^= TRUE; /* Change at least one direction */ | |
| 90 anychange = TRUE; | |
| 91 } | |
| 92 | |
| 93 /* If we didn't make any change, make both changes */ | |
| 94 if (!anychange) { | |
| 95 dir.x = -dir.x; | |
| 96 dir.y = -dir.y; | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 /* Do we change how the bolt looks? */ | |
| 101 if (change) { | |
| 102 change = FALSE; | |
| 103 if (dirch == '\\') dirch = '/'; | |
| 104 else if (dirch == '/') dirch = '\\'; | |
| 105 } | |
| 106 | |
| 107 y--; /* The bounce doesn't count as using up the bolt */ | |
| 108 | |
| 109 /* Make sure we aren't in an infinite bounce */ | |
| 110 if (++bounces > BOLT_LENGTH) used = TRUE; | |
| 111 msg("The %s bounces", name); | |
| 112 break; | |
| 113 default: | |
| 114 if (isalpha(ch)) { | |
| 115 register struct linked_list *item; | |
| 116 struct thing *tp; | |
| 117 register char *mname; | |
| 118 bool see_monster = cansee(pos.y, pos.x); | |
| 119 | |
| 120 item = find_mons(unc(pos)); | |
| 121 assert(item != NULL); | |
| 122 tp = THINGPTR(item); | |
| 123 mname = monster_name(tp); | |
| 124 | |
| 125 /* | |
| 126 * If our prey shot this, let's record the fact that | |
| 127 * he can shoot, regardless of whether he hits us. | |
| 128 */ | |
| 129 if (tp->t_dest != NULL && ce(*tp->t_dest, shooter->t_pos)) | |
| 130 tp->t_wasshot = TRUE; | |
| 131 | |
| 132 if (!save(VS_BREATH, tp, -(shooter->t_stats.s_lvl/10))) { | |
| 133 if (see_monster) { | |
| 134 if (on(*tp, ISDISGUISE) && | |
| 135 (tp->t_type != tp->t_disguise)) { | |
| 136 msg("Wait! That's a %s!", mname); | |
| 137 turn_off(*tp, ISDISGUISE); | |
| 138 } | |
| 139 | |
| 140 turn_off(*tp, CANSURPRISE); | |
| 141 msg("The %s hits %s", name, prname(mname, FALSE)); | |
| 142 } | |
| 143 | |
| 144 /* Should we start to chase the shooter? */ | |
| 145 if (shooter != &player && | |
| 146 shooter != tp && | |
| 147 shooter->t_index != tp->t_index && | |
| 148 (tp->t_dest == NULL || rnd(100) < 25)) { | |
| 149 /* | |
| 150 * If we're intelligent enough to realize that this | |
| 151 * is a friendly monster, we will attack the hero | |
| 152 * instead. | |
| 153 */ | |
| 154 if (on(*shooter, ISFRIENDLY) && | |
| 155 roll(3,6) < tp->t_stats.s_intel) | |
| 156 runto(tp, &hero); | |
| 157 | |
| 158 /* Otherwise, let's chase the monster */ | |
| 159 else runto(tp, &shooter->t_pos); | |
| 160 } | |
| 161 else if (shooter == &player) { | |
| 162 runto(tp, &hero); | |
| 163 | |
| 164 /* | |
| 165 * If the player shot a charmed monster, it may |
