Source:NetHack 2.3e/makemon.c
Revision as of 22:59, 3 July 2024 by Furey (talk | contribs) (Delete link-to-particular-source instructions. Source code covers that now. "the latest release" -> "newer releases".)
Below is the full text to makemon.c from the source code of NetHack 2.3e.
Warning! This is the source code from an old release. For newer releases, see Source code
Screenshots and source code from Hack are used under the CWI license.
1. /* SCCS Id: @(#)makemon.c 2.3 87/12/12 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. 4. #include "hack.h" 5. extern char fut_geno[]; 6. extern char *index(); 7. extern struct obj *mkobj_at(), *mksobj(), *mkobj(); 8. struct monst zeromonst; 9. extern boolean in_mklev; 10. 11. #ifdef HARD /* used in hell for bigger, badder demons! */ 12. 13. struct permonst d_lord = { "demon lord", '&',12,13,-5,50,1,5,0 }, 14. d_prince = { "demon prince", '&',14,14,-6,70,1,6,0 }; 15. #endif 16. #ifdef KJSMODS 17. # ifdef KOPS 18. struct permonst kobold = { "kobold",'K',1,6,7,0,1,4,0 }; 19. # endif 20. # ifdef ROCKMOLE 21. struct permonst giant_rat = { "giant rat",'r',0,12,7,0,1,3,0 }; 22. # endif 23. #endif /* KJSMODS /**/ 24. 25. struct permonst grey_dragon = { "grey dragon", 'D',10,9,-1,20,3,8,0 }; 26. struct permonst red_dragon = { "red dragon", 'D',10,9,-1,20,3,8,0 }; 27. struct permonst orange_dragon = { "orange dragon",'D',10,9,-1,20,3,8,0 }; 28. struct permonst white_dragon = { "white dragon", 'D',10,9,-1,20,3,8,0 }; 29. struct permonst black_dragon = { "black dragon", 'D',10,9,-1,20,3,8,0 }; 30. struct permonst blue_dragon = { "blue dragon", 'D',10,9,-1,20,3,8,0 }; 31. struct permonst green_dragon = { "green dragon", 'D',10,9,-1,20,3,8,0 }; 32. struct permonst yellow_dragon = { "yellow dragon",'D',10,9,-1,20,3,8,0 }; 33. extern struct permonst pm_gremlin; 34. 35. /* 36. * called with [x,y] = coordinates; 37. * [0,0] means anyplace 38. * [u.ux,u.uy] means: call mnexto (if !in_mklev) 39. * 40. * In case we make an Orc or killer bee, we make an entire horde 41. * (swarm); note that in this case we return only one of them 42. * (the one at [x,y]). 43. */ 44. struct monst * 45. makemon(ptr,x,y) 46. register struct permonst *ptr; 47. { 48. register struct monst *mtmp; 49. register nleft, deep, ct; 50. boolean anything = (!ptr); 51. int zlevel = dlevel; 52. #ifdef BVH 53. if(has_amulet()) zlevel = MAXLEVEL; 54. #endif 55. /* if a monster already exists at the position, return */ 56. if(x != 0 || y != 0) if(m_at(x,y)) return((struct monst *) 0); 57. if(ptr){ 58. /* if you are to make a specific monster and it has 59. already been genocided, return */ 60. if(index(fut_geno, ptr->mlet)) return((struct monst *) 0); 61. } else { 62. /* make a random (common) monster. */ 63. nleft = CMNUM - strlen(fut_geno); 64. if(index(fut_geno, 'm')) nleft++; /* only 1 minotaur */ 65. if(index(fut_geno, '@')) nleft++; 66. if(nleft <= 0) 67. return((struct monst *) 0); /* no more monsters! */ 68. 69. /* determine the strongest monster to make. */ 70. #ifdef ROCKMOLE 71. deep = rn2(nleft*zlevel/24 + 6); 72. #else 73. deep = rn2(nleft*zlevel/24 + 7); 74. #endif 75. if(deep < zlevel - 4) deep = rn2(nleft*zlevel/24 + 12); 76. /* if deep is greater than the number of monsters left 77. to create, set deep to a random number between half 78. the number left and the number left. */ 79. if(deep >= nleft) deep = rn1(nleft - nleft/2, nleft/2); 80. 81. for(ct = 0 ; ct < CMNUM ; ct++){ 82. ptr = &mons[ct]; 83. if(index(fut_geno, ptr->mlet)) continue; 84. #ifdef KOPS 85. if(ptr->mlet == 'K') { 86. # ifdef KJSMODS 87. /* since this is a random monster, make 88. a Kobold instead of a Kop. */ 89. ptr = &kobold; 90. # else 91. deep--; 92. # endif 93. continue; 94. } 95. #endif /* KOPS /**/ 96. if(deep-- <= 0) goto gotmon; 97. } 98. /* this can happen if you are deep in the dungeon and 99. mostly weak monsters have been genocided. */ 100. return((struct monst *) 0); 101. } 102. gotmon: 103. #if defined(KJSMODS) && defined(ROCKMOLE) 104. /* make a giant rat */ 105. if((zlevel < 4 && ptr->mlet == 'r') 106. || (zlevel == 1 && (ptr->mlet == 'h' || ptr->mlet == 'i')) 107. || (zlevel == 2 && (ptr->mlet == 'o' || ptr->mlet == 'y')) 108. ) ptr = &giant_rat; 109. #endif 110. mtmp = newmonst(ptr->pxlth); 111. *mtmp = zeromonst; /* clear all entries in structure */ 112. for(ct = 0; ct < ptr->pxlth; ct++) 113. ((char *) &(mtmp->mextra[0]))[ct] = 0; 114. mtmp->nmon = fmon; 115. fmon = mtmp; 116. mtmp->m_id = flags.ident++; 117. mtmp->data = ptr; 118. mtmp->mxlth = ptr->pxlth; 119. if(ptr->mlet == 'D') mtmp->mhpmax = mtmp->mhp = 80; 120. else if(!ptr->mlevel) mtmp->mhpmax = mtmp->mhp = rnd(4); 121. else mtmp->mhpmax = mtmp->mhp = d(ptr->mlevel, 8); 122. mtmp->mx = x; 123. mtmp->my = y; 124. mtmp->mcansee = 1; 125. if(ptr->mlet == 'D') { 126. mtmp->dragon = rn2(8); 127. switch(mtmp->dragon) { 128. case 0: mtmp->data = &grey_dragon; break; 129. case 1: mtmp->data = &red_dragon; break; 130. case 2: mtmp->data = &orange_dragon; break; 131. case 3: mtmp->data = &white_dragon; break; 132. case 4: mtmp->data = &black_dragon; break; 133. case 5: mtmp->data = &blue_dragon; break; 134. case 6: mtmp->data = &green_dragon; break; 135. case 7: mtmp->data = &yellow_dragon; break; 136. } 137. } 138. /* if gnome, make a gremlin or if gremlin make sure it stays gremlin */ 139. if((ptr->mlet == 'G' && zlevel >= 10 && rn2(4)) || 140. !strcmp(ptr->mname, "gremlin")) { 141. ptr = PM_GREMLIN; 142. mtmp->data = PM_GREMLIN; 143. mtmp->isgremlin = 1; 144. } 145. if(ptr->mlet == 'M'){ 146. mtmp->mimic = 1; 147. mtmp->mappearance = ']'; 148. } 149. if(!in_mklev) { 150. if(x == u.ux && y == u.uy && ptr->mlet != ' ') 151. mnexto(mtmp); 152. if(x == 0 && y == 0) 153. rloc(mtmp); 154. } 155. if(ptr->mlet == 's' || ptr->mlet == 'S') { 156. mtmp->mhide = mtmp->mundetected = 1; 157. if(in_mklev) 158. if(mtmp->mx && mtmp->my) 159. (void) mkobj_at(0, mtmp->mx, mtmp->my); 160. } 161. if(ptr->mlet == ':') { 162. #ifdef DGKMOD 163. /* If you're protected with a ring, don't create 164. * any shape-changing chameleons -dgk 165. */ 166. if (Protection_from_shape_changers) 167. mtmp->cham = 0; 168. else { 169. mtmp->cham = 1; 170. (void) newcham(mtmp, 171. # ifndef RPH 172. &mons[zlevel+14+rn2(CMNUM-14-zlevel)]); 173. # else 174. (struct permonst *)0); 175. # endif 176. } 177. #else 178. mtmp->cham = 1; 179. (void) newcham (mtmp, 180. # ifndef RPH 181. &mons[zlevel+14+rn2(CMNUM-14-zlevel)]); 182. # else 183. 0); 184. # endif 185. #endif 186. } 187. if(ptr->mlet == 'I' || ptr->mlet == ';') 188. mtmp->minvis = 1; 189. if(ptr->mlet == 'L' || ptr->mlet == 'N' 190. || (in_mklev && index("&w;", ptr->mlet) && rn2(5)) 191. ) mtmp->msleep = 1; 192. #ifdef HARD 193. if(ptr->mlet == '&' && (Inhell || u.udemigod)) { 194. 195. if(!rn2(3 + !Inhell + !u.udemigod)) { 196. if (rn2(3 + Inhell)) mtmp->data = &d_lord; 197. else { 198. mtmp->data = &d_prince; 199. mtmp->mpeaceful = 1; 200. mtmp->minvis = 1; 201. } 202. } 203. #ifdef RPH 204. if(uwep) 205. if(!strcmp(ONAME(uwep), "Excalibur")) 206. mtmp->mpeaceful = mtmp->mtame = 0; 207. #endif 208. } 209. #endif /* HARD /**/ 210. #ifndef NOWORM 211. if(ptr->mlet == 'w' && getwn(mtmp)) initworm(mtmp); 212. #endif 213. 214. if(anything) 215. if(ptr->mlet == 'O' || ptr->mlet == 'k' 216. #ifdef SAC 217. || ptr->mlet == '3' 218. #endif /* SAC /**/ 219. || (ptr->mlet == 'G' && mtmp->isgremlin) 220. ) { 221. 222. coord mm; 223. register int cnt = rnd(10); 224. mm.x = x; 225. mm.y = y; 226. while(cnt--) { 227. enexto(&mm, mm.x, mm.y); 228. (void) makemon(ptr, mm.x, mm.y); 229. } 230. } 231. #ifdef DGKMOD 232. m_initinv(mtmp); 233. #endif 234. return(mtmp); 235. } 236. 237. #ifdef DGKMOD 238. /* Give some monsters an initial inventory to use */ 239. m_initinv(mtmp) 240. struct monst *mtmp; 241. { 242. struct obj *otmp; 243. 244. switch (mtmp->data->mlet) { 245. # ifdef KAA 246. case '9': 247. if (rn2(2)) { 248. otmp = mksobj(ENORMOUS_ROCK); 249. mpickobj(mtmp, otmp); 250. } 251. # endif 252. # ifdef SAC 253. case '3': /* Outfit the troops */ 254. if (!rn2(5)) { 255. otmp = mksobj(HELMET); 256. mpickobj(mtmp, otmp); } 257. if (!rn2(5)) { 258. otmp = mksobj(CHAIN_MAIL); 259. mpickobj(mtmp, otmp); } 260. if (!rn2(4)) { 261. otmp = mksobj(DAGGER); 262. mpickobj(mtmp, otmp); } 263. if (!rn2(7)) { 264. otmp = mksobj(SPEAR); 265. mpickobj(mtmp, otmp); } 266. if (!rn2(3)) { 267. otmp = mksobj(K_RATION); 268. mpickobj(mtmp, otmp); } 269. if (!rn2(2)) { 270. otmp = mksobj(C_RATION); 271. mpickobj(mtmp, otmp); } 272. # endif /* SAC /**/ 273. # ifdef KOPS 274. case 'K': /* create Keystone Kops with cream pies to 275. * throw. As suggested by KAA. [MRS] 276. */ 277. if (!rn2(4) 278. # ifdef KJSMODS 279. && !strcmp(mtmp->data->mname, "Keystone Kop") 280. # endif 281. ) { 282. otmp = mksobj(CREAM_PIE); 283. otmp->quan = 2 + rnd(2); 284. otmp->owt = weight(otmp); 285. mpickobj(mtmp, otmp); 286. } 287. break; 288. case 'O': 289. # else 290. case 'K': 291. # endif 292. if (!rn2(4)) { 293. otmp = mksobj(DART); 294. otmp->quan = 2 + rnd(12); 295. otmp->owt = weight(otmp); 296. mpickobj(mtmp, otmp); 297. } 298. break; 299. 300. case 'C': 301. if (rn2(2)) { 302. otmp = mksobj(CROSSBOW); 303. otmp->cursed = rn2(2); 304. mpickobj(mtmp, otmp); 305. otmp = mksobj(CROSSBOW_BOLT); 306. otmp->quan = 2 + rnd(12); 307. otmp->owt = weight(otmp); 308. mpickobj(mtmp, otmp); 309. } 310. break; 311. default: 312. break; 313. } 314. } 315. #endif 316. 317. enexto(cc, xx,yy) 318. coord *cc; 319. register xchar xx,yy; 320. { 321. register xchar x,y; 322. coord foo[15], *tfoo; 323. int range, i; 324. 325. tfoo = foo; 326. range = 1; 327. do { /* full kludge action. */ 328. for(x = xx-range; x <= xx+range; x++) 329. if(goodpos(x, yy-range)) { 330. tfoo->x = x; 331. (tfoo++)->y = yy-range; 332. if(tfoo == &foo[15]) goto foofull; 333. } 334. for(x = xx-range; x <= xx+range; x++) 335. if(goodpos(x,yy+range)) { 336. tfoo->x = x; 337. (tfoo++)->y = yy+range; 338. if(tfoo == &foo[15]) goto foofull; 339. } 340. for(y = yy+1-range; y < yy+range; y++) 341. if(goodpos(xx-range,y)) { 342. tfoo->x = xx-range; 343. (tfoo++)->y = y; 344. if(tfoo == &foo[15]) goto foofull; 345. } 346. for(y = yy+1-range; y < yy+range; y++) 347. if(goodpos(xx+range,y)) { 348. tfoo->x = xx+range; 349. (tfoo++)->y = y; 350. if(tfoo == &foo[15]) goto foofull; 351. } 352. range++; 353. } while(tfoo == foo); 354. foofull: 355. i = rn2(tfoo - foo); 356. cc->x = foo[i].x; 357. cc->y = foo[i].y; 358. return(0); 359. } 360. 361. goodpos(x,y) /* used only in mnexto and rloc */ 362. { 363. return( 364. ! (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 || 365. m_at(x,y) || !ACCESSIBLE(levl[x][y].typ) 366. || (x == u.ux && y == u.uy) 367. || sobj_at(ENORMOUS_ROCK, x, y) 368. )); 369. } 370. 371. rloc(mtmp) 372. struct monst *mtmp; 373. { 374. register tx,ty; 375. register char ch = mtmp->data->mlet; 376. 377. #ifndef NOWORM 378. if(ch == 'w' && mtmp->mx) return; /* do not relocate worms */ 379. #endif 380. do { 381. tx = rn1(COLNO-3,2); 382. ty = rn2(ROWNO); 383. } while(!goodpos(tx,ty)); 384. mtmp->mx = tx; 385. mtmp->my = ty; 386. if(u.ustuck == mtmp){ 387. if(u.uswallow) { 388. u.ux = tx; 389. u.uy = ty; 390. docrt(); 391. } else u.ustuck = 0; 392. } 393. pmon(mtmp); 394. } 395. 396. struct monst * 397. mkmon_at(let,x,y) 398. char let; 399. register int x,y; 400. { 401. register int ct; 402. register struct permonst *ptr; 403. 404. for(ct = 0; ct < CMNUM; ct++) { 405. ptr = &mons[ct]; 406. if(ptr->mlet == let) 407. return(makemon(ptr,x,y)); 408. } 409. return((struct monst *)0); 410. }