1 /* omega copyright (c) 1987,1988,1989 by Laurence Raphael Brothers */
2 /* mmelee */
3 /* various functions to do with monster melee */
4
5 #include "glob.h"
6
7
m_hit(m,dtype)8 void m_hit(m,dtype)
9 struct monster *m;
10 int dtype;
11 {
12 if (m->uniqueness == COMMON) {
13 strcpy(Str3,"a ");
14 strcat(Str3,m->monstring);
15 }
16 else strcpy(Str3,m->monstring);
17 if ((Player.status[DISPLACED] > 0) && (random_range(2) == 1))
18 mprint("The attack was displaced!");
19 else p_damage(random_range(m->dmg),dtype,Str3);
20 }
21
22
23
24 /* execute monster attacks versus player */
tacmonster(m)25 void tacmonster(m)
26 struct monster *m;
27 {
28 int i=0;
29 drawvision(Player.x,Player.y);
30 transcribe_monster_actions(m);
31 while ((i < strlen(m->meleestr)) && (m->hp > 0)) {
32 if (m->uniqueness == COMMON) {
33 strcpy(Str4,"The ");
34 strcat(Str4,m->monstring);
35 }
36 else strcpy(Str4,m->monstring);
37 if (m->meleestr[i] == 'A') {
38 strcat(Str4," attacks ");
39 strcat(Str4,actionlocstr(m->meleestr[i+1]));
40 if (Verbosity == VERBOSE) mprint(Str4);
41 monster_melee(m,m->meleestr[i+1],0);
42 }
43 else if (m->meleestr[i] == 'L') {
44 strcat(Str4," lunges ");
45 strcat(Str4,actionlocstr(m->meleestr[i+1]));
46 if (Verbosity == VERBOSE) mprint(Str4);
47 monster_melee(m,m->meleestr[i+1],m->level);
48 }
49 i+=2;
50 }
51 }
52
53
54
monster_melee(m,hitloc,bonus)55 void monster_melee(m,hitloc,bonus)
56 struct monster *m;
57 char hitloc;
58 int bonus;
59 {
60 if (player_on_sanctuary())
61 print1("The aegis of your deity protects you!");
62 else {
63 /* It's lawful to wait to be attacked */
64 if (m->attacked==0) Player.alignment++;
65 m->attacked++;
66 if (m->uniqueness == COMMON) {
67 strcpy(Str2,"The ");
68 strcat(Str2,m->monstring);
69 }
70 else strcpy(Str2,m->monstring);
71 if (monster_hit(m,hitloc,bonus))
72 switch(m->meleef) {
73 case M_NO_OP:
74 strcat(Str2," touches you.");
75 mprint(Str2);
76 break;
77 case M_MELEE_NORMAL:
78 strcat(Str2," hits you.");
79 mprint(Str2);
80 m_hit(m,NORMAL_DAMAGE);
81 break;
82 case M_MELEE_NG:
83 strcat(Str2," hits you.");
84 mprint(Str2);
85 m_hit(m,NORMAL_DAMAGE);
86 if (random_range(5)==3) m_sp_ng(m);
87 break;
88 case M_MELEE_FIRE:
89 strcat(Str2," blasts you with fire.");
90 mprint(Str2);
91 m_hit(m,FLAME);
92 break;
93 case M_MELEE_DRAGON:
94 strcat(Str2," hits you and blasts you with fire.");
95 mprint(Str2);
96 m_hit(m,NORMAL_DAMAGE);
97 m_hit(m,FLAME);
98 break;
99 case M_MELEE_ELEC:
100 strcat(Str2," lashes you with electricity.");
101 mprint(Str2);
102 m_hit(m,ELECTRICITY);
103 break;
104 case M_MELEE_COLD:
105 strcat(Str2," freezes you with cold.");
106 mprint(Str2);
107 m_hit(m,ELECTRICITY);
108 break;
109 case M_MELEE_POISON:
110 strcat(Str2," hits you.");
111 mprint(Str2);
112 m_hit(m,NORMAL_DAMAGE);
113 if (random_range(10) < m->level) {
114 mprint("You've been poisoned!");
115 p_poison(m->dmg);
116 }
117 break;
118 case M_MELEE_GRAPPLE:
119 strcat(Str2," grabs you.");
120 mprint(Str2);
121 m_hit(m,NORMAL_DAMAGE);
122 Player.status[IMMOBILE]++;
123 break;
124 case M_MELEE_SPIRIT:
125 strcat(Str2," touches you.");
126 mprint(Str2);
127 m_hit(m,NORMAL_DAMAGE);
128 drain_life(m->level);
129 break;
130 case M_MELEE_DISEASE:
131 strcat(Str2," hits you.");
132 mprint(Str2);
133 m_hit(m,NORMAL_DAMAGE);
134 if (random_range(10) < m->level) {
135 mprint("You've been infected!");
136 disease(m->level);
137 }
138 break;
139 case M_MELEE_SLEEP:
140 strcat(Str2," hit you.");
141 mprint(Str2);
142 m_hit(m,NORMAL_DAMAGE);
143 if (random_range(10) < m->level) {
144 mprint("You feel drowsy");
145 sleep_player(m->level);
146 }
147 break;
148 }
149 else {
150 if (random_range(10)) strcat(Str2," missed you.");
151 else {
152 if (Verbosity == TERSE) {
153 switch(random_range(10)) {
154 case 0:
155 strcat(Str2," blundered severely.");
156 m_damage(m,m->dmg,UNSTOPPABLE); break;
157 case 1:
158 strcat(Str2," tripped while attacking.");m_dropstuff(m);break;
159 case 2:
160 strcat(Str2," seems seriously confused.");
161 m->speed = min(30,m->speed*2); break;
162 default:
163 strcat(Str2," missed you.");
164 }
165 }
166 switch(random_range(10)) {
167 case 0: strcat(Str2," flailed stupidly at you."); break;
168 case 1: strcat(Str2," made you laugh."); break;
169 case 2: strcat(Str2," blundered severely.");
170 m_damage(m,m->dmg,UNSTOPPABLE); break;
171 case 3: strcat(Str2," tripped while attacking.");m_dropstuff(m);break;
172 case 4: strcat(Str2," seems seriously confused.");
173 m->speed = min(30,m->speed*2); break;
174 case 5: strcat(Str2," is seriously ashamed."); break;
175 case 6: strcat(Str2," made a boo-boo."); break;
176 case 7: strcat(Str2," blundered."); break;
177 case 8: strcat(Str2," cries out in anger and frustration."); break;
178 case 9: strcat(Str2," curses your ancestry."); break;
179 }
180 }
181 mprint(Str2);
182 }
183 }
184 }
185
186
187
188 /* checks to see if player hits with hitmod vs. monster m at location hitloc */
monster_hit(m,hitloc,bonus)189 int monster_hit(m,hitloc,bonus)
190 struct monster *m;
191 char hitloc;
192 int bonus;
193 {
194 int i=0,blocks=FALSE,goodblocks=0,hit,riposte=FALSE;
195 while (i<strlen(Player.meleestr)) {
196 if ((Player.meleestr[i] == 'B') || (Player.meleestr[i] == 'R')) {
197 blocks = TRUE;
198 if (hitloc == Player.meleestr[i+1]) {
199 goodblocks++;
200 if (Player.meleestr[i] == 'R') riposte = TRUE;
201 }
202 }
203 i+=2;
204 }
205 if (! blocks) goodblocks = -1;
206 hit = hitp(m->hit+bonus,Player.defense+goodblocks*10);
207 if ((! hit) && (goodblocks > 0)) {
208 if (Verbosity == VERBOSE) mprint("You blocked it!");
209 if (riposte) {
210 if (Verbosity != TERSE) mprint("You got a riposte!");
211 if (hitp(Player.hit,m->ac)) {
212 mprint("You hit!");
213 weapon_use(0,Player.possessions[O_WEAPON_HAND],m);
214 }
215 else mprint("You missed.");
216 }
217 }
218 return(hit);
219 }
220
221
222
223 /* decide monster actions in tactical combat mode */
224 /* if monster is skilled, it can try see the player's attacks coming and
225 try to block appropriately. */
226
transcribe_monster_actions(m)227 void transcribe_monster_actions(m)
228 struct monster *m;
229 {
230 int i;
231 char attack_loc,block_loc;
232 static char mmstr[80];
233
234 int p_blocks[3];
235 int p_attacks[3];
236
237 for(i=0;i<3;i++)p_blocks[i] = p_attacks[i] = 0;
238
239 /* Find which area player blocks and attacks least in */
240 i = 0;
241 while (i<strlen(Player.meleestr)) {
242 if ((Player.meleestr[i] == 'B') ||
243 (Player.meleestr[i] == 'R')) {
244 if (Player.meleestr[i+1] == 'H') p_blocks[0]++;
245 if (Player.meleestr[i+1] == 'C') p_blocks[1]++;
246 if (Player.meleestr[i+1] == 'L') p_blocks[2]++;
247 }
248 else if ((Player.meleestr[i] == 'A') ||
249 (Player.meleestr[i] == 'L')) {
250 if (Player.meleestr[i+1] == 'H') p_attacks[0]++;
251 if (Player.meleestr[i+1] == 'C') p_attacks[1]++;
252 if (Player.meleestr[i+1] == 'L') p_attacks[2]++;
253 }
254 i+=2;
255 }
256
257 if ((p_blocks[2] <= p_blocks[1]) &&
258 (p_blocks[2] <= p_blocks[0]))
259 attack_loc = 'L';
260 else if ((p_blocks[1] <= p_blocks[2]) &&
261 (p_blocks[1] <= p_blocks[0]))
262 attack_loc = 'C'; /* DG 12/31/98 */
263 else attack_loc = 'H';
264 if ((p_attacks[2] <= p_attacks[1]) &&
265 (p_attacks[2] <= p_attacks[0]))
266 block_loc = 'L';
267 else if ((p_attacks[1] <= p_attacks[2]) &&
268 (p_attacks[1] <= p_attacks[0]))
269 block_loc = 'C';
270 else block_loc = 'H';
271
272 m->meleestr = mmstr;
273
274 if (m->id != NPC)
275 strcpy(m->meleestr,Monsters[m->id].meleestr);
276 else {
277 strcpy(m->meleestr,"");
278 for(i=0;i<m->level;i+=2)
279 strcat(m->meleestr,"L?R?");
280 }
281
282 i = 0;
283 while (i<strlen(m->meleestr)) {
284 if ((m->meleestr[i] == 'A') || (m->meleestr[i] == 'L')) {
285 if (m->meleestr[i+1] == '?') {
286 if (m->level+random_range(30) > Player.level+random_range(20))
287 m->meleestr[i+1] = attack_loc;
288 else m->meleestr[i+1] = random_loc();
289 }
290 else if (m->meleestr[i+1] == 'X') m->meleestr[i+1] = random_loc();
291 }
292 else if ((m->meleestr[i] == 'B') || (m->meleestr[i] == 'R')) {
293 if (m->meleestr[i+1] == '?') {
294 if (m->level+random_range(30) > Player.level+random_range(20))
295 m->meleestr[i+1] = block_loc;
296 else m->meleestr[i+1] = random_loc();
297 }
298 else if (m->meleestr[i+1] == 'X') m->meleestr[i+1] = random_loc();
299 }
300 i+=2;
301 }
302 }
303
random_loc()304 char random_loc()
305 {
306 switch(random_range(3)) {
307 case 0:return('H');
308 case 1:return('C');
309 default:return('L');
310 }
311 }
312