Guest User

NetHack Infidel role patch 3.7.0 WIP rebase

a guest
Jul 2nd, 2020
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 194.14 KB | None | 0 0
  1. diff --git c/Files i/Files
  2. index f9309dfcd..c3397ba0f 100644
  3. --- c/Files
  4. +++ i/Files
  5. @@ -35,7 +35,8 @@ Arc-fila.lua  Arc-filb.lua  Arc-goal.lua  Arc-loca.lua  Arc-strt.lua
  6.  Bar-fila.lua  Bar-filb.lua  Bar-goal.lua  Bar-loca.lua  Bar-strt.lua
  7.  Cav-fila.lua  Cav-filb.lua  Cav-goal.lua  Cav-loca.lua  Cav-strt.lua
  8.  GENFILES      Hea-fila.lua  Hea-filb.lua  Hea-goal.lua  Hea-loca.lua
  9. -Hea-strt.lua  Kni-fila.lua  Kni-filb.lua  Kni-goal.lua  Kni-loca.lua
  10. +Hea-strt.lua  Inf-fila.lua  Inf-filb.lua  Inf-goal.lua  Inf-loca.lua
  11. +Inf-strt.lua  Kni-fila.lua  Kni-filb.lua  Kni-goal.lua  Kni-loca.lua
  12.  Kni-strt.lua  Mon-fila.lua  Mon-filb.lua  Mon-goal.lua  Mon-loca.lua
  13.  Mon-strt.lua  Pri-fila.lua  Pri-filb.lua  Pri-goal.lua  Pri-loca.lua
  14.  Pri-strt.lua  Ran-fila.lua  Ran-filb.lua  Ran-goal.lua  Ran-loca.lua
  15. diff --git c/dat/Inf-fila.lua i/dat/Inf-fila.lua
  16. new file mode 100644
  17. index 000000000..d032ba107
  18. --- /dev/null
  19. +++ i/dat/Inf-fila.lua
  20. @@ -0,0 +1,58 @@
  21. +-- The upper filler is the underground complex that leads to the Forest.
  22. +-- It's a standard room-and-corridor dungeon populated with hkO.
  23. +
  24. +des.level_flags("hardfloor", "noflip")
  25. +
  26. +des.room({contents = function()
  27. +    des.stair("up")
  28. +    des.object()
  29. +    des.monster("k")
  30. +end})
  31. +
  32. +des.room({contents = function()
  33. +    des.stair("down")
  34. +    des.object()
  35. +    des.trap()
  36. +    des.monster("h")
  37. +    des.monster("k")
  38. +end})
  39. +
  40. +-- Quest dungeons always seem so empty, so here's a fountain.
  41. +des.room({contents = function()
  42. +    des.feature("fountain", -1, -1)
  43. +    des.object()
  44. +    des.monster("h")
  45. +end})
  46. +
  47. +-- Throne monsters roughly suit the hkO theme.
  48. +des.room({type = "throne", chance = 25, contents = function()
  49. +    des.object()
  50. +    des.trap()
  51. +end})
  52. +
  53. +des.room({contents = function()
  54. +    des.object()
  55. +    des.trap()
  56. +    des.monster("k")
  57. +    des.monster("k")
  58. +end})
  59. +
  60. +des.room({contents = function()
  61. +    des.object()
  62. +    des.object()
  63. +    des.trap()
  64. +    des.trap()
  65. +    des.monster("O")
  66. +    des.monster("h")
  67. +end})
  68. +
  69. +des.room({contents = function()
  70. +    des.object()
  71. +    des.object()
  72. +    des.trap()
  73. +    des.trap()
  74. +    des.monster("O")
  75. +    des.monster("k")
  76. +end})
  77. +
  78. +des.random_corridors()
  79. diff --git c/dat/Inf-filb.lua i/dat/Inf-filb.lua
  80. new file mode 100644
  81. index 000000000..c576f1fa5
  82. --- /dev/null
  83. +++ i/dat/Inf-filb.lua
  84. @@ -0,0 +1,36 @@
  85. +-- The lower fillers are some nondescript areas of the Howling Forest.
  86. +-- There's a lot of werewolves and other d and perhaps a woodchuck.
  87. +
  88. +des.level_flags("mazelevel", "hardfloor", "noflip")
  89. +des.level_init({style = "mines", fg = ".", bg = "T",
  90. +                smoothed = true, joined = true, lit = 0})
  91. +
  92. +des.levregion({type = "stair-up", region = {45, 00, 79, 20}})
  93. +des.levregion({type = "stair-down", region = {00, 00, 39, 20}})
  94. +
  95. +for _ = 1, 5 do
  96. +    des.monster("werewolf")
  97. +end
  98. +for _ = 1, d(6, 4) do
  99. +    des.monster("d")
  100. +end
  101. +for _ = 1, 4 do
  102. +    des.monster("u")
  103. +end
  104. +des.monster("forest centaur")
  105. +if percent(60) then
  106. +    des.monster("woodchuck")
  107. +end
  108. +
  109. +for _ = 1, 4 do
  110. +    des.object()
  111. +end
  112. +for _ = 1, 8 do
  113. +    des.trap()
  114. +end
  115. +
  116. +-- With so many trees, having every single one bear fruit seems excessive.
  117. +selection.negate():filter_mapchar("T"):iterate(function(x, y)
  118. +    des.feature({type = "tree", coord = {x, y},
  119. +                 looted = percent(90), swarm = percent(80)})
  120. +end)
  121. diff --git c/dat/Inf-goal.lua i/dat/Inf-goal.lua
  122. new file mode 100644
  123. index 000000000..4b26b2a4b
  124. --- /dev/null
  125. +++ i/dat/Inf-goal.lua
  126. @@ -0,0 +1,103 @@
  127. +-- The "goal" level for the quest.
  128. +
  129. +-- In this part of the Howling Forest the Paladin awaits you for a duel
  130. +-- amidst some ancient ruins.  Kill her to claim the Idol of Moloch!
  131. +
  132. +-- Note: some may find the Paladin a tough opponent.  It's intentional!
  133. +-- You come here to duel her at HER behest, on HER conditions.
  134. +-- She expects to defeat you and came prepared.  To win, you need to
  135. +-- outwit her.
  136. +
  137. +des.level_flags("mazelevel", "hardfloor", "noflipx")
  138. +des.level_init({style = "mines", fg = ".", bg = "T",
  139. +                smoothed = true, joined = true, lit = 0})
  140. +des.map({halign = "half-left", valign = "center", map =
  141. +--         1         2
  142. +--123456789012345678901234567
  143. +[[
  144. +0xxxxxxxxxx........xxxxxxxxxx
  145. +1xxxxxxx..............xxxxxxx
  146. +2xxxx....................xxxx
  147. +3xx........--..-...........xx
  148. +4x.........|.....|..........x
  149. +5.............--.|...........
  150. +6x........--................x
  151. +7xx........|..|...--.......xx
  152. +8xxxx.........|..........xxxx
  153. +9xxxxxxx..............xxxxxxx
  154. +0xxxxxxxxxx........xxxxxxxxxx
  155. +]]})
  156. +
  157. +-- The Paladin and her entourage.
  158. +des.monster("Paladin", 13, 06)
  159. +des.object({id = "figurine", name = "The Idol of Moloch",
  160. +            buc = "cursed", coord = {13, 06}})
  161. +for _, coord in pairs({{13, 03}, {15, 04}, {17, 06},
  162. +                       {13, 09}, {10, 08}, {09, 05}}) do
  163. +    des.monster({id = "templar", coord = coord, asleep = 1})
  164. +end
  165. +for _, coord in pairs({{16, 08}, {11, 04}}) do
  166. +    des.monster({id = "aligned priest", coord = coord,
  167. +                 align = "law", peaceful = 0, asleep = 1})
  168. +end
  169. +
  170. +-- Just pretend they're tripwires.
  171. +local around = selection.ellipse(13, 05, 9, 5, 1)
  172. +             ~ selection.ellipse(13, 05, 4, 3, 1)
  173. +around = around:filter_mapchar(".")
  174. +for _ = 1, 4 do
  175. +    des.trap("board", around:rndcoord(1))
  176. +end
  177. +
  178. +-- There's still some treasure buried in the ruins.
  179. +local ruins = selection.circle(13, 06, 4, 1)
  180. +for _ = 1, 2 do
  181. +    des.object({id = "gold piece", quantity = d(10, 100),
  182. +                buried = true, coord = {ruins:rndcoord(1)}})
  183. +end
  184. +for _ = 1, 3 do
  185. +    des.object({class = "*", buried = true, coord = {ruins:rndcoord(1)}})
  186. +end
  187. +if percent(60) then
  188. +    des.object({class = "=", buried = true, coord = {ruins:rndcoord(1)}})
  189. +end
  190. +if percent(50) then
  191. +    des.object({class = "=", buried = true, coord = {ruins:rndcoord(1)}})
  192. +end
  193. +if percent(40) then
  194. +    des.object({class = '"', buried = true, coord = {ruins:rndcoord()}})
  195. +end
  196. +
  197. +des.map("x") -- hack to switch to global coords
  198. +
  199. +-- The surrounding woods.
  200. +des.levregion({type = "stair-up", region = {45, 00, 79, 20}})
  201. +for _ = 1, 4 do
  202. +    des.monster("werewolf")
  203. +end
  204. +for _ = 1, d(5, 4) do
  205. +    des.monster("d")
  206. +end
  207. +for _ = 1, 3 do
  208. +    des.monster("u")
  209. +end
  210. +if percent(80) then
  211. +    des.monster("forest centaur")
  212. +end
  213. +if percent(50) then
  214. +    des.monster("woodchuck")
  215. +end
  216. +
  217. +-- And a bit of random junk.
  218. +for _ = 1, 3 do
  219. +    des.object()
  220. +end
  221. +for _ = 1, 7 do
  222. +    des.trap()
  223. +end
  224. +
  225. +-- With so many trees, having every single one bear fruit seems excessive.
  226. +selection.negate():filter_mapchar("T"):iterate(function(x, y)
  227. +    des.feature({type = "tree", coord = {x, y},
  228. +                 looted = percent(90), swarm = percent(80)})
  229. +end)
  230. diff --git c/dat/Inf-loca.lua i/dat/Inf-loca.lua
  231. new file mode 100644
  232. index 000000000..5ad6457bd
  233. --- /dev/null
  234. +++ i/dat/Inf-loca.lua
  235. @@ -0,0 +1,101 @@
  236. +-- The "locate" level for the quest.
  237. +
  238. +-- This is the edge of the Howling Forest.
  239. +-- Somewhere in here the Paladin awaits you.
  240. +
  241. +des.level_flags("mazelevel", "hardfloor", "noflipx")
  242. +des.level_init({style = "mines", fg = ".", bg = "T",
  243. +                smoothed = true, joined = true, lit = 0})
  244. +des.map({coord = {50, 00}, map =
  245. +--        1         2
  246. +--2345678901234567890123456789
  247. +[[
  248. +xxxx.|            ----        0
  249. +xxx..--           |..|        1
  250. +x.....---         |..|        2
  251. +...}}...|         -+--        3
  252. +...}}}..--         #          4
  253. +..}}}....|         #          5
  254. +...}}....|       --S-         6
  255. +.........--      |..|         7
  256. +..........--     |..|         8
  257. +...........|     |..+####     9
  258. +...........+#####+..|   #     0
  259. +...........|     |..|   #     1
  260. +...........|     ----   #     2
  261. +..........--            #     3
  262. +.........--             #     4
  263. +.........|              #     5
  264. +........-|            --+--   6
  265. +.........|            |...|   7
  266. +x......---            |...|   8
  267. +xxx.----              -----   9
  268. +xxxx|                         0
  269. +]]})
  270. +des.non_diggable(selection.area(05, 00, 29, 20))
  271. +
  272. +-- Upstairs to (rest of) the underground complex.
  273. +des.region({region = {23, 17, 25, 18}, prefilled = true, contents = function()
  274. +    des.monster("k")
  275. +end});
  276. +des.stair("up", 24, 18)
  277. +des.door("random", 24, 16)
  278. +
  279. +-- The last room before the Forest!
  280. +des.door("random", 20, 09)
  281. +des.region({region = {18, 07, 19, 11}, prefilled = true, contents = function()
  282. +    des.monster("h")
  283. +end});
  284. +des.door("random", 17, 10)
  285. +des.door("random", 11, 10)
  286. +
  287. +-- An ogre guards some treasure.
  288. +des.door("locked", 19, 03)
  289. +des.region({region = {19, 01, 20, 02}});
  290. +des.monster("O", 19, 02)
  291. +des.object("chest", 19, 01)
  292. +des.object("chest", 20, 01)
  293. +
  294. +-- The lake.
  295. +des.monster("piranha", 03, 03)
  296. +des.monster("piranha", 04, 04)
  297. +des.monster("piranha", 04, 05)
  298. +
  299. +-- The forest is spreading.
  300. +des.replace_terrain({region = {00, 00, 10, 20}, fromterrain = ".",
  301. +                     toterrain = "T", chance = 5});
  302. +
  303. +des.map("x") -- hack to switch to global coords
  304. +
  305. +-- The forest's edge.
  306. +des.levregion({type = "stair-down", region = {00, 00, 39, 20}})
  307. +local forest = selection.area(00, 00, 60, 20):filter_mapchar(".")
  308. +for _ = 1, 3 do
  309. +    des.monster("werewolf", forest:rndcoord(1))
  310. +end
  311. +for _ = 1, d(4, 4) do
  312. +    des.monster("d", forest:rndcoord(1))
  313. +end
  314. +for _ = 1, 2 do
  315. +    des.monster("u", forest:rndcoord(1))
  316. +end
  317. +if percent(65) then
  318. +    des.monster("forest centaur", forest:rndcoord(1))
  319. +end
  320. +if percent(40) then
  321. +    des.monster("woodchuck", forest:rndcoord())
  322. +end
  323. +
  324. +-- Some traps and a little loot.
  325. +for _ = 1, 4 do
  326. +    des.object()
  327. +end
  328. +for _ = 1, 6 do
  329. +    des.trap()
  330. +end
  331. +
  332. +-- With so many trees, having every single one bear fruit seems excessive.
  333. +selection.area(00, 00, 60, 20):filter_mapchar("T"):iterate(function(x, y)
  334. +    des.feature({type = "tree", coord = {x, y},
  335. +                 looted = percent(90), swarm = percent(80)})
  336. +end)
  337. diff --git c/dat/Inf-strt.lua i/dat/Inf-strt.lua
  338. new file mode 100644
  339. index 000000000..d0f834163
  340. --- /dev/null
  341. +++ i/dat/Inf-strt.lua
  342. @@ -0,0 +1,107 @@
  343. +-- The "start" level for the quest.
  344. +
  345. +-- Here you meet your class leader, the preacher of Moloch,
  346. +-- and receive an invitation to a duel with the Paladin.
  347. +
  348. +des.level_flags("mazelevel", "noteleport", "hardfloor", "noflipx")
  349. +des.level_init({style = "solidfill", fg = " "});
  350. +
  351. +des.map({halign = "right", valign = "center", map =
  352. +--         1         2         3         4         5         6
  353. +--1234567890123456789012345678901234567890123456789012345678901
  354. +[[
  355. +0                                    |.........................
  356. +1                                    |.........................
  357. +2                  -----             --........................
  358. +3   ----         ---...-----         --........................
  359. +4   |..|        --.........|         |.........................
  360. +5   |..|        |..........|        --.........................
  361. +6   -+--      ---..........----     |..........................
  362. +7    #      ---...............|     --.........................
  363. +8    #      |.................---    |.........................
  364. +9 ---S-   ---...................|    |-........................
  365. +0 |...|   |.....................+####S.........................
  366. +1 |...+###+.....................|    |.........................
  367. +2 |...|   |....................--    |.........................
  368. +3 -----   ----.................|    --.........................
  369. +4            |.................|    |..........................
  370. +5     ---- ##S...............---   --..........................
  371. +6     |..| # ---............--     |...........................
  372. +7     |..+##   |........-----      --..........................
  373. +8     |..|     ----------           |..........................
  374. +9     |..|                          |-.........................
  375. +0     ----                          |..........................
  376. +]]})
  377. +des.non_diggable(selection.area(00, 00, 37, 20))
  378. +
  379. +-- You arrive at a sparsely wooded cliffside.
  380. +des.replace_terrain({region = {35, 00, 61, 20}, fromterrain = ".",
  381. +                     toterrain = "T", chance = 1});
  382. +des.levregion({type = "branch", region = {38, 00, 61, 20}})
  383. +local outside = selection.area(35, 00, 61, 20):filter_mapchar(".")
  384. +outside:set(37, 10, 0) -- see dart trap below
  385. +for _ = 1, d(3, 4) do
  386. +    des.monster("d", outside:rndcoord(1))
  387. +end
  388. +if percent(20) then
  389. +    des.monster("black unicorn", outside:rndcoord(1))
  390. +end
  391. +for _ = 1, 3 do
  392. +    des.trap({coord = {outside:rndcoord(1)}})
  393. +end
  394. +
  395. +-- The Hidden Temple is behind a secret door.
  396. +-- The altar is coaligned, but haunted,
  397. +-- presumably having been forcibly converted in the past.
  398. +des.trap("dart", 37, 10)
  399. +des.door("locked", 31, 10)
  400. +des.region({x1 = 20, y1 = 10, irregular = true,
  401. +            lit = 1, type = "temple"})
  402. +des.altar({coord = {20, 10}, align="coaligned", type="altar"})
  403. +des.monster("preacher of Moloch", 20, 10)
  404. +for _, coord in pairs({{20, 07}, {23, 08}, {24, 10}, {23, 12},
  405. +                       {20, 13}, {17, 12}, {16, 10}, {17, 08}}) do
  406. +    des.monster("cultist", coord)
  407. +end
  408. +
  409. +-- Some "decorations".
  410. +local around_altar = selection.ellipse(20, 10, 4, 3, 1)
  411. +for _ = 1, 3 do
  412. +    des.object({id = "corpse", montype = "elf",
  413. +                coord = {around_altar:rndcoord(1)}})
  414. +end
  415. +for _ = 1, 2 do
  416. +    des.object({id = "corpse", montype = "human",
  417. +                coord = {around_altar:rndcoord(1)}})
  418. +end
  419. +local statues = {{20, 04}, {24, 05}, {27, 08}, {28, 13},
  420. +                 {25, 15}, {19, 16}, {14, 14}, {13, 09}}
  421. +shuffle(statues)
  422. +for idx, mon in ipairs({"horned devil", "barbed devil", "marilith",
  423. +                        "vrock", "hezrou", "bone devil", "ice devil",
  424. +                        "pit fiend"}) do
  425. +    des.object({id = "statue", montype = mon,
  426. +                coord = statues[idx], contents = false})
  427. +end
  428. +
  429. +-- Entrance to the underground complex leading to the Howling Forest.
  430. +des.door("closed", 09, 11)
  431. +des.door("closed", 05, 11)
  432. +des.region(selection.area(02, 10, 04, 12), "lit")
  433. +des.stair("down", 03, 11)
  434. +
  435. +-- Unholy water supply.
  436. +des.door("locked", 04, 06)
  437. +des.region(selection.area(04, 04, 05, 05), "lit")
  438. +for x = 04, 05 do
  439. +    des.object({class = "!", id = "water", buc = "cursed",
  440. +                quantity = d(2), coord = {x, 04}})
  441. +end
  442. +
  443. +-- A small cache of valuables.
  444. +des.door("locked", 08, 17)
  445. +des.region(selection.area(06, 16, 07, 19), "lit")
  446. +des.object({coord = {06, 16}})
  447. +des.object({coord = {06, 17}})
  448. +des.object("axe", 06, 18)
  449. +des.object({coord = {06, 19}})
  450. diff --git c/dat/astral.lua i/dat/astral.lua
  451. index 5a3a70286..0952eebfa 100644
  452. --- c/dat/astral.lua
  453. +++ i/dat/astral.lua
  454. @@ -8,7 +8,12 @@ des.level_init({ style = "solidfill", fg = " " });
  455.  
  456.  des.level_flags("mazelevel", "noteleport", "hardfloor", "nommap", "shortsighted", "solidify")
  457.  des.message("You arrive on the Astral Plane!")
  458. -des.message("Here the High Temple of %d is located.")
  459. +if u.role == "Infidel" then
  460. +    -- the temple of Moloch isn't here!
  461. +    des.message("Here the High Temples of the heaven are located.")
  462. +else
  463. +    des.message("Here the High Temple of %d is located.")
  464. +end
  465.  des.message("You sense alarm, hostility, and excitement in the air!")
  466.  des.map([[
  467.                                ---------------                              
  468. @@ -33,6 +38,15 @@ des.map([[
  469.                               -----------------                            
  470.  ]]);
  471.  
  472. +-- For Infidels, the minions of Moloch are replaced by minions
  473. +-- of a random aligned god; otherwise this level would be too easy
  474. +local enemy
  475. +if u.role == "Infidel" then
  476. +    enemy = "noncoaligned"
  477. +else
  478. +    enemy = "noalign"
  479. +end
  480. +
  481.  -- chance to alter above map and turn the wings of the bottom-center into
  482.  -- a pair of big (5x15) rooms
  483.  for i=1,2 do
  484. @@ -59,7 +73,7 @@ for i=1,2 do
  485.       end
  486.       -- extra monsters; was [6 + 3d4] when both wings were opened up at once
  487.       for i=1,3 + math.random(2 - 1,2*3) do
  488. -        des.monster({ id="Angel", coord = { hall:rndcoord(1) }, align="noalign", peaceful=0 })
  489. +        des.monster({ id="Angel", coord = { hall:rndcoord(1) }, align=enemy, peaceful=0 })
  490.          if percent(50) then
  491.             des.monster({ coord = { hall:rndcoord(1) }, peaceful=0 })
  492.          end
  493. @@ -104,28 +118,28 @@ des.non_diggable(selection.area(00,00,74,19))
  494.  des.non_passwall(selection.area(00,00,74,19))
  495.  -- Moloch's horde
  496.  -- West round room
  497. -des.monster({ id = "aligned priest",x=18,y=09,align="noalign", peaceful=0 })
  498. -des.monster({ id = "aligned priest",x=19,y=08,align="noalign", peaceful=0 })
  499. -des.monster({ id = "aligned priest",x=19,y=09,align="noalign", peaceful=0 })
  500. -des.monster({ id = "aligned priest",x=19,y=10,align="noalign", peaceful=0 })
  501. -des.monster({ id = "Angel",x=20,y=09,align="noalign", peaceful=0 })
  502. -des.monster({ id = "Angel",x=20,y=10,align="noalign", peaceful=0 })
  503. +des.monster({ id = "aligned priest",x=18,y=09,align=enemy, peaceful=0 })
  504. +des.monster({ id = "aligned priest",x=19,y=08,align=enemy, peaceful=0 })
  505. +des.monster({ id = "aligned priest",x=19,y=09,align=enemy, peaceful=0 })
  506. +des.monster({ id = "aligned priest",x=19,y=10,align=enemy, peaceful=0 })
  507. +des.monster({ id = "Angel",x=20,y=09,align=enemy, peaceful=0 })
  508. +des.monster({ id = "Angel",x=20,y=10,align=enemy, peaceful=0 })
  509.  des.monster({ id = "Pestilence", coord = { place:rndcoord(1) }, peaceful=0 })
  510.  -- South-central round room
  511. -des.monster({ id = "aligned priest",x=36,y=12,align="noalign", peaceful=0 })
  512. -des.monster({ id = "aligned priest",x=37,y=12,align="noalign", peaceful=0 })
  513. -des.monster({ id = "aligned priest",x=38,y=12,align="noalign", peaceful=0 })
  514. -des.monster({ id = "aligned priest",x=36,y=13,align="noalign", peaceful=0 })
  515. -des.monster({ id = "Angel",x=38,y=13,align="noalign", peaceful=0 })
  516. -des.monster({ id = "Angel",x=37,y=13,align="noalign", peaceful=0 })
  517. +des.monster({ id = "aligned priest",x=36,y=12,align=enemy, peaceful=0 })
  518. +des.monster({ id = "aligned priest",x=37,y=12,align=enemy, peaceful=0 })
  519. +des.monster({ id = "aligned priest",x=38,y=12,align=enemy, peaceful=0 })
  520. +des.monster({ id = "aligned priest",x=36,y=13,align=enemy, peaceful=0 })
  521. +des.monster({ id = "Angel",x=38,y=13,align=enemy, peaceful=0 })
  522. +des.monster({ id = "Angel",x=37,y=13,align=enemy, peaceful=0 })
  523.  des.monster({ id = "Death", coord = { place:rndcoord(1) }, peaceful=0 })
  524.  -- East round room
  525. -des.monster({ id = "aligned priest",x=56,y=09,align="noalign", peaceful=0 })
  526. -des.monster({ id = "aligned priest",x=55,y=08,align="noalign", peaceful=0 })
  527. -des.monster({ id = "aligned priest",x=55,y=09,align="noalign", peaceful=0 })
  528. -des.monster({ id = "aligned priest",x=55,y=10,align="noalign", peaceful=0 })
  529. -des.monster({ id = "Angel",x=54,y=09,align="noalign", peaceful=0 })
  530. -des.monster({ id = "Angel",x=54,y=10,align="noalign", peaceful=0 })
  531. +des.monster({ id = "aligned priest",x=56,y=09,align=enemy, peaceful=0 })
  532. +des.monster({ id = "aligned priest",x=55,y=08,align=enemy, peaceful=0 })
  533. +des.monster({ id = "aligned priest",x=55,y=09,align=enemy, peaceful=0 })
  534. +des.monster({ id = "aligned priest",x=55,y=10,align=enemy, peaceful=0 })
  535. +des.monster({ id = "Angel",x=54,y=09,align=enemy, peaceful=0 })
  536. +des.monster({ id = "Angel",x=54,y=10,align=enemy, peaceful=0 })
  537.  des.monster({ id = "Famine", coord = { place:rndcoord(1) }, peaceful=0 })
  538.  --
  539.  -- The aligned horde
  540. diff --git c/dat/data.base i/dat/data.base
  541. index b4ada5b50..39f883f71 100644
  542. --- c/dat/data.base
  543. +++ i/dat/data.base
  544. @@ -71,6 +71,16 @@ agate*
  545.     solution is slowly deposited into cavities and veins in older
  546.     rock.
  547.         [ The Columbia Encyclopedia, Sixth Edition ]
  548. +agent
  549. +agent of *
  550. +   It was part of his profession to kill people.  He had never liked
  551. +   doing it and when he had to kill he did it as well as he knew how
  552. +   and forgot about it.  As a secret agent who held the rare double-O
  553. +   prefix -- the licence to kill in the Secret Service -- it was his
  554. +   duty to be as cool about death as a surgeon.  If it happened,
  555. +   it happened.  Regret was unprofessional -- worse, it was
  556. +   death-watch beetle in the soul.
  557. +       [ Goldfinger, by Ian Fleming ]
  558.  aleax
  559.     Said to be a doppelganger sent to inflict divine punishment
  560.     for alignment violations.
  561. @@ -412,6 +422,8 @@ banshee
  562.         [ Brewer's Concise Dictionary of Phrase and Fable ]
  563.  barbarian
  564.  * barbarian
  565. +champion
  566. +champion of *
  567.     They dressed alike -- in buckskin boots, leathern breeks and
  568.     deerskin shirts, with broad girdles that held axes and short
  569.     swords; and they were all gaunt and scarred and hard-eyed;
  570. @@ -2455,6 +2467,11 @@ idefix
  571.     strong views on the environment (he howls whenever he sees an
  572.     uprooted tree).
  573.         [ Wikipedia, the free encyclopedia ]
  574. +*idol of moloch
  575. +   One of the rare few artifacts able to exert Moloch's influence
  576. +   aboveground.  By drawing on Moloch's power, the faithful are able
  577. +   to summon demons, defile shrines, and replenish their magical
  578. +   energy.  The Idol also protects its holder from hostile magics.
  579.  # takes "imp or minor demon" when specifying 'i'
  580.  imp
  581.  imp or minor demon
  582. @@ -2477,6 +2494,23 @@ succubus
  583.     same demon, one who lies with a human for its own purposes,
  584.     usually to the detriment of the mortals who are unwise in
  585.     their dealings with them.
  586. +infidel
  587. +* infidel
  588. +cultist
  589. +malefic*
  590. +   We must especially observe that this heresy, witchcraft, not only
  591. +   differs from all other heresy in this, that not merely by a tacit
  592. +   compact, but by a compact which is exactly defined and expressed
  593. +   it blasphemes the Creator and endeavours to the utmost to profane Him
  594. +   and to harm His creatures, for all other simple heresies have made
  595. +   no open compact with the devil, no compact, that is, either tacit
  596. +   or exactly expressed, although their errors and misbelief are directly
  597. +   to be attributed to the Father of errors and lies.  Moreover,
  598. +   maleficium (witchcraft) differs from all other harmful and mysterious
  599. +   arts in this point, that of all superstition it is essentially
  600. +   the vilest, the most evil and the worst, wherefore it derives its name
  601. +   from doing evil, and from blaspheming the true faith.
  602. +       [ The Malleus Maleficarum, translated by Montague Summers ]
  603.  *insect
  604.  *insects
  605.     A minute invertebrate animal; one of the class _Insecta_.
  606. @@ -3870,6 +3904,17 @@ page
  607.     of gentle parentage attending a royal or princely personage.
  608.         [ Webster's Comprehensive International Dictionary
  609.           of the English Language ]
  610. +*paladin
  611. +*paladin of *
  612. +   The paladin is a noble and heroic warrior, the symbol of all
  613. +   that is right and true in the world.  As such, he has high ideals
  614. +   that he must maintain at all times.  Throughout legend and history
  615. +   there are many heroes who could be called paladins: Roland and
  616. +   the 12 Peers of Charlemagne, Sir Lancelot, Sir Gawain, and Sir Galahad
  617. +   are all examples of the class.  However, many brave and
  618. +   heroic soldiers have tried and failed to live up to the ideals of
  619. +   the paladin.  It is not an easy task!
  620. +       [ AD&D Player's Handbook, 2nd Edition ]
  621.  *pall
  622.     _Pallium._  The Roman name for a square woollen cloak worn
  623.     by men in ancient Greece, especially by philosophers and
  624. @@ -4607,6 +4652,14 @@ scroll *
  625.     I read these words, and read again, and tried
  626.     My eyes against the heavens, and read again.
  627.         [ Endymion, by John Keats ]
  628. +secespita
  629. +   The secespita is a long iron sacrificial knife, made of brass
  630. +   and copper from Cyprus, with a solid and rounded ivory handle,
  631. +   which is secured to the hilt by a ring of silver or gold.
  632. +   The flamens and their wives, the flaminicae, who were priests
  633. +   and priestesses of the Ancient Rome, the virgins and the pontiffs
  634. +   made use of it for sacrifices.
  635. +       [ Wikipedia, the free encyclopedia ]
  636.  set
  637.  seth
  638.     The ancient Egyptian god of chaos (Set), the embodiment of
  639. @@ -4856,6 +4909,12 @@ javelin
  640.     don't I?"
  641.     "Why, yes, of course," said Wilbur.
  642.         [ Charlotte's Web, by E.B. White ]
  643. +splanchomanc*
  644. +anthropomanc*
  645. +   Anthropomancy is a method of divination by the entrails of dead
  646. +   or dying men or women, often virgin female children, through
  647. +   sacrifice.  This practice was sometimes also called splanchomancy.
  648. +       [ Wikipedia, the free encyclopedia ]
  649.  *spore
  650.  *sphere
  651.     The attack by those who want to die -- this is the attack
  652. @@ -5000,6 +5059,20 @@ susano*o
  653.         [ Encyclopedia of Gods, by Michael Jordan ]
  654.  tanko
  655.     Samurai plate armor of the Yamato period (AD 300 - 710).
  656. +templar
  657. +templar of *
  658. +   Above all things, whosoever would be a knight of Christ,
  659. +   choosing such holy orders, you in your profession of faith
  660. +   must unite pure diligence and firm perseverence, which is so worthy
  661. +   and so holy, and is known to be so noble, that if it is preserved
  662. +   untainted for ever, you will deserve to keep company with the martyrs
  663. +   who gave their souls for Jesus Christ.  In this religious order
  664. +   has flourished and is revitalised the order of knighthood. [...]
  665. +   God works well with us and our saviour Jesus Christ; He has sent
  666. +   his friends from the Holy City of Jerusalem to the marches of France
  667. +   and Burgundy, who for our salvation and the spread of the true faith
  668. +   do not cease to offer their souls to God, a welcome sacrifice.
  669. +       [ Rule of the Knights Templar, translated by J. M. Upton-Ward ]
  670.  tengu
  671.     The tengu was the most troublesome creature of Japanese
  672.     legend.  Part bird and part man, with red beak for a nose
  673. diff --git c/dat/quest.lua i/dat/quest.lua
  674. index d23208b36..54a8e06f8 100644
  675. --- c/dat/quest.lua
  676. +++ i/dat/quest.lua
  677. @@ -1073,6 +1073,382 @@ to be %Ra to know that %n is on the verge of victory.]],
  678.  absence, yes?  How fare you upon your quest for the Amulet?"]],
  679.        },
  680.     },
  681. +    Inf = {
  682. +        legacy = {
  683. +            -- Note: %lh is just to randomize the pronoun,
  684. +            -- the unlucky hero was not actually your leader
  685. +            output = "menu",
  686. +            text = [[
  687. +It is written in the Book of %d:
  688. +
  689. +    After the Creation, the mighty %G %d rebelled
  690. +    against the tyranny of Marduk the Creator.  %d
  691. +    defeated Marduk and obtained from him the most powerful
  692. +    of all the artifacts of the gods, the Amulet of Yendor,
  693. +    and %dH hid it in %dJ dark domain of Gehennom, the
  694. +    Under World, where %dH now gathers power and prepares for
  695. +    the final confrontation.
  696. +
  697. +Many fools were sent by the gods of the heaven after the Amulet,
  698. +only to die in the underground mazes.  By pure luck, one of them
  699. +has succeeded; thankfully, %lh was ambushed on the way back
  700. +and the Amulet was recovered by %ds Cult.
  701. +
  702. +You, a newly trained %r, have been heralded
  703. +from birth as the instrument of %d.  You are destined
  704. +to return the Amulet to its rightful owner, or die in the
  705. +attempt.  Your hour of destiny has come.  For the sake
  706. +of us all:  Go bravely with %d!]],
  707. +            synopsis = "%dC has chosen you "
  708. +            .. "to return the Amulet of Yendor to %dI."
  709. +        },
  710. +        firsttime = {
  711. +            output = "text",
  712. +            text = [[
  713. +You arrive at the mouth of a cave that hosts %H.  This is
  714. +the place where %l taught you the glory of %d,
  715. +where you studied black arts with your fellow %gp,
  716. +and where you were chosen for your unholy mission.
  717. +
  718. +You did not expect to be back so soon.
  719. +Why has %l called you?
  720. +
  721. +It is nighttime, and the moonlight is scattered by clouds.  You make sure
  722. +to stay in the shadows, for even here you are likely to be ambushed
  723. +for your precious cargo.  The surface is never safe for you now.]],
  724. +            synopsis = "You arrive near %H.  "
  725. +            .. "Talk to %l to find out why %lh called you."
  726. +        },
  727. +        nexttime = {
  728. +            text = "Once again, you near %H."
  729. +        },
  730. +        othertime = {
  731. +            text = "Again you face %H.  "
  732. +            .. "%dS presence feels fainter than usual.  "
  733. +            .. "You wonder if you'll be allowed to return here yet again."
  734. +        },
  735. +        guardtalk_before = {
  736. +            '"Agents of the false gods are everywhere!  '
  737. +            .. 'I got my purse stolen!"',
  738. +            '"I was once biten by a werewolf in %i.  '
  739. +            .. 'It\'s not nearly as glamorous as the books make it sound."',
  740. +            '"I just noticed a pile of skulls in that corner.  '
  741. +            .. '%pC... are we the baddies?"',
  742. +            -- Note: this will obviously need to be rewritten
  743. +            -- if the Paladin's gender changes
  744. +            '"%nC of %D acts all high and mighty, '
  745. +            .. 'but %nh\'s still just a woman."',
  746. +            '"We were THIS close to recovering %o by ourselves!  '
  747. +            .. 'The church of %D just got lucky... and a better funding."'
  748. +        },
  749. +        leader_first = {
  750. +            output = "text",
  751. +            text = [[
  752. +"My %S, welcome back.  You must be wondering why I have interrupted
  753. +your mission!  As it happens, another quest has arisen that
  754. +only you can undertake.  Let me see if you're up to the challenge."]],
  755. +            synopsis = "I have another important mission for you, "
  756. +            .. "if you're ready."
  757. +        },
  758. +        leader_next = {
  759. +            text = '"Welcome again, %p.  I hope you\'re ready this time."'
  760. +        },
  761. +        leader_other = {
  762. +            text = '"Again you return, %p.  %nC won\'t wait forever!  '
  763. +            .. 'Are you ready now?"'
  764. +        },
  765. +        leader_last = {
  766. +            output = "text",
  767. +            text = [[
  768. +"I am most disappointed, %p.  The fire of %d no longer
  769. +burns in your breast!  How could you abandon your faith so easily?
  770. +You're no longer our %s.  Begone and never return!  We will
  771. +find someone else to finish your quest."]],
  772. +            synopsis = "You're exiled from the Cult for your lack of faith."
  773. +        },
  774. +        badlevel = {
  775. +            output = "text",
  776. +            text = [[
  777. +"Alas, %p, you're still weak.  I cannot in good faith send you
  778. +against %n of %D now; %nh'll squash you
  779. +like an insect!  You must train and attain more skill;
  780. +come back when you're a proper %R."]],
  781. +            synopsis = "%rA has no chance against %n.  "
  782. +            .. "Come back when you are %Ra."
  783. +        },
  784. +        badalign = {
  785. +            output = "text",
  786. +            text = [[
  787. +"No, that will not do.  The fire of %d within you is too weak.
  788. +Only with the support of our faith can you hope to prevail!
  789. +Go back to %Z and perform more sacrifices to
  790. +honor %d.  When your devotion is strong again, you may return."]],
  791. +            synopsis = "Your faith is too weak.  "
  792. +            .. "Return when you're sufficently %a."
  793. +        },
  794. +        assignquest = {
  795. +            output = "text",
  796. +            text = [[
  797. +"Yes, my %S.  You are now as ready as you'll ever be.  Listen
  798. +carefully as I explain the current situation and your new quest.
  799. +
  800. +"As you must know, we have long searched for the lost %ot,
  801. +for it is vitally important both to our faith and the ultimate plan
  802. +of our %GC %d.  But the church of %D
  803. +has learned of our efforts and sponsored a team of professional
  804. +archeologists to find %O first.  Unfortunately, it seems
  805. +they were succesful.
  806. +
  807. +"A week ago, the Cult has received a message from a prominent %nt
  808. +of %D.  %nH claims that %O is in
  809. +%nj posession, and challenges you to a `honorable duel' for the artifact.
  810. +%nC was adamant in dueling you specifically, so it's
  811. +clearly a ploy to obtain the Amulet of Yendor that was entrusted to you.
  812. +
  813. +"We have no choice but to accept, as without %O %ds plan
  814. +cannot be completed.  %nC of %D
  815. +waits for you in the ancient ruins amidst %i, which
  816. +can be reached through the underground complex below our temple.
  817. +You must travel there and retrieve %o by any means.
  818. +
  819. +"%dC be your strength, %p.  Go with %dJ blessing."]],
  820. +            synopsis = "%nC of %D found %o and challenged you to a duel.  "
  821. +            .. "Kill %ni by any means."
  822. +        },
  823. +        encourage = {
  824. +            '"As long as the fire of %d burns within your chest, '
  825. +            .. 'you will prevail."',
  826. +            '"%nC of %D is a capable spellcaster as well as a powerful '
  827. +            .. 'warrior.  Approach %ni with care and think before acting."',
  828. +            -- This was supposed to hint to her being immune to scare monster.
  829. +            -- Probably no longer relevant for 3.7?
  830. +            '"%nC of %Ds faith is very strong, '
  831. +            .. 'and as such %nh knows no fear."',
  832. +            '"%iC is plagued by werewolves.  '
  833. +            .. 'If you can wield silver weapons, do so."',
  834. +            '"If you know how to evoke fireballs, '
  835. +            .. 'it will be your greatest aid.  %nC may be well-armored, '
  836. +            .. 'but that won\'t protect %ni from burning alive!"',
  837. +            '"%oC protects %oi holder from many harmful magics.  '
  838. +            .. 'Unfortunately, %oi current holder is %n.  '
  839. +            .. 'If you can somehow steal %oh, it will aid you greatly."',
  840. +            '"When you obtain %o, you may call for %ds aid at any time.  '
  841. +            .. 'Even at the surface, you will be answered."',
  842. +            '"Watch where you aim your wands: '
  843. +            .. '%n of %D has a magical reflective shield."',
  844. +            '"The church of %D wouldn\'t risk %O if they weren\'t sure '
  845. +            .. '%n can defeat you in a fair fight.  So don\'t fight fair!"',
  846. +            '"%nC of %D is immune to mundane poisons, '
  847. +            .. 'but a paralyzing venom will work wonders on %ni."'
  848. +        },
  849. +        locate_first = {
  850. +            output = "text",
  851. +            text = [[
  852. +The gloom and stillness of the underground caves gives way to moonlight,
  853. +hooting of owls, and an occasional blood-chilling howl.
  854. +
  855. +%iC lies ahead.  Somewhere in these woods
  856. +%n of %D awaits you.]],
  857. +            synopsis = "You have reached %i.  %nC is somewhere ahead."
  858. +        },
  859. +        locate_next = {
  860. +            text = "Again, you stand at the edge of %i."
  861. +        },
  862. +        goal_first = {
  863. +            output = "text",
  864. +            text = [[
  865. +You've reached a clearing in the forest.  In the distance, you can %x
  866. +the ancient ruins where %n of %D
  867. +has challenged you to the duel.
  868. +
  869. +It's still nighttime.  Hopefully you can sneak up unnoticed, but what then?]],
  870. +            synopsis = "You have found the dueling field.  "
  871. +            .. "You must proceed carefully."
  872. +        },
  873. +        goal_next = {
  874. +            text = "Once again, you approach the ancient ruins."
  875. +        },
  876. +        nemesis_first = {
  877. +            output = "text",
  878. +            text = [[
  879. +"Ah, %p.  You've answered my challenge, after all.
  880. +It seems that your vile cult has at least some recognition of honor.
  881. +
  882. +"But no matter.  Your malignant existence is an affront to
  883. +%D, and it is by my hand that it will end today.
  884. +
  885. +"And after I defeat you and take the Amulet from your undeserving grasp,
  886. +I will destroy %o once and for all, and your cult
  887. +shall soon follow!
  888. +
  889. +"Prepare yourself, villian, for your final judgement!"]],
  890. +            synopsis = "I shall defeat you and then destroy %o and your cult."
  891. +        },
  892. +        nemesis_next = {
  893. +            text = '"Again you return, %p.  '
  894. +            .. 'Did you think running away could help you somehow?"'
  895. +        },
  896. +        nemesis_other = {
  897. +            text = '"Surely by now you understand that you '
  898. +            .. 'haven\'t got a chance.  Accept your fate and die, coward!"'
  899. +        },
  900. +        nemesis_wantsit = {
  901. +            text = '"Wha-- how?  Get back here, thief!  We\'re not done yet!"'
  902. +        },
  903. +        discourage = {
  904. +            '"%dC is a coward who can but hide underground.  '
  905. +            .. 'Aren\'t you ashamed to be %dj slave?"',
  906. +            '"You\'re a disgrace both as a combatant and as %ra.  '
  907. +            .. 'Why do I even bother?"',
  908. +            '"I hope you like fire, because that\'s '
  909. +            .. 'how you\'re going to spend the rest of eternity."',
  910. +            '"Ready to give up, %p?  You know your %G can\'t help you here."',
  911. +            '"The judgement of %D is upon you now!"',
  912. +            '"When I claim the Amulet of Yendor for %D, '
  913. +            .. '%d will become but a footnote in a history book."',
  914. +            '"Did %l really think %ra could even reach the bottom '
  915. +            .. 'of Gehennom?  The Amulet will be much safer with me."',
  916. +            '"None of your fellow %gp will survive my wrath.  '
  917. +            .. 'This I promise."',
  918. +            '"For your sins, you will die today!"',
  919. +            '"You will never have %o, and soon, you will lose your life."'
  920. +        },
  921. +        gotit = {
  922. +            output = "text",
  923. +            text = [[
  924. +As you pick up %o, you feel the presence of %d clearer
  925. +than ever.  The power of %d encompasses your soul, and you instantly
  926. +understand why your Cult was searching for %O, and why
  927. +%n of %D wanted to destroy %oi.
  928. +
  929. +You must return to %l at once.  With %O,
  930. +the Cult will be more powerful than ever!]],
  931. +            synopsis = "You feel the power of %d as you touch %O; "
  932. +            .. "return to %l with %oi."
  933. +        },
  934. +        killed_nemesis = {
  935. +            output = "text",
  936. +            text = [[
  937. +%nC falls to %ni knees.  With %ni last breath, %nh whispers:
  938. +
  939. +    "Don't... think you've won just yet.  I am but one servant of
  940. +    %D out of many, and other gods are...
  941. +    after you as well.  You will... never reach %d alive.
  942. +    The justice will..."
  943. +
  944. +A ray of bright light pierces the dawning sky, and %ns body is gone.]],
  945. +            synopsis = "%nC of %D dies, but others are after the Amulet."
  946. +        },
  947. +        offeredit = {
  948. +            output = "text",
  949. +            text = [[
  950. +"%pC, you are victorous!  Well done.  %dC is pleased
  951. +by your success.  All of us are proud of you as well.
  952. +
  953. +"You must now continue on your original mission.  But along with
  954. +the Amulet, you must also deliver %O to %ds Sanctum.
  955. +Such is %dJ will, and such is %dJ plan.
  956. +
  957. +"When you reach the high altar, the final phase of the plan will be
  958. +revealed to you.  Remember to keep %o on you
  959. +at all times!  If %oh's lost, all our preparations will be ruined."]],
  960. +            synopsis = "You must bring %O to %d along with the Amulet."
  961. +        },
  962. +        quest_complete_no_bell = {
  963. +            text = '"The silver bell which was carried by %n of %D '
  964. +            .. 'will be essential for entering %ds Sanctum."',
  965. +        },
  966. +        offeredit2 = {
  967. +            output = "text",
  968. +            text = [[
  969. +"You're %Os keeper now, but %d alone is %oj owner.
  970. +You must bring %oh to %dI along with the Amulet of Yendor.
  971. +%Z await your return through
  972. +the magic portal that brought you here."]],
  973. +            synopsis = "%OC is your responsibility now.  "
  974. +            .. "Bring it to %d along with the Amulet."
  975. +        },
  976. +        guardtalk_after = {
  977. +            '"Agents of the false gods are everywhere!  '
  978. +            .. 'I got my purse stolen!"',
  979. +            '"Glory to %d, %s!  Let\'s drink elf blood together!"',
  980. +            '"I just noticed a pile of skulls in that corner.  '
  981. +            .. '%pC... are we the baddies?"',
  982. +            '"Have you made sure to properly desecrate %ns corpse?  '
  983. +            .. 'Appearances are important!"',
  984. +            '"%oC is ours!  Take that, professional archeology!"'
  985. +        },
  986. +        posthanks = {
  987. +            text = '"Welcome back, my %S.  '
  988. +            .. 'Have you found your way to Sanctum yet?"'
  989. +        },
  990. +        moloch_missing = {
  991. +            output = "text",
  992. +            text = [[
  993. +Very good, My pawn.  Thou hast finally reached here.  But where is
  994. +Mine %Ot that was entrusted to thee?  Thou wast told to bring %oi here.
  995. +For thy sake, I hope thou hast not lost it!
  996. +
  997. +Return with %O and invoke My name here, and do not falter.]],
  998. +            synopsis = "Fetch %o and invoke %oi on My high altar."
  999. +        },
  1000. +        moloch = {
  1001. +            output = "text",
  1002. +            text = [[
  1003. +"My pawn, thou hast done well.  Now listen carefully, for the time
  1004. +for thy final test has come.
  1005. +
  1006. +"A deity who wields the Amulet of Yendor can claim dominion over
  1007. +the gods of the heaven, the position that is Mine by right.  But I am
  1008. +no longer welcome among them, so I must take My place by force.
  1009. +
  1010. +"%OC that thou carriest is a vessel for My power, and now I shall
  1011. +make %oi the vessel for the Amulet's true power as well.  Carrying %oi
  1012. +will allow thee to journey to the Astral Plane in the heaven.  There,
  1013. +the false gods reside.
  1014. +
  1015. +"Find the weakest among them and invoke Mine %Ot in their temple.
  1016. +I will take their place, and all will bow to My rule, as they should.
  1017. +
  1018. +"Which deity is the weakest, thou must find out thyself.  Perhaps My
  1019. +servants can advise you."]],
  1020. +            synopsis = "Travel to Astral Plane "
  1021. +            .. "and convert one of the high altars."
  1022. +        },
  1023. +        -- Note: in the next two messages, %a and %d refer
  1024. +        -- to one of the aligned gods at random.
  1025. +        -- Consequently, "Moloch" is typed directly,
  1026. +        -- which may break hypothetical aligned Infidels.
  1027. +        high_priest = {
  1028. +            output = "text",
  1029. +            text = [[
  1030. +"My %S, we all pray for thy success on thy quest.  The false gods
  1031. +posess power beyond any mere mortal, and even with Moloch's help
  1032. +overthrowing one of them will be a challenge.  Chose thine opponent wisely.
  1033. +
  1034. +"I shall offer thee an advice.  Last night, I had a vision.  There was
  1035. +a great battle in the heaven; the forces of our Lord Moloch were besieging
  1036. +a fortress of %d.  But %dj %a minions held their
  1037. +ground for thirty days and nights and, sadly, the fortress was not taken.
  1038. +
  1039. +"The meaning here is clear: when in thy mission thou reachest the heaven,
  1040. +challenging %d will likely be futile.  Keep this in mind."]],
  1041. +            synopsis = "You should avoid invoking %o on the %a high altar."
  1042. +        },
  1043. +        delivered_amulet = {
  1044. +            output = "text",
  1045. +            text = [[
  1046. +"Congratulations, %p!  We are closer than ever to the ultimate victory.
  1047. +
  1048. +"As Moloch has told you, you must now bring %O to one of the high altars
  1049. +on the Astral Plane.  It's hard to say which deity will be more susceptible
  1050. +to Moloch's power, but in all my years fending off non-believers,
  1051. +I have noticed that %ap are unusually resistant to my clerical magic.
  1052. +
  1053. +"Perhaps that extends to %d %diself, as well."]],
  1054. +            synopsis = "You should avoid invoking %o on the %a high altar."
  1055. +        }
  1056. +    },
  1057.     Kni = {
  1058.        assignquest = {
  1059.           synopsis = "[Pass through %i to reach %n.  Destroy %ni and return with %o.]",
  1060. diff --git c/dat/sanctum.lua i/dat/sanctum.lua
  1061. index 45aa0b361..e8b704889 100644
  1062. --- c/dat/sanctum.lua
  1063. +++ i/dat/sanctum.lua
  1064. @@ -105,22 +105,29 @@ des.object("?")
  1065.  des.object("?")
  1066.  des.object("?")
  1067.  des.object("?")
  1068. +-- Make Sanctum monsters more friendly to Infidels
  1069. +local to_infidels
  1070. +if u.role == "Infidel" then
  1071. +    to_infidels = 1
  1072. +else
  1073. +    to_infidels = 0
  1074. +end
  1075.  -- Some monsters.
  1076. -des.monster({ id = "horned devil", x=14,y=12,peaceful=0 })
  1077. -des.monster({ id = "barbed devil", x=18,y=08,peaceful=0 })
  1078. -des.monster({ id = "erinys", x=10,y=04,peaceful=0 })
  1079. -des.monster({ id = "marilith", x=07,y=09,peaceful=0 })
  1080. -des.monster({ id = "nalfeshnee", x=27,y=08,peaceful=0 })
  1081. +des.monster({ id = "horned devil", x=14,y=12,peaceful=to_infidels })
  1082. +des.monster({ id = "barbed devil", x=18,y=08,peaceful=to_infidels })
  1083. +des.monster({ id = "erinys", x=10,y=04,peaceful=to_infidels })
  1084. +des.monster({ id = "marilith", x=07,y=09,peaceful=to_infidels })
  1085. +des.monster({ id = "nalfeshnee", x=27,y=08,peaceful=to_infidels })
  1086.  -- Moloch's horde
  1087. -des.monster({ id = "aligned priest", x=20,y=03,align="noalign",peaceful=0 })
  1088. -des.monster({ id = "aligned priest", x=15,y=04,align="noalign",peaceful=0 })
  1089. -des.monster({ id = "aligned priest", x=11,y=05,align="noalign",peaceful=0 })
  1090. -des.monster({ id = "aligned priest", x=11,y=07,align="noalign",peaceful=0 })
  1091. -des.monster({ id = "aligned priest", x=11,y=09,align="noalign",peaceful=0 })
  1092. -des.monster({ id = "aligned priest", x=11,y=12,align="noalign",peaceful=0 })
  1093. -des.monster({ id = "aligned priest", x=15,y=13,align="noalign",peaceful=0 })
  1094. -des.monster({ id = "aligned priest", x=17,y=13,align="noalign",peaceful=0 })
  1095. -des.monster({ id = "aligned priest", x=21,y=13,align="noalign",peaceful=0 })
  1096. +des.monster({ id = "aligned priest", x=20,y=03,align="noalign",peaceful=to_infidels })
  1097. +des.monster({ id = "aligned priest", x=15,y=04,align="noalign",peaceful=to_infidels })
  1098. +des.monster({ id = "aligned priest", x=11,y=05,align="noalign",peaceful=to_infidels })
  1099. +des.monster({ id = "aligned priest", x=11,y=07,align="noalign",peaceful=to_infidels })
  1100. +des.monster({ id = "aligned priest", x=11,y=09,align="noalign",peaceful=to_infidels })
  1101. +des.monster({ id = "aligned priest", x=11,y=12,align="noalign",peaceful=to_infidels })
  1102. +des.monster({ id = "aligned priest", x=15,y=13,align="noalign",peaceful=to_infidels })
  1103. +des.monster({ id = "aligned priest", x=17,y=13,align="noalign",peaceful=to_infidels })
  1104. +des.monster({ id = "aligned priest", x=21,y=13,align="noalign",peaceful=to_infidels })
  1105.  -- A few nasties
  1106.  des.monster("L")
  1107.  des.monster("L")
  1108. diff --git c/dat/valley.lua i/dat/valley.lua
  1109. index adcd4e80f..1741fb3e4 100644
  1110. --- c/dat/valley.lua
  1111. +++ i/dat/valley.lua
  1112. @@ -77,6 +77,7 @@ des.non_diggable(selection.area(00,00,75,19))
  1113.  -- **LOTS** of dead bodies (all human).
  1114.  -- note: no priest(esse)s or monks - maybe Moloch has a *special*
  1115.  --       fate reserved for members of *those* classes.
  1116. +--       Obviously, no Infidel corpses as well.
  1117.  --
  1118.  des.object({ id="corpse",montype="archeologist" })
  1119.  des.object({ id="corpse",montype="archeologist" })
  1120. diff --git c/doc/Guidebook.mn i/doc/Guidebook.mn
  1121. index b10e8ca25..9766bd92d 100644
  1122. --- c/doc/Guidebook.mn
  1123. +++ i/doc/Guidebook.mn
  1124. @@ -132,6 +132,11 @@ and neutralize poisons; and with their instruments, they can divine a
  1125.  being's state of health or sickness.  Their medical practice earns them
  1126.  quite reasonable amounts of money, with which they enter the dungeon.
  1127.  .pg
  1128. +\fIInfidels\fP are cultists of the evil god Moloch.  They are quite
  1129. +proficient in black magics, but less so in the physical combat.  As an
  1130. +Infidel, your goal is not to retrieve the Amulet, but to return it to its
  1131. +hiding place within Gehennom.
  1132. +.pg
  1133.  \fIKnights\fP are distinguished from the common skirmisher by their
  1134.  devotion to the ideals of chivalry and by the surpassing excellence of
  1135.  their armor.
  1136. diff --git c/doc/Guidebook.tex i/doc/Guidebook.tex
  1137. index 937000f8f..7c1ad7777 100644
  1138. --- c/doc/Guidebook.tex
  1139. +++ i/doc/Guidebook.tex
  1140. @@ -139,6 +139,12 @@ of health or sickness.  Their medical practice earns them quite reasonable
  1141.  amounts of money, with which they enter the dungeon.
  1142.  %.pg
  1143.  %
  1144. +\item[\bb{Infidels}]%
  1145. +are cultists of the evil god Moloch.  They are quite proficient in black
  1146. +magics, but less so in the physical combat.  As an Infidel, your goal is not
  1147. +to retrieve the Amulet, but to return it to its hiding place within Gehennom.
  1148. +%.pg
  1149. +%
  1150.  \item[\bb{Knights}]%
  1151.  are distinguished from the common skirmisher by their
  1152.  devotion to the ideals of chivalry and by the surpassing excellence of
  1153. diff --git c/include/artifact.h i/include/artifact.h
  1154. index 4e5193f55..49fddb636 100644
  1155. --- c/include/artifact.h
  1156. +++ i/include/artifact.h
  1157. @@ -66,7 +66,8 @@ enum invoke_prop_types {
  1158.      LEV_TELE,
  1159.      CREATE_PORTAL,
  1160.      ENLIGHTENING,
  1161. -    CREATE_AMMO
  1162. +    CREATE_AMMO,
  1163. +    CHANNEL
  1164.  };
  1165.  
  1166.  #endif /* ARTIFACT_H */
  1167. diff --git c/include/artilist.h i/include/artilist.h
  1168. index d7b8f250c..cac08f352 100644
  1169. --- c/include/artilist.h
  1170. +++ i/include/artilist.h
  1171. @@ -29,6 +29,7 @@ static const char *artifact_names[] = {
  1172.  #define     FIRE(a,b)   {0,AD_FIRE,a,b}
  1173.  #define     ELEC(a,b)   {0,AD_ELEC,a,b}         /* electrical shock */
  1174.  #define     STUN(a,b)   {0,AD_STUN,a,b}         /* magical attack */
  1175. +#define     DREN(a,b)   {0,AD_DREN,a,b}         /* drains energy */
  1176.  /* clang-format on */
  1177.  
  1178.  static NEARDATA struct artifact artilist[] = {
  1179. @@ -163,6 +164,12 @@ static NEARDATA struct artifact artilist[] = {
  1180.        PHYS(5, 0), DFNS(AD_BLND), NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM, 1500L,
  1181.        NO_COLOR),
  1182.  
  1183. +    /* The energy drain only works if the artifact kills its victim.
  1184. +     * Also increases sacrifice value while wielded. */
  1185. +    A("Secespita", KNIFE, (SPFX_RESTR | SPFX_ATTK), 0, 0,
  1186. +      DREN(5, 1), NO_DFNS, NO_CARY, 0, A_CHAOTIC, PM_INFIDEL, NON_PM,
  1187. +      1000L, NO_COLOR),
  1188. +
  1189.      /*
  1190.       *      The artifacts for the quest dungeon, all self-willed.
  1191.       */
  1192. @@ -197,6 +204,13 @@ A("The Palantir of Westernesse",        CRYSTAL_BALL,
  1193.        0, 0, DRLI(0, 0), DRLI(0, 0), NO_CARY, HEALING, A_NEUTRAL, PM_HEALER,
  1194.        NON_PM, 5000L, NO_COLOR),
  1195.  
  1196. +    /* Also confers energy regeneration,
  1197. +     * but only to those in good standing with Moloch. */
  1198. +    A("The Idol of Moloch", FIGURINE,
  1199. +      (SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL), SPFX_HSPDAM, 0,
  1200. +      NO_ATTK, NO_DFNS, CARY(AD_MAGM), CHANNEL, A_CHAOTIC, PM_INFIDEL, NON_PM,
  1201. +      4000L, NO_COLOR),
  1202. +
  1203.      A("The Magic Mirror of Merlin", MIRROR,
  1204.        (SPFX_NOGEN | SPFX_RESTR | SPFX_INTEL | SPFX_SPEAK), SPFX_ESP, 0,
  1205.        NO_ATTK, NO_DFNS, CARY(AD_MAGM), 0, A_LAWFUL, PM_KNIGHT, NON_PM, 1500L,
  1206. diff --git c/include/context.h i/include/context.h
  1207. index e2bd9b49f..7be6e65e9 100644
  1208. --- c/include/context.h
  1209. +++ i/include/context.h
  1210. @@ -127,6 +127,9 @@ struct context_info {
  1211.      long seer_turn;         /* when random clairvoyance will next kick in */
  1212.      long stethoscope_move;  /* when a stethoscope was last used */
  1213.      short stethoscope_movement; /* to track multiple moves on same turn */
  1214. +    long next_moloch_offering; /* Moloch demands regular sacrifices */
  1215. +    char inf_aligns; /* random alignment permutation number for Infidels */
  1216. +    boolean coward;  /* restrict Infidel Elbereth penalty to once per move */
  1217.      boolean travel;  /* find way automatically to u.tx,u.ty */
  1218.      boolean travel1; /* first travel step */
  1219.      boolean forcefight;
  1220. diff --git c/include/decl.h i/include/decl.h
  1221. index c131b3735..f560c936b 100644
  1222. --- c/include/decl.h
  1223. +++ i/include/decl.h
  1224. @@ -622,7 +622,7 @@ struct repo { /* repossession context */
  1225.  #define BP_ROLE 3
  1226.  #define NUM_BP 4
  1227.  
  1228. -#define NUM_ROLES (13)
  1229. +#define NUM_ROLES (14)
  1230.  struct role_filter {
  1231.      boolean roles[NUM_ROLES+1];
  1232.      short mask;
  1233. @@ -842,6 +842,7 @@ struct instance_globals {
  1234.      /* starting equipment gets auto-worn at beginning of new game,
  1235.         and we don't want stealth or displacement feedback then */
  1236.      boolean initial_don; /* manipulated in set_wear() */
  1237. +    struct obj *last_worn_armor; /* hides some messages in check_wings() */
  1238.  
  1239.      /* dog.c */
  1240.      int petname_used; /* user preferred pet name has been used */
  1241. @@ -1064,7 +1065,7 @@ struct instance_globals {
  1242.      /* values calculated when prayer starts, and used when completed */
  1243.      aligntyp p_aligntyp;
  1244.      int p_trouble;
  1245. -    int p_type; /* (-1)-3: (-1)=really naughty, 3=really good */
  1246. +    int p_type; /* (-3)-3: (-1)=really naughty, 3=really good */
  1247.  
  1248.      /* quest.c */
  1249.      struct q_score quest_status;
  1250. diff --git c/include/extern.h i/include/extern.h
  1251. index 3a7cdcf52..64a0a42a3 100644
  1252. --- c/include/extern.h
  1253. +++ i/include/extern.h
  1254. @@ -49,6 +49,7 @@ E boolean FDECL(snuff_candle, (struct obj *));
  1255.  E boolean FDECL(snuff_lit, (struct obj *));
  1256.  E boolean FDECL(catch_lit, (struct obj *));
  1257.  E void FDECL(use_unicorn_horn, (struct obj **));
  1258. +E void FDECL(use_figurine, (struct obj **));
  1259.  E boolean FDECL(tinnable, (struct obj *));
  1260.  E void NDECL(reset_trapset);
  1261.  E void FDECL(fig_transform, (ANY_P *, long));
  1262. @@ -71,6 +72,7 @@ E boolean FDECL(confers_luck, (struct obj *));
  1263.  E boolean FDECL(arti_reflects, (struct obj *));
  1264.  E boolean FDECL(shade_glare, (struct obj *));
  1265.  E boolean FDECL(restrict_name, (struct obj *, const char *));
  1266. +E boolean FDECL(attacks, (int, struct obj *));
  1267.  E boolean FDECL(defends, (int, struct obj *));
  1268.  E boolean FDECL(defends_when_carried, (int, struct obj *));
  1269.  E boolean FDECL(protects, (struct obj *, BOOLEAN_P));
  1270. @@ -500,6 +502,7 @@ E void NDECL(cancel_don);
  1271.  E int FDECL(stop_donning, (struct obj *));
  1272.  E int NDECL(Armor_off);
  1273.  E int NDECL(Armor_gone);
  1274. +E void FDECL(check_wings, (BOOLEAN_P));
  1275.  E int NDECL(Helmet_off);
  1276.  E int NDECL(Gloves_off);
  1277.  E int NDECL(Boots_on);
  1278. @@ -515,7 +518,7 @@ E void FDECL(Blindf_on, (struct obj *));
  1279.  E void FDECL(Blindf_off, (struct obj *));
  1280.  E int NDECL(dotakeoff);
  1281.  E int NDECL(doremring);
  1282. -E int FDECL(cursed, (struct obj *));
  1283. +E int FDECL(cursed, (struct obj *, BOOLEAN_P));
  1284.  E int FDECL(armoroff, (struct obj *));
  1285.  E int FDECL(canwearobj, (struct obj *, long *, BOOLEAN_P));
  1286.  E int NDECL(dowear);
  1287. @@ -1566,7 +1569,7 @@ E boolean FDECL(big_little_match, (int, int));
  1288.  E const char *FDECL(locomotion, (const struct permonst *, const char *));
  1289.  E const char *FDECL(stagger, (const struct permonst *, const char *));
  1290.  E const char *FDECL(on_fire, (struct permonst *, struct attack *));
  1291. -E const struct permonst *FDECL(raceptr, (struct monst *));
  1292. +E struct permonst *FDECL(raceptr, (struct monst *));
  1293.  E boolean FDECL(olfaction, (struct permonst *));
  1294.  
  1295.  /* ### monmove.c ### */
  1296. @@ -2091,6 +2094,8 @@ E boolean NDECL(stuck_in_wall);
  1297.  #ifdef USE_TRAMPOLI
  1298.  E int NDECL(prayer_done);
  1299.  #endif
  1300. +E void FDECL(god_zaps_you, (ALIGNTYP_P));
  1301. +E void FDECL(godvoice, (ALIGNTYP_P, const char *));
  1302.  E int NDECL(dosacrifice);
  1303.  E boolean FDECL(can_pray, (BOOLEAN_P));
  1304.  E int NDECL(dopray);
  1305. @@ -2102,6 +2107,7 @@ E const char *FDECL(a_gname_at, (XCHAR_P x, XCHAR_P y));
  1306.  E const char *FDECL(align_gname, (ALIGNTYP_P));
  1307.  E const char *FDECL(halu_gname, (ALIGNTYP_P));
  1308.  E const char *FDECL(align_gtitle, (ALIGNTYP_P));
  1309. +E aligntyp FDECL(inf_align, (int));
  1310.  E void FDECL(altar_wrath, (int, int));
  1311.  
  1312.  /* ### priest.c ### */
  1313. @@ -2250,6 +2256,7 @@ E int FDECL(rnz, (int));
  1314.  
  1315.  /* ### role.c ### */
  1316.  
  1317. +E int FDECL(special_alignment, (int, int));
  1318.  E boolean FDECL(validrole, (int));
  1319.  E boolean FDECL(validrace, (int, int));
  1320.  E boolean FDECL(validgend, (int, int, int));
  1321. diff --git c/include/mondata.h i/include/mondata.h
  1322. index abff12a2c..b8e96026a 100644
  1323. --- c/include/mondata.h
  1324. +++ i/include/mondata.h
  1325. @@ -32,6 +32,9 @@
  1326.  #define is_lminion(mon) \
  1327.      (is_minion((mon)->data) && mon_aligntyp(mon) == A_LAWFUL)
  1328.  #define is_flyer(ptr) (((ptr)->mflags1 & M1_FLY) != 0L)
  1329. +/* flight blocked by most body armor */
  1330. +#define big_wings(ptr) ((ptr) == &mons[PM_WINGED_GARGOYLE] \
  1331. +                        || (ptr) == &mons[PM_DEMON])
  1332.  #define is_floater(ptr) ((ptr)->mlet == S_EYE || (ptr)->mlet == S_LIGHT)
  1333.  /* clinger: piercers, mimics, wumpus -- generally don't fall down holes */
  1334.  #define is_clinger(ptr) (((ptr)->mflags1 & M1_CLING) != 0L)
  1335. @@ -99,6 +102,8 @@
  1336.  #define carnivorous(ptr) (((ptr)->mflags1 & M1_CARNIVORE) != 0L)
  1337.  #define herbivorous(ptr) (((ptr)->mflags1 & M1_HERBIVORE) != 0L)
  1338.  #define metallivorous(ptr) (((ptr)->mflags1 & M1_METALLIVORE) != 0L)
  1339. +#define inediate(ptr) (((ptr)->mflags1 & (M1_CARNIVORE | M1_HERBIVORE \
  1340. +                                          | M1_METALLIVORE)) == 0L)
  1341.  #define polyok(ptr) (((ptr)->mflags2 & M2_NOPOLY) == 0L)
  1342.  #define is_shapeshifter(ptr) (((ptr)->mflags2 & M2_SHAPESHIFTER) != 0L)
  1343.  #define is_undead(ptr) (((ptr)->mflags2 & M2_UNDEAD) != 0L)
  1344. diff --git c/include/monflag.h i/include/monflag.h
  1345. index b343791b0..f979aa4df 100644
  1346. --- c/include/monflag.h
  1347. +++ i/include/monflag.h
  1348. @@ -183,6 +183,7 @@ enum ms_sounds {
  1349.  #define MH_DWARF        M2_DWARF
  1350.  #define MH_GNOME        M2_GNOME
  1351.  #define MH_ORC          M2_ORC
  1352. +#define MH_DEMON        M2_DEMON
  1353.  
  1354.  /* for mons[].geno (constant during game) */
  1355.  #define G_UNIQ          0x1000 /* generated only once */
  1356. diff --git c/include/patchlevel.h i/include/patchlevel.h
  1357. index 24b92cf36..d332859bd 100644
  1358. --- c/include/patchlevel.h
  1359. +++ i/include/patchlevel.h
  1360. @@ -14,7 +14,7 @@
  1361.   * Incrementing EDITLEVEL can be used to force invalidation of old bones
  1362.   * and save files.
  1363.   */
  1364. -#define EDITLEVEL 20
  1365. +#define EDITLEVEL 21
  1366.  
  1367.  #define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2020"
  1368.  #define COPYRIGHT_BANNER_B \
  1369. diff --git c/include/you.h i/include/you.h
  1370. index 437500d9c..772d45899 100644
  1371. --- c/include/you.h
  1372. +++ i/include/you.h
  1373. @@ -48,9 +48,8 @@ struct u_event {
  1374.      Bitfield(uopened_dbridge, 1);   /* opened the drawbridge */
  1375.      Bitfield(invoked, 1);           /* invoked Gate to the Sanctum level */
  1376.      Bitfield(gehennom_entered, 1);  /* entered Gehennom via Valley */
  1377. -    Bitfield(uhand_of_elbereth, 2); /* became Hand of Elbereth */
  1378. +    Bitfield(uhand_of_elbereth, 3); /* became Hand of Elbereth */
  1379.      Bitfield(udemigod, 1);          /* killed the wiz */
  1380. -    Bitfield(uvibrated, 1);         /* stepped on "vibrating square" */
  1381.      Bitfield(ascended, 1);          /* has offered the Amulet */
  1382.  };
  1383.  
  1384. @@ -74,7 +73,7 @@ enum achivements {
  1385.      ACH_CNDL =  3, /* acquired Candelabrum of Invocation */
  1386.      ACH_BOOK =  4, /* acquired Book of the Dead */
  1387.      ACH_INVK =  5, /* performed invocation to gain access to Sanctum */
  1388. -    ACH_AMUL =  6, /* acquired The Amulet */
  1389. +    ACH_AMUL =  6, /* acquired (for Infidels: offered) The Amulet */
  1390.      ACH_ENDG =  7, /* entered end game */
  1391.      ACH_ASTR =  8, /* entered Astral Plane */
  1392.      ACH_UWIN =  9, /* ascended */
  1393. @@ -276,6 +275,7 @@ struct Race {
  1394.  };
  1395.  
  1396.  extern const struct Race races[]; /* Table of available races */
  1397. +extern struct Race race_demon;    /* used in pray.c */
  1398.  #define Race_if(X) (g.urace.malenum == (X))
  1399.  #define Race_switch (g.urace.malenum)
  1400.  
  1401. diff --git c/include/youprop.h i/include/youprop.h
  1402. index c7bce068c..cc878bffb 100644
  1403. --- c/include/youprop.h
  1404. +++ i/include/youprop.h
  1405. @@ -228,11 +228,13 @@
  1406.  #define HFlying u.uprops[FLYING].intrinsic
  1407.  #define EFlying u.uprops[FLYING].extrinsic
  1408.  /* BFlying has I_SPECIAL set if levitating or trapped in the floor or both,
  1409. -   FROMOUTSIDE set if inside solid rock (or in water on Plane of Water) */
  1410. +   FROMOUTSIDE set if inside solid rock (or in water on Plane of Water)
  1411. +   W_ARM set if in big_wings() form and wearing blocking body armor
  1412. +   (the last one obviously won't block the steed from flying) */
  1413.  #define BFlying u.uprops[FLYING].blocked
  1414. -#define Flying                                                      \
  1415. -    ((HFlying || EFlying || (u.usteed && is_flyer(u.usteed->data))) \
  1416. -     && !BFlying)
  1417. +#define Flying                                                           \
  1418. +    (((HFlying || EFlying) && !BFlying                                   \
  1419. +      || u.usteed && is_flyer(u.usteed->data)) && !(BFlying & ~W_ARMOR))
  1420.  /* May touch surface; does not override any others */
  1421.  
  1422.  #define EWwalking u.uprops[WWALKING].extrinsic
  1423. @@ -373,7 +375,7 @@
  1424.     redundant but allows the function calls to be skipped most of the time */
  1425.  #define Unaware (g.multi < 0 && (unconscious() || is_fainted()))
  1426.  
  1427. -#define Hate_silver (u.ulycn >= LOW_PM || hates_silver(g.youmonst.data))
  1428. +#define Hate_silver (u.ulycn >= LOW_PM || hates_silver(raceptr(&g.youmonst)))
  1429.  
  1430.  /* _Hitchhikers_Guide_to_the_Galaxy_ on uses for 'towel': "wrap it round
  1431.     your head to ward off noxious fumes" [we require it to be damp or wet] */
  1432. diff --git c/src/allmain.c i/src/allmain.c
  1433. index a609b4244..dc76d0bb1 100644
  1434. --- c/src/allmain.c
  1435. +++ i/src/allmain.c
  1436. @@ -233,7 +233,13 @@ boolean resuming;
  1437.                          && ((wtcap < MOD_ENCUMBER
  1438.                               && (!(g.moves % ((MAXULEV + 8 - u.ulevel)
  1439.                                              * (Role_if(PM_WIZARD) ? 3 : 4)
  1440. -                                            / 6)))) || Energy_regeneration)) {
  1441. +                                            / 6)))) || Energy_regeneration
  1442. +                    /* the Idol grants energy regen to piously unaligned;
  1443. +                     * it really shouldn't be restricted to Infidels,
  1444. +                     * but so far we have no other unaligned roles */
  1445. +                            || Role_if(PM_INFIDEL) && u.uhave.questart
  1446. +                               && u.ualign.type == A_NONE
  1447. +                               && u.ualign.record > rn2(20))) {
  1448.                          u.uen += rn1(
  1449.                              (int) (ACURR(A_WIS) + ACURR(A_INT)) / 15 + 1, 1);
  1450.                          if (u.uen > u.uenmax)
  1451. @@ -243,6 +249,48 @@ boolean resuming;
  1452.                              interrupt_multi("You feel full of energy.");
  1453.                      }
  1454.  
  1455. +                    /* Moloch demands regular sacrifices! */
  1456. +                    if (g.context.next_moloch_offering <= g.moves) {
  1457. +                        if (g.context.next_moloch_offering == g.moves
  1458. +                            && (u.ualign.type == A_NONE
  1459. +                                || u.ualignbase[A_CURRENT] == A_NONE)) {
  1460. +                            You_feel("%s urge to perform a sacrifice.",
  1461. +                                     u.ualign.type == A_NONE ? "an"
  1462. +                                                             : "a faint");
  1463. +                            stop_occupation();
  1464. +                        }
  1465. +                        if (u.ualign.type == A_NONE && !rn2(10)
  1466. +                            && rn2(g.moves - g.context.next_moloch_offering
  1467. +                                   + 1000) >= 1000) {
  1468. +                            if (u.ualign.record > -99)
  1469. +                                adjalign(-1);
  1470. +                            if (u.ualign.record < -10 && !rn2(u.ugangr + 1)
  1471. +                                && rn2(-u.ualign.record + 90) >= 100) {
  1472. +                                char *angry = (char *) 0;
  1473. +                                u.ugangr++;
  1474. +                                /* avoid repetitive messages */
  1475. +                                switch (u.ugangr) {
  1476. +                                /* same values as in cmd.c */
  1477. +                                case 1:
  1478. +                                    angry = "";
  1479. +                                    break;
  1480. +                                case 4:
  1481. +                                    angry = "very ";
  1482. +                                    break;
  1483. +                                case 7:
  1484. +                                    angry = "extremely ";
  1485. +                                    break;
  1486. +                                }
  1487. +                                if (angry) {
  1488. +                                    You_feel("that %s is %sangry at your "
  1489. +                                             "lack of offerings.", u_gname(),
  1490. +                                             angry);
  1491. +                                    stop_occupation();
  1492. +                                }
  1493. +                            }
  1494. +                        }
  1495. +                    }
  1496. +
  1497.                      if (!u.uinvulnerable) {
  1498.                          if (Teleportation && !rn2(85)) {
  1499.                              xchar old_ux = u.ux, old_uy = u.uy;
  1500. @@ -358,6 +406,7 @@ boolean resuming;
  1501.              /* when/if hero escapes from lava, he can't just stay there */
  1502.              else if (!u.umoved)
  1503.                  (void) pooleffects(FALSE);
  1504. +            g.context.coward = FALSE;
  1505.  
  1506.          } /* actual time passed */
  1507.  
  1508. @@ -608,6 +657,9 @@ newgame()
  1509.      g.context.next_attrib_check = 600L; /* arbitrary first setting */
  1510.      g.context.tribute.enabled = TRUE;   /* turn on 3.6 tributes    */
  1511.      g.context.tribute.tributesz = sizeof(struct tribute_info);
  1512. +    g.context.inf_aligns = rn2(6);      /* randomness for the Infidel role */
  1513. +    g.context.next_moloch_offering = 6000; /* give a grace period before
  1514. +                                            * the first sacrifice */
  1515.  
  1516.      for (i = LOW_PM; i < NUMMONS; i++)
  1517.          g.mvitals[i].mvflags = mons[i].geno & G_NOCORPSE;
  1518. @@ -648,7 +700,7 @@ newgame()
  1519.  
  1520.      if (flags.legacy) {
  1521.          flush_screen(1);
  1522. -        com_pager("legacy");
  1523. +        qt_pager("legacy");
  1524.      }
  1525.  
  1526.      urealtime.realtime = 0L;
  1527. diff --git c/src/apply.c i/src/apply.c
  1528. index 856b54ee5..4b81fa7ee 100644
  1529. --- c/src/apply.c
  1530. +++ i/src/apply.c
  1531. @@ -20,7 +20,6 @@ static void FDECL(use_lamp, (struct obj *));
  1532.  static void FDECL(light_cocktail, (struct obj **));
  1533.  static void FDECL(display_jump_positions, (int));
  1534.  static void FDECL(use_tinning_kit, (struct obj *));
  1535. -static void FDECL(use_figurine, (struct obj **));
  1536.  static void FDECL(use_grease, (struct obj *));
  1537.  static void FDECL(use_trap, (struct obj *));
  1538.  static void FDECL(use_stone, (struct obj *));
  1539. @@ -2089,6 +2088,7 @@ long timeout;
  1540.      boolean cansee_spot, silent, okay_spot;
  1541.      boolean redraw = FALSE;
  1542.      boolean suppress_see = FALSE;
  1543. +    boolean idol = figurine && figurine->oartifact == ART_IDOL_OF_MOLOCH;
  1544.      char monnambuf[BUFSZ], carriedby[BUFSZ];
  1545.  
  1546.      if (!figurine) {
  1547. @@ -2099,7 +2099,8 @@ long timeout;
  1548.      okay_spot = get_obj_location(figurine, &cc.x, &cc.y, 0);
  1549.      if (figurine->where == OBJ_INVENT || figurine->where == OBJ_MINVENT)
  1550.          okay_spot = enexto(&cc, cc.x, cc.y, &mons[figurine->corpsenm]);
  1551. -    if (!okay_spot || !figurine_location_checks(figurine, &cc, TRUE)) {
  1552. +    if (idol && figurine->age > timeout || !okay_spot
  1553. +        || !figurine_location_checks(figurine, &cc, TRUE)) {
  1554.          /* reset the timer to try again later */
  1555.          (void) start_timer((long) rnd(5000), TIMER_OBJECT, FIG_TRANSFORM,
  1556.                             obj_to_any(figurine));
  1557. @@ -2143,9 +2144,14 @@ long timeout;
  1558.  
  1559.          case OBJ_FLOOR:
  1560.              if (cansee_spot && !silent) {
  1561. -                if (suppress_see)
  1562. +                if (idol) {
  1563. +                    if (!suppress_see)
  1564. +                        You_see("a cloud of %s mist coagulate "
  1565. +                                "into the shape of %s%s!",
  1566. +                                hcolor("crimson"), monnambuf, and_vanish);
  1567. +                } else if (suppress_see) {
  1568.                      pline("%s suddenly vanishes!", an(xname(figurine)));
  1569. -                else
  1570. +                }  else
  1571.                      You_see("a figurine transform into %s%s!", monnambuf,
  1572.                              and_vanish);
  1573.                  redraw = TRUE; /* update figurine's map location */
  1574. @@ -2181,12 +2187,20 @@ long timeout;
  1575.              break;
  1576.          }
  1577.      }
  1578. -    /* free figurine now */
  1579. -    if (carried(figurine)) {
  1580. -        useup(figurine);
  1581. +    if (idol) {
  1582. +        long cooldown = rnz(100);
  1583. +        figurine->age = timeout + cooldown;
  1584. +        /* still cursed */
  1585. +        (void) start_timer((long) rnd(9000) + cooldown, TIMER_OBJECT,
  1586. +                           FIG_TRANSFORM, obj_to_any(figurine));
  1587.      } else {
  1588. -        obj_extract_self(figurine);
  1589. -        obfree(figurine, (struct obj *) 0);
  1590. +        /* free figurine now */
  1591. +        if (carried(figurine)) {
  1592. +            useup(figurine);
  1593. +        } else {
  1594. +            obj_extract_self(figurine);
  1595. +            obfree(figurine, (struct obj *) 0);
  1596. +        }
  1597.      }
  1598.      if (redraw)
  1599.          newsym(cc.x, cc.y);
  1600. @@ -2228,14 +2242,25 @@ boolean quietly;
  1601.      return TRUE;
  1602.  }
  1603.  
  1604. -static void
  1605. +void
  1606.  use_figurine(optr)
  1607.  struct obj **optr;
  1608.  {
  1609.      register struct obj *obj = *optr;
  1610. +    boolean idol = obj->oartifact == ART_IDOL_OF_MOLOCH;
  1611.      xchar x, y;
  1612.      coord cc;
  1613. +    char *release_figurine;
  1614.  
  1615. +    if (idol) {
  1616. +        /* copied from artifact.c */
  1617. +        if (obj->age > g.monstermoves) {
  1618. +            You_feel("that %s %s ignoring you.", the(xname(obj)),
  1619. +                     otense(obj, "are"));
  1620. +            obj->age += (long) d(3, 10);
  1621. +            return;
  1622. +        }
  1623. +    }
  1624.      if (u.uswallow) {
  1625.          /* can't activate a figurine while swallowed */
  1626.          if (!figurine_location_checks(obj, (coord *) 0, FALSE))
  1627. @@ -2252,17 +2277,34 @@ struct obj **optr;
  1628.      /* Passing FALSE arg here will result in messages displayed */
  1629.      if (!figurine_location_checks(obj, &cc, FALSE))
  1630.          return;
  1631. -    You("%s and it %stransforms.",
  1632. -        (u.dx || u.dy) ? "set the figurine beside you"
  1633. -                       : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
  1634. -                          || is_pool(cc.x, cc.y))
  1635. -                             ? "release the figurine"
  1636. -                             : (u.dz < 0 ? "toss the figurine into the air"
  1637. -                                         : "set the figurine on the ground"),
  1638. -        Blind ? "supposedly " : "");
  1639. +    if (u.dx || u.dy)
  1640. +        release_figurine = "set the figurine beside you";
  1641. +    else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
  1642. +             || is_pool(cc.x, cc.y))
  1643. +        release_figurine = "release the figurine";
  1644. +    else if (u.dz < 0)
  1645. +        release_figurine = "toss the figurine into the air";
  1646. +    else
  1647. +        release_figurine = "set the figurine on the ground";
  1648. +    if (idol) {
  1649. +        if (Blind)
  1650. +            You("%s and feel an unholy aura emanate from it.",
  1651. +                release_figurine);
  1652. +        else
  1653. +            You("%s and a cloud of %s mist arises from it.",
  1654. +                release_figurine, hcolor("crimson"));
  1655. +    } else
  1656. +        You("%s and it %stransforms.", release_figurine,
  1657. +            Blind ? "supposedly " : "");
  1658.      (void) make_familiar(obj, cc.x, cc.y, FALSE);
  1659. -    (void) stop_timer(FIG_TRANSFORM, obj_to_any(obj));
  1660. -    useup(obj);
  1661. +    if (idol) {
  1662. +        obj->age = g.monstermoves + rnz(100);
  1663. +        freeinv(obj);
  1664. +        place_object(obj, cc.x, cc.y);
  1665. +    } else {
  1666. +        (void) stop_timer(FIG_TRANSFORM, obj_to_any(obj));
  1667. +        useup(obj);
  1668. +    }
  1669.      if (Blind)
  1670.          map_invisible(cc.x, cc.y);
  1671.      *optr = 0;
  1672. @@ -3649,7 +3691,7 @@ doapply()
  1673.      case BLINDFOLD:
  1674.      case LENSES:
  1675.          if (obj == ublindf) {
  1676. -            if (!cursed(obj))
  1677. +            if (!cursed(obj, FALSE))
  1678.                  Blindf_off(obj);
  1679.          } else if (!ublindf) {
  1680.              Blindf_on(obj);
  1681. diff --git c/src/artifact.c i/src/artifact.c
  1682. index 77eced018..52d83aa58 100644
  1683. --- c/src/artifact.c
  1684. +++ i/src/artifact.c
  1685. @@ -40,7 +40,7 @@ static int FDECL(count_surround_traps, (int, int));
  1686.  #define FATAL_DAMAGE_MODIFIER 200
  1687.  
  1688.  static void NDECL(hack_artifacts);
  1689. -static boolean FDECL(attacks, (int, struct obj *));
  1690. +static void FDECL(fix_artifact, (struct obj *));
  1691.  
  1692.  /* handle some special cases; must be called after u_init() */
  1693.  static void
  1694. @@ -96,6 +96,19 @@ NHFILE *nhfp;
  1695.      hack_artifacts();  /* redo non-saved special cases */
  1696.  }
  1697.  
  1698. +/* Some artifacts may need additional tweaking when created.
  1699. + * Called when the artifact is christened.
  1700. + */
  1701. +static void
  1702. +fix_artifact(otmp)
  1703. +struct obj *otmp;
  1704. +{
  1705. +    if (otmp->oartifact == ART_IDOL_OF_MOLOCH) {
  1706. +        set_corpsenm(otmp, PM_HORNED_DEVIL);
  1707. +        otmp->spe = 0;
  1708. +    }
  1709. +}
  1710. +
  1711.  const char *
  1712.  artiname(artinum)
  1713.  int artinum;
  1714. @@ -123,8 +136,8 @@ aligntyp alignment; /* target alignment, or A_NONE */
  1715.  {
  1716.      const struct artifact *a;
  1717.      int m, n, altn;
  1718. -    boolean by_align = (alignment != A_NONE);
  1719. -    short o_typ = (by_align || !otmp) ? 0 : otmp->otyp;
  1720. +    boolean by_align = alignment != A_NONE || !otmp;
  1721. +    short o_typ = by_align ? 0 : otmp->otyp;
  1722.      boolean unique = !by_align && otmp && objects[o_typ].oc_unique;
  1723.      short eligible[NROFARTIFACTS];
  1724.  
  1725. @@ -193,6 +206,7 @@ aligntyp alignment; /* target alignment, or A_NONE */
  1726.              otmp = oname(otmp, a->name);
  1727.              otmp->oartifact = m;
  1728.              g.artiexist[m] = TRUE;
  1729. +            fix_artifact(otmp);
  1730.          }
  1731.      } else {
  1732.          /* nothing appropriate could be found; return original object */
  1733. @@ -265,6 +279,8 @@ boolean mod;
  1734.                  if (otmp->otyp == RIN_INCREASE_DAMAGE)
  1735.                      otmp->spe = 0;
  1736.                  g.artiexist[m] = mod;
  1737. +                if (mod)
  1738. +                    fix_artifact(otmp);
  1739.                  break;
  1740.              }
  1741.      return;
  1742. @@ -398,7 +414,7 @@ const char *name;
  1743.      return FALSE;
  1744.  }
  1745.  
  1746. -static boolean
  1747. +boolean
  1748.  attacks(adtyp, otmp)
  1749.  int adtyp;
  1750.  struct obj *otmp;
  1751. @@ -793,6 +809,8 @@ struct monst *mtmp;
  1752.              return !(yours ? Poison_resistance : resists_poison(mtmp));
  1753.          case AD_DRLI:
  1754.              return !(yours ? Drain_resistance : resists_drli(mtmp));
  1755. +        case AD_DREN:
  1756. +            return !nonliving(ptr);
  1757.          case AD_STON:
  1758.              return !(yours ? Stone_resistance : resists_ston(mtmp));
  1759.          default:
  1760. @@ -1605,6 +1623,88 @@ struct obj *obj;
  1761.              nhUse(otmp);
  1762.              break;
  1763.          }
  1764. +        case CHANNEL:
  1765. +            /* Should this break atheist conduct?  Currently it doesn't,
  1766. +             * under the excuse of being necessary to ascend.
  1767. +             * But still, we're channeling a god's power here... */
  1768. +            if (IS_ALTAR(levl[u.ux][u.uy].typ)) {
  1769. +                aligntyp altar_align = Amask2align(levl[u.ux][u.uy].altarmask
  1770. +                                                   & AM_MASK);
  1771. +                boolean high_altar = (Is_astralevel(&u.uz)
  1772. +                                      || Is_sanctum(&u.uz))
  1773. +                                     && (levl[u.ux][u.uy].altarmask
  1774. +                                         & AM_SHRINE);
  1775. +                if (!Blind)
  1776. +                    pline("Tendrils of %s mist seep out of %s "
  1777. +                          "and into the altar below...",
  1778. +                          hcolor("crimson"), the(xname(obj)));
  1779. +                else
  1780. +                    You_feel("something flow from %s.", the(xname(obj)));
  1781. +                if (altar_align == A_NONE) {
  1782. +                    if (high_altar && Role_if(PM_INFIDEL)
  1783. +                        && u.uevent.ascended && !obj->spe) {
  1784. +                        godvoice(A_NONE, (char *) 0);
  1785. +                        qt_pager("moloch");
  1786. +                        You_feel("strange energies envelop %s.",
  1787. +                                 the(xname(obj)));
  1788. +                        obj->spe = 1;
  1789. +                        u.uhave.amulet = 1;
  1790. +                        break;
  1791. +                    }
  1792. +                    if (!Blind)
  1793. +                        pline_The("altar glows for a moment.");
  1794. +                    /* nothing happens */
  1795. +                    break;
  1796. +                }
  1797. +                if (high_altar) {
  1798. +                    /* messages yoinked from pray.c */
  1799. +                    You("sense a conflict between %s and %s.",
  1800. +                        align_gname(A_NONE), a_gname());
  1801. +                    if (obj->spe && altar_align == inf_align(1)) {
  1802. +                        You_feel("the power of %s increase.",
  1803. +                                 align_gname(A_NONE));
  1804. +                    } else {
  1805. +                        pline("%s feel the power of %s decrease.",
  1806. +                              u.ualign.type == A_NONE ? "Unluckily, you"
  1807. +                                                      : "You",
  1808. +                              align_gname(A_NONE));
  1809. +                        godvoice(altar_align, "So, mortal!  You dare "
  1810. +                                              "desecrate my High Temple!");
  1811. +                        god_zaps_you(altar_align);
  1812. +                        break;
  1813. +                    }
  1814. +                }
  1815. +                levl[u.ux][u.uy].altarmask &= AM_SHRINE;
  1816. +                levl[u.ux][u.uy].altarmask |= AM_NONE;
  1817. +                if (!Blind)
  1818. +                    pline_The("altar glows %s.", hcolor(NH_RED));
  1819. +                if (!high_altar) {
  1820. +                    /* the Idol does all the work for you,
  1821. +                     * so you don't get a luck increase;
  1822. +                     * but you don't get a hostile minion, either */
  1823. +                    struct monst *pri = findpriest(temple_occupied(u.urooms));
  1824. +                    if (pri && mon_aligntyp(pri) != A_NONE)
  1825. +                        angry_priest();
  1826. +                } else {
  1827. +                    /* At this point, the player must be an Infidel.
  1828. +                     * Should we still check for opposite alignment?
  1829. +                     * Currently, Moloch doesn't care. */
  1830. +                    adjalign(10);
  1831. +                    pline1("A sinister laughter echoes through the temple, "
  1832. +                           "and you're bathed in darkness...");
  1833. +                    godvoice(A_NONE, "My pawn, thou hast done well!");
  1834. +                    display_nhwindow(WIN_MESSAGE, FALSE);
  1835. +                    verbalize("In return for thy service, "
  1836. +                              "I grant thee a part of My domain!");
  1837. +                    You("ascend to the status of Demon %s...",
  1838. +                        flags.female ? "Lady" : "Lord");
  1839. +                    done(ASCENDED);
  1840. +                }
  1841. +            } else {
  1842. +                obj->age = 0; /* will be set below */
  1843. +                use_figurine(&obj);
  1844. +            }
  1845. +            break;
  1846.          }
  1847.      } else {
  1848.          long eprop = (u.uprops[oart->inv_prop].extrinsic ^= W_ARTI),
  1849. diff --git c/src/attrib.c i/src/attrib.c
  1850. index eb069a1f0..984492db9 100644
  1851. --- c/src/attrib.c
  1852. +++ i/src/attrib.c
  1853. @@ -41,6 +41,11 @@ static const struct innate {
  1854.                   { 15, &(HWarning), "sensitive", "" },
  1855.                   { 0, 0, 0, 0 } },
  1856.  
  1857. +  inf_abil[] = { { 1, &(HFire_resistance), "", "" },
  1858. +                 { 15, &(HWarning), "sensitive", "" },
  1859. +                 { 20, &(HShock_resistance), "inured", "softened" },
  1860. +                 { 0, 0, 0, 0 } },
  1861. +
  1862.    kni_abil[] = { { 7, &(HFast), "quick", "slow" }, { 0, 0, 0, 0 } },
  1863.  
  1864.    mon_abil[] = { { 1, &(HFast), "", "" },
  1865. @@ -101,6 +106,15 @@ static const struct innate {
  1866.                   { 1, &HPoison_resistance, "", "" },
  1867.                   { 0, 0, 0, 0 } },
  1868.  
  1869. +  dem_abil[] = { { 1, &HInfravision, "", "" },
  1870. +                 { 1, &HFire_resistance, "", "" },
  1871. +                 { 1, &HPoison_resistance, "", "" },
  1872. +                 { 1, &HDrain_resistance, "", "" },
  1873. +                 { 1, &HSee_invisible, "", "" },
  1874. +                 { 1, &HFlying, "", "" },
  1875. +                 /* also inediate */
  1876. +                 { 0, 0, 0, 0 } },
  1877. +
  1878.    hum_abil[] = { { 0, 0, 0, 0 } };
  1879.  
  1880.  static void NDECL(exerper);
  1881. @@ -711,6 +725,7 @@ int r;
  1882.          { PM_BARBARIAN, bar_abil },
  1883.          { PM_CAVEMAN, cav_abil },
  1884.          { PM_HEALER, hea_abil },
  1885. +        { PM_INFIDEL, inf_abil },
  1886.          { PM_KNIGHT, kni_abil },
  1887.          { PM_MONK, mon_abil },
  1888.          { PM_PRIEST, pri_abil },
  1889. @@ -752,6 +767,9 @@ long frommask;
  1890.          case PM_ORC:
  1891.              abil = orc_abil;
  1892.              break;
  1893. +        case PM_DEMON:
  1894. +            abil = dem_abil;
  1895. +            break;
  1896.          case PM_HUMAN:
  1897.              abil = hum_abil;
  1898.              break;
  1899. @@ -805,6 +823,8 @@ int propidx;
  1900.          return FROM_LYCN;
  1901.      if (propidx == FAST && Very_fast)
  1902.          return FROM_NONE; /* can't become very fast innately */
  1903. +    if (propidx == FLYING && (BFlying & W_ARMOR))
  1904. +        return FROM_NONE; /* not from form, as that is blocked */
  1905.      if ((innateness = innately(&u.uprops[propidx].intrinsic)) != FROM_NONE)
  1906.          return innateness;
  1907.      if (propidx == JUMPING && Role_if(PM_KNIGHT)
  1908. diff --git c/src/botl.c i/src/botl.c
  1909. index 2dfaa11b9..cc0cdd448 100644
  1910. --- c/src/botl.c
  1911. +++ i/src/botl.c
  1912. @@ -89,9 +89,10 @@ do_statusline1()
  1913.              ACURR(A_DEX), ACURR(A_CON), ACURR(A_INT), ACURR(A_WIS),
  1914.              ACURR(A_CHA));
  1915.      Sprintf(nb = eos(nb),
  1916. -            (u.ualign.type == A_CHAOTIC)
  1917. -                ? "  Chaotic"
  1918. -                : (u.ualign.type == A_NEUTRAL) ? "  Neutral" : "  Lawful");
  1919. +            (u.ualign.type == A_NONE) ? "  Unaligned"
  1920. +                : (u.ualign.type == A_CHAOTIC) ? "  Chaotic"
  1921. +                    : (u.ualign.type == A_NEUTRAL) ? "  Neutral"
  1922. +                        : "  Lawful");
  1923.  #ifdef SCORE_ON_BOTL
  1924.      if (flags.showscore)
  1925.          Sprintf(nb = eos(nb), " S:%ld", botl_score());
  1926. @@ -748,11 +749,13 @@ bot_via_windowport()
  1927.      g.blstats[idx][BL_CH].a.a_int = ACURR(A_CHA);
  1928.  
  1929.      /* Alignment */
  1930. -    Strcpy(g.blstats[idx][BL_ALIGN].val, (u.ualign.type == A_CHAOTIC)
  1931. -                                          ? "Chaotic"
  1932. -                                          : (u.ualign.type == A_NEUTRAL)
  1933. -                                               ? "Neutral"
  1934. -                                               : "Lawful");
  1935. +    Strcpy(g.blstats[idx][BL_ALIGN].val, (u.ualign.type == A_NONE)
  1936. +                                             ? "Unaligned"
  1937. +                                             : (u.ualign.type == A_CHAOTIC)
  1938. +                                                 ? "Chaotic"
  1939. +                                                 : (u.ualign.type == A_LAWFUL)
  1940. +                                                     ? "Lawful"
  1941. +                                                     : "Neutral");
  1942.  
  1943.      /* Score */
  1944.      g.blstats[idx][BL_SCORE].a.a_long =
  1945. diff --git c/src/decl.c i/src/decl.c
  1946. index 3264d7282..7e7a18801 100644
  1947. --- c/src/decl.c
  1948. +++ i/src/decl.c
  1949. @@ -383,6 +383,7 @@ const struct instance_globals g_init = {
  1950.  
  1951.      /* do_wear.c */
  1952.      FALSE, /* initial_don */
  1953. +    NULL, /* last_worn_armor */
  1954.  
  1955.      /* dog.c */
  1956.      0,  /* petname_used */
  1957. diff --git c/src/do.c i/src/do.c
  1958. index 9bbf997f2..569c72c8c 100644
  1959. --- c/src/do.c
  1960. +++ i/src/do.c
  1961. @@ -570,7 +570,7 @@ const char *word;
  1962.              Norep("You cannot %s %s you are wearing.", word, something);
  1963.          return FALSE;
  1964.      }
  1965. -    if (obj->otyp == LOADSTONE && obj->cursed) {
  1966. +    if (obj->otyp == LOADSTONE && cursed(obj, TRUE)) {
  1967.          /* getobj() kludge sets corpsenm to user's specified count
  1968.             when refusing to split a stack of cursed loadstones */
  1969.          if (*word) {
  1970. @@ -925,7 +925,8 @@ int retry;
  1971.                  if (cnt < otmp->quan) {
  1972.                      if (welded(otmp)) {
  1973.                          ; /* don't split */
  1974. -                    } else if (otmp->otyp == LOADSTONE && otmp->cursed) {
  1975. +                    } else if (otmp->otyp == LOADSTONE
  1976. +                               && cursed(otmp, TRUE)) {
  1977.                          /* same kludge as getobj(), for canletgo()'s use */
  1978.                          otmp->corpsenm = (int) cnt; /* don't split */
  1979.                      } else {
  1980. @@ -1312,6 +1313,8 @@ boolean at_stairs, falling, portal;
  1981.       *   -2    5.21   4.17   0.0
  1982.       *   -3    2.08   0.0    0.0
  1983.       *
  1984. +     *   Infidels (unaligned) are spared from the mysterious force.
  1985. +     *
  1986.       * 3.7.0: the chance for the "mysterious force" to kick in goes down
  1987.       * as it kicks in, starting at 25% per climb attempt and dropping off
  1988.       * gradually but substantially.  The drop off is greater when hero is
  1989. @@ -1319,7 +1322,7 @@ boolean at_stairs, falling, portal;
  1990.       */
  1991.      if (Inhell && up && u.uhave.amulet && !newdungeon && !portal
  1992.          && (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz) - 3)) {
  1993. -        if (!rn2(4 + g.context.mysteryforce)) {
  1994. +        if (u.ualign.type != A_NONE && !rn2(4 + g.context.mysteryforce)) {
  1995.              int odds = 3 + (int) u.ualign.type,   /* 2..4 */
  1996.                  diff = (odds <= 1) ? 0 : rn2(odds); /* paranoia */
  1997.  
  1998. @@ -1791,7 +1794,8 @@ final_level()
  1999.      create_mplayers(rn1(4, 3), TRUE);
  2000.  
  2001.      /* create a guardian angel next to player, if worthy */
  2002. -    gain_guardian_angel();
  2003. +    if (u.ualign.type != A_NONE)
  2004. +        gain_guardian_angel();
  2005.  }
  2006.  
  2007.  /* change levels at the end of this turn, after monsters finish moving */
  2008. diff --git c/src/do_wear.c i/src/do_wear.c
  2009. index 0aebf7ffb..95647786a 100644
  2010. --- c/src/do_wear.c
  2011. +++ i/src/do_wear.c
  2012. @@ -411,7 +411,7 @@ Helmet_on(VOID_ARGS)
  2013.             by hero falling onto a polymorph trap or into water (emergency
  2014.             disrobe) or maybe lava (probably not, helm isn't 'organic') */
  2015.          uchangealign((u.ualign.type != A_NEUTRAL)
  2016. -                         ? -u.ualign.type
  2017. +                         ? -sgn(u.ualign.type)
  2018.                           : (uarmh->o_id % 2) ? A_CHAOTIC : A_LAWFUL,
  2019.                       1);
  2020.          /* makeknown(HELM_OF_OPPOSITE_ALIGNMENT); -- below, after Tobjnam() */
  2021. @@ -695,6 +695,7 @@ Armor_on(VOID_ARGS)
  2022.       */
  2023.      if (uarm) /* no known instances of !uarm here but play it safe */
  2024.          uarm->known = 1; /* suit's +/- evident because of status line AC */
  2025. +    check_wings(FALSE);
  2026.      return 0;
  2027.  }
  2028.  
  2029. @@ -704,6 +705,7 @@ Armor_off(VOID_ARGS)
  2030.      g.context.takeoff.mask &= ~W_ARM;
  2031.      setworn((struct obj *) 0, W_ARM);
  2032.      g.context.takeoff.cancelled_don = FALSE;
  2033. +    check_wings(FALSE);
  2034.      return 0;
  2035.  }
  2036.  
  2037. @@ -719,9 +721,43 @@ Armor_gone()
  2038.      g.context.takeoff.mask &= ~W_ARM;
  2039.      setnotworn(uarm);
  2040.      g.context.takeoff.cancelled_don = FALSE;
  2041. +    check_wings(FALSE);
  2042.      return 0;
  2043.  }
  2044.  
  2045. +/* Some monster forms' flight is blocked by most body armor. */
  2046. +void
  2047. +check_wings(silent)
  2048. +boolean silent; /* we assume a wardrobe change if false */
  2049. +{
  2050. +    boolean old_flying = Flying;
  2051. +
  2052. +    BFlying &= ~W_ARM;
  2053. +    if (!big_wings(raceptr(&g.youmonst)))
  2054. +        return;
  2055. +
  2056. +    if (!uarm) {
  2057. +        if (!silent && Flying && !old_flying)
  2058. +            You("spread your wings and take flight.");
  2059. +    } else if (Is_dragon_scales(uarm)) {
  2060. +        if (!silent && uarm != g.last_worn_armor)
  2061. +            You("arrange the scales around your wings.");
  2062. +    } else if (uarm->otyp == LEATHER_JACKET) {
  2063. +        if (!silent && uarm != g.last_worn_armor)
  2064. +            pline1("This jacket seems to have holes for wings.");
  2065. +    } else {
  2066. +        BFlying |= W_ARM;
  2067. +        if (!silent)
  2068. +            You("fold your wings under your suit.");
  2069. +    }
  2070. +
  2071. +    if (uarm)
  2072. +        g.last_worn_armor = uarm;
  2073. +
  2074. +    if (Flying != old_flying)
  2075. +        g.context.botl = TRUE;
  2076. +}
  2077. +
  2078.  static void
  2079.  Amulet_on()
  2080.  {
  2081. @@ -1593,31 +1629,35 @@ doremring()
  2082.  
  2083.  /* Check if something worn is cursed _and_ unremovable. */
  2084.  int
  2085. -cursed(otmp)
  2086. +cursed(otmp, silent)
  2087.  struct obj *otmp;
  2088. +boolean silent;
  2089.  {
  2090.      if (!otmp) {
  2091.          impossible("cursed without otmp");
  2092.          return 0;
  2093.      }
  2094. -    /* Curses, like chickens, come home to roost. */
  2095. -    if ((otmp == uwep) ? welded(otmp) : (int) otmp->cursed) {
  2096. -        boolean use_plural = (is_boots(otmp) || is_gloves(otmp)
  2097. -                              || otmp->otyp == LENSES || otmp->quan > 1L);
  2098. -
  2099. -        /* might be trying again after applying grease to hands */
  2100. -        if (Glib && otmp->bknown
  2101. -            /* for weapon, we'll only get here via 'A )' */
  2102. -            && (uarmg ? (otmp == uwep)
  2103. -                      : ((otmp->owornmask & (W_WEP | W_RING)) != 0)))
  2104. -            pline("Despite your slippery %s, you can't.",
  2105. -                  fingers_or_gloves(TRUE));
  2106. -        else
  2107. -            You("can't.  %s cursed.", use_plural ? "They are" : "It is");
  2108. -        set_bknown(otmp, 1);
  2109. +    /* Inf are immune to curses. */
  2110. +    if (Role_if(PM_INFIDEL) || !otmp->cursed || otmp == uwep && !welded(otmp))
  2111. +        return 0;
  2112. +    if (silent)
  2113.          return 1;
  2114. -    }
  2115. -    return 0;
  2116. +
  2117. +    /* Curses, like chickens, come home to roost. */
  2118. +    boolean use_plural = (is_boots(otmp) || is_gloves(otmp)
  2119. +                          || otmp->otyp == LENSES || otmp->quan > 1L);
  2120. +
  2121. +    /* might be trying again after applying grease to hands */
  2122. +    if (Glib && otmp->bknown
  2123. +        /* for weapon, we'll only get here via 'A )' */
  2124. +        && (uarmg ? (otmp == uwep)
  2125. +            : ((otmp->owornmask & (W_WEP | W_RING)) != 0)))
  2126. +        pline("Despite your slippery %s, you can't.",
  2127. +              fingers_or_gloves(TRUE));
  2128. +    else
  2129. +        You("can't.  %s cursed.", use_plural ? "They are" : "It is");
  2130. +    set_bknown(otmp, 1);
  2131. +    return 1;
  2132.  }
  2133.  
  2134.  int
  2135. @@ -1628,7 +1668,7 @@ struct obj *otmp;
  2136.      int delay = -objects[otmp->otyp].oc_delay;
  2137.      const char *what = 0;
  2138.  
  2139. -    if (cursed(otmp))
  2140. +    if (cursed(otmp, FALSE))
  2141.          return 0;
  2142.      /* this used to make assumptions about which types of armor had
  2143.         delays and which didn't; now both are handled for all types */
  2144. @@ -2349,13 +2389,13 @@ int otyp;
  2145.          /* reasons ring can't be removed match those checked by select_off();
  2146.             limbless case has extra checks because ordinarily it's temporary */
  2147.          if (nolimbs(g.youmonst.data) && uamul
  2148. -            && uamul->otyp == AMULET_OF_UNCHANGING && uamul->cursed)
  2149. +            && uamul->otyp == AMULET_OF_UNCHANGING && cursed(uamul, TRUE))
  2150.              return uamul;
  2151.          if (welded(uwep) && (ring == uright || bimanual(uwep)))
  2152.              return uwep;
  2153. -        if (uarmg && uarmg->cursed)
  2154. +        if (uarmg && cursed(uarmg, TRUE))
  2155.              return uarmg;
  2156. -        if (ring->cursed)
  2157. +        if (cursed(ring, TRUE))
  2158.              return ring;
  2159.          /* normally outermost layer is processed first, but slippery gloves
  2160.             wears off quickly so uncurse ring itself before handling those */
  2161. @@ -2464,7 +2504,7 @@ register struct obj *otmp;
  2162.          ; /* some items can be removed even when cursed */
  2163.      } else {
  2164.          /* otherwise, this is fundamental */
  2165. -        if (cursed(otmp))
  2166. +        if (cursed(otmp, FALSE))
  2167.              return 0;
  2168.      }
  2169.  
  2170. @@ -2512,7 +2552,7 @@ do_takeoff()
  2171.  
  2172.      g.context.takeoff.mask |= I_SPECIAL; /* set flag for cancel_doff() */
  2173.      if (doff->what == W_WEP) {
  2174. -        if (!cursed(uwep)) {
  2175. +        if (!cursed(uwep, FALSE)) {
  2176.              setuwep((struct obj *) 0);
  2177.              if (was_twoweap)
  2178.                  You("are no longer wielding either weapon.");
  2179. @@ -2529,46 +2569,46 @@ do_takeoff()
  2180.          You("no longer have ammunition readied.");
  2181.      } else if (doff->what == WORN_ARMOR) {
  2182.          otmp = uarm;
  2183. -        if (!cursed(otmp))
  2184. +        if (!cursed(otmp, FALSE))
  2185.              (void) Armor_off();
  2186.      } else if (doff->what == WORN_CLOAK) {
  2187.          otmp = uarmc;
  2188. -        if (!cursed(otmp))
  2189. +        if (!cursed(otmp, FALSE))
  2190.              (void) Cloak_off();
  2191.      } else if (doff->what == WORN_BOOTS) {
  2192.          otmp = uarmf;
  2193. -        if (!cursed(otmp))
  2194. +        if (!cursed(otmp, FALSE))
  2195.              (void) Boots_off();
  2196.      } else if (doff->what == WORN_GLOVES) {
  2197.          otmp = uarmg;
  2198. -        if (!cursed(otmp))
  2199. +        if (!cursed(otmp, FALSE))
  2200.              (void) Gloves_off();
  2201.      } else if (doff->what == WORN_HELMET) {
  2202.          otmp = uarmh;
  2203. -        if (!cursed(otmp))
  2204. +        if (!cursed(otmp, FALSE))
  2205.              (void) Helmet_off();
  2206.      } else if (doff->what == WORN_SHIELD) {
  2207.          otmp = uarms;
  2208. -        if (!cursed(otmp))
  2209. +        if (!cursed(otmp, FALSE))
  2210.              (void) Shield_off();
  2211.      } else if (doff->what == WORN_SHIRT) {
  2212.          otmp = uarmu;
  2213. -        if (!cursed(otmp))
  2214. +        if (!cursed(otmp, FALSE))
  2215.              (void) Shirt_off();
  2216.      } else if (doff->what == WORN_AMUL) {
  2217.          otmp = uamul;
  2218. -        if (!cursed(otmp))
  2219. +        if (!cursed(otmp, FALSE))
  2220.              Amulet_off();
  2221.      } else if (doff->what == LEFT_RING) {
  2222.          otmp = uleft;
  2223. -        if (!cursed(otmp))
  2224. +        if (!cursed(otmp, FALSE))
  2225.              Ring_off(uleft);
  2226.      } else if (doff->what == RIGHT_RING) {
  2227.          otmp = uright;
  2228. -        if (!cursed(otmp))
  2229. +        if (!cursed(otmp, FALSE))
  2230.              Ring_off(uright);
  2231.      } else if (doff->what == WORN_BLINDF) {
  2232. -        if (!cursed(ublindf))
  2233. +        if (!cursed(ublindf, FALSE))
  2234.              Blindf_off(ublindf);
  2235.      } else {
  2236.          impossible("do_takeoff: taking off %lx", doff->what);
  2237. diff --git c/src/dog.c i/src/dog.c
  2238. index a19167794..aef390467 100644
  2239. --- c/src/dog.c
  2240. +++ i/src/dog.c
  2241. @@ -75,10 +75,16 @@ boolean quietly;
  2242.      struct permonst *pm;
  2243.      struct monst *mtmp = 0;
  2244.      int chance, trycnt = 100;
  2245. +    boolean idol = otmp && otmp->oartifact == ART_IDOL_OF_MOLOCH;
  2246.  
  2247.      do {
  2248.          if (otmp) { /* figurine; otherwise spell */
  2249.              int mndx = otmp->corpsenm;
  2250. +            if (idol) {
  2251. +                mndx = ndemon(A_NONE);
  2252. +                if (mndx == NON_PM) /* just in case */
  2253. +                    continue;
  2254. +            }
  2255.  
  2256.              pm = &mons[mndx];
  2257.              /* activating a figurine provides one way to exceed the
  2258. @@ -86,10 +92,14 @@ boolean quietly;
  2259.                 it has a special limit (erinys, Nazgul) */
  2260.              if ((g.mvitals[mndx].mvflags & G_EXTINCT)
  2261.                  && mbirth_limit(mndx) != MAXMONNO) {
  2262. -                if (!quietly)
  2263. +                if (!quietly) {
  2264.                      /* have just been given "You <do something with>
  2265.                         the figurine and it transforms." message */
  2266. -                    pline("... into a pile of dust.");
  2267. +                    if (!idol)
  2268. +                        pline("... into a pile of dust.");
  2269. +                    else if (!Blind)
  2270. +                        pline_The("cloud disperses.");
  2271. +                }
  2272.                  break; /* mtmp is null */
  2273.              }
  2274.          } else if (!rn2(3)) {
  2275. @@ -103,10 +113,16 @@ boolean quietly;
  2276.              }
  2277.          }
  2278.  
  2279. -        mtmp = makemon(pm, x, y, MM_EDOG | MM_IGNOREWATER | NO_MINVENT);
  2280. +        mtmp = makemon(pm, x, y, MM_EDOG | MM_IGNOREWATER
  2281. +                                 | (!idol * NO_MINVENT));
  2282.          if (otmp && !mtmp) { /* monster was genocided or square occupied */
  2283. -            if (!quietly)
  2284. -                pline_The("figurine writhes and then shatters into pieces!");
  2285. +            if (!quietly) {
  2286. +                if (!idol)
  2287. +                    pline_The("figurine writhes and then shatters "
  2288. +                              "into pieces!");
  2289. +                else if (!Blind)
  2290. +                    pline_The("cloud disperses.");
  2291. +            }
  2292.              break;
  2293.          }
  2294.      } while (!mtmp && --trycnt > 0);
  2295. @@ -114,6 +130,14 @@ boolean quietly;
  2296.      if (!mtmp)
  2297.          return (struct monst *) 0;
  2298.  
  2299. +    if (idol && !quietly && !Blind) {
  2300. +        pline_The("mist coagulates into the shape of %s%s.",
  2301. +                  x_monnam(mtmp, ARTICLE_A, (char *) 0, SUPPRESS_IT
  2302. +                           | SUPPRESS_INVISIBLE | SUPPRESS_SADDLE
  2303. +                           | SUPPRESS_NAME, FALSE),
  2304. +                  canspotmon(mtmp) ? "" : " and vanishes");
  2305. +    }
  2306. +
  2307.      if (is_pool(mtmp->mx, mtmp->my) && minliquid(mtmp))
  2308.          return (struct monst *) 0;
  2309.  
  2310. @@ -134,7 +158,7 @@ boolean quietly;
  2311.              }
  2312.          }
  2313.          /* if figurine has been named, give same name to the monster */
  2314. -        if (has_oname(otmp))
  2315. +        if (has_oname(otmp) && !idol)
  2316.              mtmp = christen_monst(mtmp, ONAME(otmp));
  2317.      }
  2318.      set_malign(mtmp); /* more alignment changes */
  2319. @@ -551,6 +575,19 @@ long nmv; /* number of moves */
  2320.          m_unleash(mtmp, FALSE);
  2321.      }
  2322.  
  2323. +    /* maybe pick up the abandoned Amulet */
  2324. +    if (mtmp->data == &mons[PM_AGENT] && !mtmp->mpeaceful
  2325. +        && !mon_has_amulet(mtmp) && rn2(imv + 1) > 300) {
  2326. +        struct obj *otmp;
  2327. +        for (otmp = g.level.objlist; otmp; otmp = otmp->nobj)
  2328. +            if (otmp->otyp == AMULET_OF_YENDOR
  2329. +                || otmp->otyp == FAKE_AMULET_OF_YENDOR) {
  2330. +                obj_extract_self(otmp);
  2331. +                (void) mpickobj(mtmp, otmp);
  2332. +                break;
  2333. +            }
  2334. +    }
  2335. +
  2336.      /* recover lost hit points */
  2337.      if (!regenerates(mtmp->data))
  2338.          imv /= 20;
  2339. @@ -941,7 +978,7 @@ register struct obj *obj;
  2340.          /* monsters with conflicting structures cannot be tamed */
  2341.          || mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion
  2342.          || is_covetous(mtmp->data) || is_human(mtmp->data)
  2343. -        || (is_demon(mtmp->data) && !is_demon(g.youmonst.data))
  2344. +        || (is_demon(mtmp->data) && !is_demon(raceptr(&g.youmonst)))
  2345.          || (obj && dogfood(mtmp, obj) >= MANFOOD))
  2346.          return FALSE;
  2347.  
  2348. diff --git c/src/dothrow.c i/src/dothrow.c
  2349. index 1e6930c8e..caa8c1dd1 100644
  2350. --- c/src/dothrow.c
  2351. +++ i/src/dothrow.c
  2352. @@ -159,6 +159,7 @@ int shotlimit;
  2353.          /* some roles don't get a volley bonus until becoming expert */
  2354.          weakmultishot = (Role_if(PM_WIZARD) || Role_if(PM_PRIEST)
  2355.                           || (Role_if(PM_HEALER) && skill != P_KNIFE)
  2356. +                         || (Role_if(PM_INFIDEL) && skill != P_DAGGER)
  2357.                           || (Role_if(PM_TOURIST) && skill != -P_DART)
  2358.                           /* poor dexterity also inhibits multishot */
  2359.                           || Fumbling || ACURR(A_DEX) <= 6);
  2360. @@ -1824,7 +1825,7 @@ register struct monst *mon;
  2361.  register struct obj *obj;
  2362.  {
  2363.      char buf[BUFSZ];
  2364. -    boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
  2365. +    boolean is_buddy = sgn(mon->data->maligntyp) == u.ualign.type;
  2366.      boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
  2367.      int ret = 0;
  2368.      static NEARDATA const char nogood[] = " is not interested in your junk.";
  2369. diff --git c/src/dungeon.c i/src/dungeon.c
  2370. index f376e5237..333aec237 100644
  2371. --- c/src/dungeon.c
  2372. +++ i/src/dungeon.c
  2373. @@ -1420,7 +1420,8 @@ boolean at_stairs;
  2374.          /* Taking an up dungeon branch. */
  2375.          /* KMH -- Upwards branches are okay if not level 1 */
  2376.          /* (Just make sure it doesn't go above depth 1) */
  2377. -        if (!u.uz.dnum && u.uz.dlevel == 1 && !u.uhave.amulet)
  2378. +        if (!u.uz.dnum && u.uz.dlevel == 1
  2379. +            && (!u.uhave.amulet || Role_if(PM_INFIDEL) && !u.uevent.ascended))
  2380.              done(ESCAPED);
  2381.          else
  2382.              goto_level(&g.sstairs.tolev, at_stairs, FALSE, FALSE);
  2383. @@ -3303,8 +3304,11 @@ boolean printdun;
  2384.              else
  2385.                  ADDNTOBUF("temple", mptr->feat.ntemple);
  2386.  
  2387. -            /* only print out altar's god if they are all to your god */
  2388. -            if (Amask2align(Msa2amask(mptr->feat.msalign)) == u.ualign.type)
  2389. +            /* only print out altar's god if they are all to your god
  2390. +             * For Infidels, only print Moloch if there's exactly one altar;
  2391. +             * this is a technical resriction (i.e. I'm too lazy to fix it) */
  2392. +            if (Amask2align(Msa2amask(mptr->feat.msalign)) == u.ualign.type
  2393. +                && (u.ualign.type != A_NONE || mptr->feat.naltar == 1))
  2394.                  Sprintf(eos(buf), " to %s", align_gname(u.ualign.type));
  2395.          }
  2396.          ADDNTOBUF("throne", mptr->feat.nthrone);
  2397. diff --git c/src/eat.c i/src/eat.c
  2398. index de5e698b6..e51a41c86 100644
  2399. --- c/src/eat.c
  2400. +++ i/src/eat.c
  2401. @@ -2819,10 +2819,7 @@ gethungry()
  2402.         will need to wear an Amulet of Unchanging so still burn a small
  2403.         amount of nutrition in the 'moves % 20' ring/amulet check below */
  2404.      if ((!Unaware || !rn2(10)) /* slow metabolic rate while asleep */
  2405. -        && (carnivorous(g.youmonst.data)
  2406. -            || herbivorous(g.youmonst.data)
  2407. -            || metallivorous(g.youmonst.data))
  2408. -        && !Slow_digestion)
  2409. +        && !inediate(raceptr(&g.youmonst)) && !Slow_digestion)
  2410.          u.uhunger--; /* ordinary food consumption */
  2411.  
  2412.      if (g.moves % 2) { /* odd turns */
  2413. diff --git c/src/end.c i/src/end.c
  2414. index a33e9ef07..82a81c520 100644
  2415. --- c/src/end.c
  2416. +++ i/src/end.c
  2417. @@ -906,6 +906,8 @@ struct obj *list; /* inventory or container contents */
  2418.          } else if (obj->oartifact) {
  2419.              continue;
  2420.          } else if (obj->oclass == AMULET_CLASS) {
  2421. +            if (Role_if(PM_INFIDEL) && obj->otyp == AMULET_OF_YENDOR)
  2422. +                continue; /* starting inventory */
  2423.              i = obj->otyp - FIRST_AMULET;
  2424.              if (!g.amulets[i].count) {
  2425.                  g.amulets[i].count = obj->quan;
  2426. @@ -1471,7 +1473,9 @@ int how;
  2427.                  ? (const char *) ((flags.female && g.urole.name.f)
  2428.                      ? g.urole.name.f
  2429.                      : g.urole.name.m)
  2430. -                : (const char *) (flags.female ? "Demigoddess" : "Demigod"));
  2431. +                : Role_if(PM_INFIDEL) /* can only ascend via Moloch */
  2432. +                 ? (const char *) (flags.female ? "Demon Lady" : "Demon Lord")
  2433. +                 : (const char *) (flags.female ? "Demigoddess" : "Demigod"));
  2434.      dump_forward_putstr(endwin, 0, pbuf, done_stopprint);
  2435.      dump_forward_putstr(endwin, 0, "", done_stopprint);
  2436.  
  2437. diff --git c/src/engrave.c i/src/engrave.c
  2438. index f78545329..e1f967c20 100644
  2439. --- c/src/engrave.c
  2440. +++ i/src/engrave.c
  2441. @@ -429,7 +429,7 @@ int
  2442.  freehand()
  2443.  {
  2444.      return (!uwep || !welded(uwep)
  2445. -            || (!bimanual(uwep) && (!uarms || !uarms->cursed)));
  2446. +            || (!bimanual(uwep) && (!uarms || !cursed(uarms, TRUE))));
  2447.  }
  2448.  
  2449.  static NEARDATA const char styluses[] = { ALL_CLASSES, ALLOW_NONE,
  2450. @@ -502,7 +502,7 @@ doengrave()
  2451.      maxelen = BUFSZ - 1;
  2452.      if (oep)
  2453.          oetype = oep->engr_type;
  2454. -    if (is_demon(g.youmonst.data) || is_vampire(g.youmonst.data))
  2455. +    if (is_demon(raceptr(&g.youmonst)) || is_vampire(g.youmonst.data))
  2456.          type = ENGR_BLOOD;
  2457.  
  2458.      /* Can the adventurer engrave at all? */
  2459. diff --git c/src/exper.c i/src/exper.c
  2460. index f7e426db4..c69186bdd 100644
  2461. --- c/src/exper.c
  2462. +++ i/src/exper.c
  2463. @@ -32,6 +32,7 @@ int en;
  2464.      case PM_WIZARD:
  2465.          return (2 * en);
  2466.      case PM_HEALER:
  2467. +    case PM_INFIDEL:
  2468.      case PM_KNIGHT:
  2469.          return ((3 * en) / 2);
  2470.      case PM_BARBARIAN:
  2471. diff --git c/src/explode.c i/src/explode.c
  2472. index c44baa261..c43671c42 100644
  2473. --- c/src/explode.c
  2474. +++ i/src/explode.c
  2475. @@ -184,8 +184,8 @@ int expltype;
  2476.                      break;
  2477.                  case AD_DISN:
  2478.                      explmask[i][j] = (olet == WAND_CLASS)
  2479. -                                         ? !!(nonliving(g.youmonst.data)
  2480. -                                              || is_demon(g.youmonst.data))
  2481. +                                         ? (nonliving(g.youmonst.data)
  2482. +                                            || is_demon(raceptr(&g.youmonst)))
  2483.                                           : !!Disint_resistance;
  2484.                      break;
  2485.                  case AD_ELEC:
  2486. diff --git c/src/hack.c i/src/hack.c
  2487. index 81ed3c38e..386d55aee 100644
  2488. --- c/src/hack.c
  2489. +++ i/src/hack.c
  2490. @@ -2078,7 +2078,6 @@ invocation_message()
  2491.              Sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
  2492.  
  2493.          You_feel("a strange vibration %s.", buf);
  2494. -        u.uevent.uvibrated = 1;
  2495.          if (otmp && otmp->spe == 7 && otmp->lamplit)
  2496.              pline("%s %s!", The(xname(otmp)),
  2497.                    Blind ? "throbs palpably" : "glows with a strange light");
  2498. @@ -2119,7 +2118,7 @@ switch_terrain()
  2499.          /* [minor bug: we don't know whether this is beginning flight or
  2500.             resuming it; that could be tracked so that this message could
  2501.             be adjusted to "resume flying", but isn't worth the effort...] */
  2502. -        if (Flying)
  2503. +        if (Flying && !was_flying)
  2504.              You("start flying.");
  2505.      }
  2506.      if ((!!Levitation ^ was_levitating) || (!!Flying ^ was_flying))
  2507. diff --git c/src/insight.c i/src/insight.c
  2508. index 6e300241b..8267664c6 100644
  2509. --- c/src/insight.c
  2510. +++ i/src/insight.c
  2511. @@ -293,7 +293,7 @@ int unused_mode UNUSED;
  2512.  int final;
  2513.  {
  2514.      const char *role_titl, *rank_titl;
  2515. -    int innategend, difgend, difalgn;
  2516. +    int innategend, difgend, difalgn, difrace;
  2517.      char buf[BUFSZ], tmpbuf[BUFSZ];
  2518.  
  2519.      /* note that if poly'd, we need to use u.mfemale instead of flags.female
  2520. @@ -377,12 +377,14 @@ int final;
  2521.         trailing "and" on all three aligned entries but looks too verbose] */
  2522.      Sprintf(buf, " who %s opposed by", !final ? "is" : "was");
  2523.      if (u.ualign.type != A_LAWFUL)
  2524. -        Sprintf(eos(buf), " %s (%s) and", align_gname(A_LAWFUL),
  2525. -                align_str(A_LAWFUL));
  2526. +        Sprintf(eos(buf), " %s (%s)%s", align_gname(A_LAWFUL),
  2527. +                align_str(A_LAWFUL),
  2528. +                (u.ualign.type != A_NONE) ? " and" : ",");
  2529.      if (u.ualign.type != A_NEUTRAL)
  2530.          Sprintf(eos(buf), " %s (%s)%s", align_gname(A_NEUTRAL),
  2531.                  align_str(A_NEUTRAL),
  2532. -                (u.ualign.type != A_CHAOTIC) ? " and" : "");
  2533. +                (u.ualign.type == A_NONE) ? ", and" /* oxford comma */
  2534. +                : (u.ualign.type != A_CHAOTIC) ? " and" : "");
  2535.      if (u.ualign.type != A_CHAOTIC)
  2536.          Sprintf(eos(buf), " %s (%s)", align_gname(A_CHAOTIC),
  2537.                  align_str(A_CHAOTIC));
  2538. @@ -397,12 +399,26 @@ int final;
  2539.      difalgn = (((u.ualign.type != u.ualignbase[A_CURRENT]) ? 1 : 0)
  2540.                 + ((u.ualignbase[A_CURRENT] != u.ualignbase[A_ORIGINAL])
  2541.                    ? 2 : 0));
  2542. +    difrace = g.urace.malenum != races[flags.initrace].malenum;
  2543.      if (difalgn & 1) { /* have temporary alignment so report permanent one */
  2544.          Sprintf(buf, "actually %s", align_str(u.ualignbase[A_CURRENT]));
  2545.          you_are(buf, "");
  2546.          difalgn &= ~1; /* suppress helm from "started out <foo>" message */
  2547.      }
  2548. -    if (difgend || difalgn) { /* sex change or perm align change or both */
  2549. +    if (difrace) { /* permanent race change (Inf crowning) */
  2550. +        buf[0] = '\0';
  2551. +        if (difalgn) {
  2552. +            Strcat(buf, align_str(u.ualignbase[A_ORIGINAL]));
  2553. +            Strcat(buf, " ");
  2554. +        }
  2555. +        if (difgend) {
  2556. +            Strcat(buf, genders[flags.initgend].adj);
  2557. +            Strcat(buf, " ");
  2558. +        }
  2559. +        Strcat(buf, races[flags.initrace].noun);
  2560. +        Sprintf(buf, " You started out as %s.", an(buf));
  2561. +        enlght_out(buf);
  2562. +    } else if (difgend || difalgn) { /* sex change or perm align change */
  2563.          Sprintf(buf, " You started out %s%s%s.",
  2564.                  difgend ? genders[flags.initgend].adj : "",
  2565.                  (difgend && difalgn) ? " and " : "",
  2566. @@ -968,6 +984,25 @@ int final;
  2567.              enl_msg("You ", "fall", "fell", " asleep uncontrollably", buf);
  2568.          }
  2569.      }
  2570. +    /* In case the player missed the "urge to perform a sacrifice",
  2571. +     * put a reminder here. */
  2572. +    if (u.ualign.type == A_NONE) {
  2573. +        long due = g.moves - g.context.next_moloch_offering;
  2574. +        if (due < 0) {
  2575. +            if (wizard) {
  2576. +                Sprintf(buf, "%ld turns until your next "
  2577. +                        "mandatory sacrifice to ", -due);
  2578. +                you_have(buf, u_gname());
  2579. +            }
  2580. +        } else {
  2581. +            if (wizard && due > 0)
  2582. +                Sprintf(buf, "%ld turns late for your "
  2583. +                        "next sacrifice to ", due);
  2584. +            else
  2585. +                Strcpy(buf, "due for a sacrifice to ");
  2586. +            you_are(buf, u_gname());
  2587. +        }
  2588. +    }
  2589.      /* hunger/nutrition */
  2590.      if (Hunger) {
  2591.          if (magic || cause_known(HUNGER))
  2592. @@ -1251,9 +1286,10 @@ int final;
  2593.      enlght_out(final ? "Final Attributes:" : "Current Attributes:");
  2594.  
  2595.      if (u.uevent.uhand_of_elbereth) {
  2596. -        static const char *const hofe_titles[3] = { "the Hand of Elbereth",
  2597. +        static const char *const hofe_titles[4] = { "the Hand of Elbereth",
  2598.                                                      "the Envoy of Balance",
  2599. -                                                    "the Glory of Arioch" };
  2600. +                                                    "the Glory of Arioch",
  2601. +                                                    "a demon of Moloch" };
  2602.          you_are(hofe_titles[u.uevent.uhand_of_elbereth - 1], "");
  2603.      }
  2604.  
  2605. @@ -1422,7 +1458,7 @@ int final;
  2606.          BLevitation = save_BLev;
  2607.      }
  2608.      /* actively flying handled earlier as a status condition */
  2609. -    if (BFlying) { /* flight is blocked */
  2610. +    if (BFlying && !Flying) { /* flight is blocked */
  2611.          long save_BFly = BFlying;
  2612.  
  2613.          BFlying = 0L;
  2614. @@ -1444,7 +1480,9 @@ int final;
  2615.                               ? if_surroundings_permitted
  2616.                               /* two or more of levitation, surroundings,
  2617.                                  and being trapped in the floor */
  2618. -                             : " if circumstances permitted",
  2619. +                             : (save_BFly == W_ARM)
  2620. +                                ? " if your wings weren't confined"
  2621. +                                : " if circumstances permitted",
  2622.                      "");
  2623.          }
  2624.          BFlying = save_BFly;
  2625. @@ -1916,7 +1954,9 @@ int final; /* used "behind the curtain" by enl_foo() macros */
  2626.      if (remove_achievement(ACH_UWIN)) { /* UWIN == Ascended! */
  2627.          /* for ascension, force it to be last and Amulet next to last
  2628.             by taking them out and then adding them back */
  2629. -        if (remove_achievement(ACH_AMUL)) /* should always be True here */
  2630. +        /* Inf are an exception, as the Amulet offering
  2631. +         * is not endgame to them */
  2632. +        if (!Role_if(PM_INFIDEL) && remove_achievement(ACH_AMUL))
  2633.              record_achievement(ACH_AMUL);
  2634.          record_achievement(ACH_UWIN);
  2635.      }
  2636. @@ -1994,9 +2034,11 @@ int final; /* used "behind the curtain" by enl_foo() macros */
  2637.          case ACH_AMUL:
  2638.              /* alternate wording for ascended (always past tense) since
  2639.                 hero had it until #offer forced it to be relinquished */
  2640. +            /* always means "delivered" for Infidels */
  2641.              enl_msg(You_,
  2642. -                    u.uhave.amulet ? "have" : "have obtained",
  2643. -                    u.uevent.ascended ? "delivered"
  2644. +                    Role_if(PM_INFIDEL) ? "have delivered"
  2645. +                     : u.uhave.amulet ? "have" : "have obtained",
  2646. +                    Role_if(PM_INFIDEL) || u.uevent.ascended ? "delivered"
  2647.                       : u.uhave.amulet ? "had" : "had obtained",
  2648.                      " the Amulet of Yendor", "");
  2649.              break;
  2650. diff --git c/src/invent.c i/src/invent.c
  2651. index 0e0ccec8f..8df7b49f3 100644
  2652. --- c/src/invent.c
  2653. +++ i/src/invent.c
  2654. @@ -812,7 +812,8 @@ struct obj *obj;
  2655.          if (u.uhave.amulet)
  2656.              impossible("already have amulet?");
  2657.          u.uhave.amulet = 1;
  2658. -        record_achievement(ACH_AMUL);
  2659. +        if (!Role_if(PM_INFIDEL))
  2660. +            record_achievement(ACH_AMUL);
  2661.      } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
  2662.          if (u.uhave.menorah)
  2663.              impossible("already have candelabrum?");
  2664. @@ -833,6 +834,8 @@ struct obj *obj;
  2665.              if (u.uhave.questart)
  2666.                  impossible("already have quest artifact?");
  2667.              u.uhave.questart = 1;
  2668. +            if (Role_if(PM_INFIDEL) && obj->spe)
  2669. +                u.uhave.amulet = 1;
  2670.              artitouch(obj);
  2671.          }
  2672.          set_artifact_intrinsic(obj, 1, W_ART);
  2673. @@ -1057,7 +1060,8 @@ const char *drop_fmt, *drop_arg, *hold_msg;
  2674.              drop_arg = strcpy(buf, drop_arg);
  2675.  
  2676.          obj = addinv_core0(obj, (struct obj *) 0, FALSE);
  2677. -        if (inv_cnt(FALSE) > 52 || ((obj->otyp != LOADSTONE || !obj->cursed)
  2678. +        if (inv_cnt(FALSE) > 52 || ((obj->otyp != LOADSTONE
  2679. +                                     || !cursed(obj, TRUE))
  2680.                                      && near_capacity() > prev_encumbr)) {
  2681.              /* undo any merge which took place */
  2682.              if (obj->quan > oquan)
  2683. @@ -1164,6 +1168,8 @@ struct obj *obj;
  2684.              if (!u.uhave.questart)
  2685.                  impossible("don't have quest artifact?");
  2686.              u.uhave.questart = 0;
  2687. +            if (Role_if(PM_INFIDEL) && obj->spe)
  2688. +                u.uhave.amulet = 0;
  2689.          }
  2690.          set_artifact_intrinsic(obj, 0, W_ART);
  2691.      }
  2692. @@ -1213,6 +1219,7 @@ register struct obj *obj;
  2693.      boolean update_map;
  2694.  
  2695.      if (obj->otyp == AMULET_OF_YENDOR
  2696. +        || Role_if(PM_INFIDEL) && is_quest_artifact(obj) && obj->spe
  2697.          || obj->otyp == CANDELABRUM_OF_INVOCATION
  2698.          || obj->otyp == BELL_OF_OPENING
  2699.          || obj->otyp == SPE_BOOK_OF_THE_DEAD) {
  2700. @@ -1442,7 +1449,7 @@ boolean
  2701.  splittable(obj)
  2702.  struct obj *obj;
  2703.  {
  2704. -    return !((obj->otyp == LOADSTONE && obj->cursed)
  2705. +    return !((obj->otyp == LOADSTONE && cursed(obj, TRUE))
  2706.               || (obj == uwep && welded(uwep)));
  2707.  }
  2708.  
  2709. @@ -1654,10 +1661,11 @@ register const char *let, *word;
  2710.               || (!strncmp(word, "rub on the stone", 16)
  2711.                   && *let == GEM_CLASS && otmp->dknown
  2712.                   && objects[otyp].oc_name_known)
  2713. -             /* suppress corpses on astral, amulets elsewhere */
  2714. +             /* suppress corpses on astral (or sanctum), amulets elsewhere */
  2715.               || (!strcmp(word, "sacrifice")
  2716.                   /* (!astral && amulet) || (astral && !amulet) */
  2717. -                 && (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
  2718. +                 && ((!Is_astralevel(&u.uz) && !Is_sanctum(&u.uz))
  2719. +                     ^ (otmp->oclass != AMULET_CLASS)))
  2720.               /* suppress container being stashed into */
  2721.               || (!strcmp(word, "stash") && !ck_bag(otmp))
  2722.               /* worn armor (shirt, suit) covered by worn armor (suit, cloak)
  2723. @@ -1873,7 +1881,7 @@ register const char *let, *word;
  2724.              /* don't split a stack of cursed loadstones */
  2725.              if (splittable(otmp))
  2726.                  otmp = splitobj(otmp, cnt);
  2727. -            else if (otmp->otyp == LOADSTONE && otmp->cursed)
  2728. +            else if (otmp->otyp == LOADSTONE && cursed(otmp, TRUE))
  2729.                  /* kludge for canletgo()'s can't-drop-this message */
  2730.                  otmp->corpsenm = (int) cnt;
  2731.          }
  2732. diff --git c/src/makemon.c i/src/makemon.c
  2733. index b325c64a7..59bd9fcd9 100644
  2734. --- c/src/makemon.c
  2735. +++ i/src/makemon.c
  2736. @@ -182,7 +182,7 @@ register struct monst *mtmp;
  2737.              (void) mongets(mtmp, (mm != PM_ETTIN) ? BOULDER : CLUB);
  2738.          break;
  2739.      case S_HUMAN:
  2740. -        if (is_mercenary(ptr)) {
  2741. +        if (is_mercenary(ptr) || mm == PM_TEMPLAR) {
  2742.              w1 = w2 = 0;
  2743.              switch (mm) {
  2744.              case PM_WATCHMAN:
  2745. @@ -201,6 +201,7 @@ register struct monst *mtmp;
  2746.                  break;
  2747.              case PM_CAPTAIN:
  2748.              case PM_WATCH_CAPTAIN:
  2749. +            case PM_TEMPLAR:
  2750.                  w1 = rn2(2) ? LONG_SWORD : SILVER_SABER;
  2751.                  break;
  2752.              default:
  2753. @@ -263,11 +264,20 @@ register struct monst *mtmp;
  2754.          } else if (mm == PM_NINJA) { /* extra quest villains */
  2755.              (void) mongets(mtmp, rn2(4) ? SHURIKEN : DART);
  2756.              (void) mongets(mtmp, rn2(4) ? SHORT_SWORD : AXE);
  2757. +        } else if (mm == PM_CHAMPION) {
  2758. +            (void) mongets(mtmp, rn2(2) ? TWO_HANDED_SWORD : BATTLE_AXE);
  2759. +            (void) mongets(mtmp, rn2(3) ? RING_MAIL : CHAIN_MAIL);
  2760. +        } else if (mm == PM_AGENT) {
  2761. +            (void) mongets(mtmp, rn2(4) ? SHORT_SWORD : DAGGER);
  2762. +            if (!rn2(3))
  2763. +                (void) mongets(mtmp, LEATHER_ARMOR);
  2764. +            (void) mongets(mtmp, POT_INVISIBILITY);
  2765.          } else if (ptr->msound == MS_GUARDIAN) {
  2766.              /* quest "guardians" */
  2767.              switch (mm) {
  2768.              case PM_STUDENT:
  2769.              case PM_ATTENDANT:
  2770. +            case PM_CULTIST:
  2771.              case PM_ABBOT:
  2772.              case PM_ACOLYTE:
  2773.              case PM_GUIDE:
  2774. @@ -584,7 +594,7 @@ register struct monst *mtmp;
  2775.       */
  2776.      switch (ptr->mlet) {
  2777.      case S_HUMAN:
  2778. -        if (is_mercenary(ptr)) {
  2779. +        if (is_mercenary(ptr) || monsndx(ptr) == PM_TEMPLAR) {
  2780.              register int mac;
  2781.  
  2782.              switch (monsndx(ptr)) {
  2783. @@ -609,6 +619,9 @@ register struct monst *mtmp;
  2784.              case PM_WATCH_CAPTAIN:
  2785.                  mac = -2;
  2786.                  break;
  2787. +            case PM_TEMPLAR:
  2788. +                mac = -3;
  2789. +                break;
  2790.              default:
  2791.                  impossible("odd mercenary %d?", monsndx(ptr));
  2792.                  mac = 0;
  2793. @@ -668,6 +681,10 @@ register struct monst *mtmp;
  2794.              } else if (ptr == &mons[PM_WATCHMAN]) {
  2795.                  if (rn2(3)) /* most watchmen carry a whistle */
  2796.                      (void) mongets(mtmp, TIN_WHISTLE);
  2797. +            } else if (ptr == &mons[PM_TEMPLAR]) {
  2798. +                if (rn2(3)) /* being in a holy order has its benefits */
  2799. +                    (void) mongets(mtmp, rn2(4) ? POT_HEALING
  2800. +                                                : POT_EXTRA_HEALING);
  2801.              } else if (ptr == &mons[PM_GUARD]) {
  2802.                  /* if hero teleports out of a vault while being confronted
  2803.                     by the vault's guard, there is a shrill whistling sound,
  2804. @@ -708,6 +725,22 @@ register struct monst *mtmp;
  2805.              mkmonmoney(mtmp, (long) rn1(10, 20));
  2806.          } else if (quest_mon_represents_role(ptr, PM_MONK)) {
  2807.              (void) mongets(mtmp, rn2(11) ? ROBE : CLOAK_OF_MAGIC_RESISTANCE);
  2808. +        } else if (ptr == &mons[PM_PREACHER_OF_MOLOCH]) {
  2809. +            (void) mongets(mtmp, QUARTERSTAFF);
  2810. +            (void) mongets(mtmp, rn2(3) ? ROBE : CLOAK_OF_PROTECTION);
  2811. +        } else if (ptr == &mons[PM_PALADIN]) {
  2812. +            otmp = mksobj(MORNING_STAR, FALSE, FALSE);
  2813. +            otmp->blessed = otmp->oerodeproof = 1;
  2814. +            otmp->spe = rn1(3, 3);
  2815. +            (void) mpickobj(mtmp, otmp);
  2816. +            /* the Paladin wears no helmet
  2817. +             * because she looks cooler without a helmet */
  2818. +            (void) mongets(mtmp, LEATHER_GLOVES);
  2819. +            (void) mongets(mtmp, SHIELD_OF_REFLECTION);
  2820. +            (void) mongets(mtmp, LEATHER_CLOAK);
  2821. +            (void) mongets(mtmp, CRYSTAL_PLATE_MAIL);
  2822. +            (void) mongets(mtmp, HIGH_BOOTS);
  2823. +            (void) mongets(mtmp, POT_SPEED);
  2824.          }
  2825.          break;
  2826.      case S_NYMPH:
  2827. @@ -1284,7 +1317,7 @@ long mmflags;
  2828.              mtmp->mpeaceful = FALSE;
  2829.          break;
  2830.      case S_UNICORN:
  2831. -        if (is_unicorn(ptr) && sgn(u.ualign.type) == sgn(ptr->maligntyp))
  2832. +        if (is_unicorn(ptr) && u.ualign.type == sgn(ptr->maligntyp))
  2833.              mtmp->mpeaceful = TRUE;
  2834.          break;
  2835.      case S_BAT:
  2836. @@ -1372,6 +1405,13 @@ long mmflags;
  2837.                                ? !eminp->renegade
  2838.                                : eminp->renegade;
  2839.      }
  2840. +    /* these monsters are normally affiliated with a deity */
  2841. +    if ((mndx == PM_PALADIN || mndx == PM_TEMPLAR || mndx == PM_CHAMPION
  2842. +         || mndx == PM_AGENT) && !(mmflags & MM_EMIN)) {
  2843. +        newemin(mtmp);
  2844. +        mtmp->isminion = 1;
  2845. +        EMIN(mtmp)->min_align = sgn(ptr->maligntyp);
  2846. +    }
  2847.      set_malign(mtmp); /* having finished peaceful changes */
  2848.      if (anymon && !(mmflags & MM_NOGRP)) {
  2849.          if ((ptr->geno & G_SGROUP) && rn2(2)) {
  2850. @@ -2042,7 +2082,11 @@ register struct permonst *ptr;
  2851.  
  2852.      if (always_peaceful(ptr))
  2853.          return TRUE;
  2854. -    if (always_hostile(ptr))
  2855. +    /* Major demons will sometimes be peaceful to unaligned Infidels.
  2856. +     * They must pass this 50% check, then the 50% check for chaotics
  2857. +     * being non-hostile to unaligned, then the usual check for coaligned.
  2858. +     * For crowned Infidels, the last two checks are bypassed. */
  2859. +    if (always_hostile(ptr) && (ual != A_NONE || !is_demon(ptr) || rn2(2)))
  2860.          return FALSE;
  2861.      if (ptr->msound == MS_LEADER || ptr->msound == MS_GUARDIAN)
  2862.          return TRUE;
  2863. @@ -2059,8 +2103,12 @@ register struct permonst *ptr;
  2864.      if (sgn(mal) != sgn(ual))
  2865.          return FALSE;
  2866.  
  2867. -    /* Negative monster hostile to player with Amulet. */
  2868. -    if (mal < A_NEUTRAL && u.uhave.amulet)
  2869. +    /* Not all chaotics support Moloch.  This goes especially for elves. */
  2870. +    if (ual == A_NONE && (is_elf(ptr) || rn2(2)))
  2871. +        return FALSE;
  2872. +
  2873. +    /* Chaotic monsters hostile to players with Amulet, except Infidels. */
  2874. +    if (mal < A_NEUTRAL && u.uhave.amulet && ual != A_NONE)
  2875.          return FALSE;
  2876.  
  2877.      /* minions are hostile to players that have strayed at all */
  2878. @@ -2105,7 +2153,7 @@ struct monst *mtmp;
  2879.              mal *= 5;
  2880.      }
  2881.  
  2882. -    coaligned = (sgn(mal) == sgn(u.ualign.type));
  2883. +    coaligned = (sgn(mal) == u.ualign.type);
  2884.      if (mtmp->data->msound == MS_LEADER) {
  2885.          mtmp->malign = -20;
  2886.      } else if (mal == A_NONE) {
  2887. @@ -2113,6 +2161,8 @@ struct monst *mtmp;
  2888.              mtmp->malign = 0;
  2889.          else
  2890.              mtmp->malign = 20; /* really hostile */
  2891. +        if (u.ualign.type == A_NONE)
  2892. +            mtmp->malign -= 20; /* reverse */
  2893.      } else if (always_peaceful(mtmp->data)) {
  2894.          int absmal = abs(mal);
  2895.          if (mtmp->mpeaceful)
  2896. diff --git c/src/mcastu.c i/src/mcastu.c
  2897. index bc1000fbe..02d8c5116 100644
  2898. --- c/src/mcastu.c
  2899. +++ i/src/mcastu.c
  2900. @@ -375,7 +375,7 @@ int spellnum;
  2901.      switch (spellnum) {
  2902.      case MGC_DEATH_TOUCH:
  2903.          pline("Oh no, %s's using the touch of death!", mhe(mtmp));
  2904. -        if (nonliving(g.youmonst.data) || is_demon(g.youmonst.data)) {
  2905. +        if (nonliving(g.youmonst.data) || is_demon(raceptr(&g.youmonst))) {
  2906.              You("seem no deader than before.");
  2907.          } else if (!Antimagic && rn2(mtmp->m_lev) > 12) {
  2908.              if (Hallucination) {
  2909. diff --git c/src/mhitu.c i/src/mhitu.c
  2910. index 29d257294..e5193cc68 100644
  2911. --- c/src/mhitu.c
  2912. +++ i/src/mhitu.c
  2913. @@ -792,7 +792,7 @@ boolean youseeit;
  2914.       */
  2915.  
  2916.      if (is_demon(mdat)) {
  2917. -        if (mdat != &mons[PM_BALROG]
  2918. +        if (mdat != &mons[PM_BALROG] && mdat != &mons[PM_DEMON]
  2919.              && mdat != &mons[PM_SUCCUBUS] && mdat != &mons[PM_INCUBUS]) {
  2920.              if (!rn2(13))
  2921.                  (void) msummon(mtmp);
  2922. diff --git c/src/minion.c i/src/minion.c
  2923. index 03706027a..c8d3a87db 100644
  2924. --- c/src/minion.c
  2925. +++ i/src/minion.c
  2926. @@ -260,7 +260,7 @@ register struct monst *mtmp;
  2927.          }
  2928.          newsym(mtmp->mx, mtmp->my);
  2929.      }
  2930. -    if (g.youmonst.data->mlet == S_DEMON) { /* Won't blackmail their own. */
  2931. +    if (is_demon(raceptr(&g.youmonst))) { /* Won't blackmail their own. */
  2932.          pline("%s says, \"Good hunting, %s.\"", Amonnam(mtmp),
  2933.                flags.female ? "Sister" : "Brother");
  2934.          if (!tele_restrict(mtmp))
  2935. diff --git c/src/mon.c i/src/mon.c
  2936. index f9b5fd6d4..21b1efad2 100644
  2937. --- c/src/mon.c
  2938. +++ i/src/mon.c
  2939. @@ -2640,7 +2640,7 @@ int xkill_flags; /* 1: suppress message, 2: suppress corpse, 4: pacifist */
  2940.      }
  2941.      if ((mtmp->mpeaceful && !rn2(2)) || mtmp->mtame)
  2942.          change_luck(-1);
  2943. -    if (is_unicorn(mdat) && sgn(u.ualign.type) == sgn(mdat->maligntyp)) {
  2944. +    if (is_unicorn(mdat) && u.ualign.type == sgn(mdat->maligntyp)) {
  2945.          change_luck(-5);
  2946.          You_feel("guilty...");
  2947.      }
  2948. @@ -2668,7 +2668,7 @@ int xkill_flags; /* 1: suppress message, 2: suppress corpse, 4: pacifist */
  2949.          /* cancel divine protection for killing your priest */
  2950.          if (p_coaligned(mtmp))
  2951.              u.ublessed = 0;
  2952. -        if (mdat->maligntyp == A_NONE)
  2953. +        else if (mdat->maligntyp == A_NONE)
  2954.              adjalign((int) (ALIGNLIM / 4)); /* BIG bonus */
  2955.      } else if (mtmp->mtame) {
  2956.          adjalign(-15); /* bad!! */
  2957. @@ -3068,7 +3068,6 @@ boolean via_attack;
  2958.          /* only hypocritical if monster is vulnerable to Elbereth (or
  2959.             peaceful--not vulnerable but attacking it is hypocritical) */
  2960.          && (onscary(u.ux, u.uy, mtmp) || mtmp->mpeaceful)) {
  2961. -        You_feel("like a hypocrite.");
  2962.          /* AIS: Yes, I know alignment penalties and bonuses aren't balanced
  2963.             at the moment. This is about correct relative to other "small"
  2964.             penalties; it should be fairly large, as attacking while standing
  2965. @@ -3077,7 +3076,11 @@ boolean via_attack;
  2966.             it's intentionally larger than the 1s and 2s that are normally
  2967.             given for this sort of thing. */
  2968.          /* reduce to 3 (average) when alignment is already very low */
  2969. -        adjalign((u.ualign.record > 5) ? -5 : -rnd(5));
  2970. +        if (u.ualign.type != A_NONE) {
  2971. +            You_feel("like a hypocrite.");
  2972. +            adjalign((u.ualign.record > 5) ? -5 : -rnd(5));
  2973. +        } else
  2974. +            You_feel("wily."); /* no alignment penalty */
  2975.  
  2976.          if (!Blind)
  2977.              pline("The engraving beneath you fades.");
  2978. diff --git c/src/mondata.c i/src/mondata.c
  2979. index 4e0ba2d0a..4e13ae429 100644
  2980. --- c/src/mondata.c
  2981. +++ i/src/mondata.c
  2982. @@ -97,7 +97,7 @@ boolean
  2983.  resists_drli(mon)
  2984.  struct monst *mon;
  2985.  {
  2986. -    struct permonst *ptr = mon->data;
  2987. +    struct permonst *ptr = raceptr(mon); /* handle demonic race */
  2988.      struct obj *wep;
  2989.  
  2990.      if (is_undead(ptr) || is_demon(ptr) || is_were(ptr)
  2991. @@ -430,8 +430,7 @@ register struct permonst *ptr;
  2992.      return (boolean) (bigmonst(ptr)
  2993.                        || (ptr->msize > MZ_SMALL && !humanoid(ptr))
  2994.                        /* special cases of humanoids that cannot wear suits */
  2995. -                      || ptr == &mons[PM_MARILITH]
  2996. -                      || ptr == &mons[PM_WINGED_GARGOYLE]);
  2997. +                      || ptr == &mons[PM_MARILITH]);
  2998.  }
  2999.  
  3000.  /* creature sticks other creatures it hits */
  3001. @@ -1130,7 +1129,7 @@ int montyp1, montyp2;
  3002.   * Returns correct pointer for non-polymorphed and polymorphed
  3003.   * player.  It does not return a pointer to player role character.
  3004.   */
  3005. -const struct permonst *
  3006. +struct permonst *
  3007.  raceptr(mtmp)
  3008.  struct monst *mtmp;
  3009.  {
  3010. diff --git c/src/monmove.c i/src/monmove.c
  3011. index 7c03b2236..f5a720c3c 100644
  3012. --- c/src/monmove.c
  3013. +++ i/src/monmove.c
  3014. @@ -396,6 +396,14 @@ int *inrange, *nearby, *scared;
  3015.                      || (!mtmp->mpeaceful && in_your_sanctuary(mtmp, 0, 0)))) {
  3016.          *scared = 1;
  3017.          monflee(mtmp, rnd(rn2(7) ? 10 : 100), TRUE, TRUE);
  3018. +        if (u.ualign.type == A_NONE && !g.context.coward
  3019. +            && sengr_at("Elbereth", seescaryx, seescaryy, TRUE)) {
  3020. +            /* Followers of Moloch aren't supposed
  3021. +             * to hide behind other gods. */
  3022. +            You_feel("like a coward.");
  3023. +            g.context.coward = TRUE; /* once per move */
  3024. +            adjalign(-5);
  3025. +        }
  3026.      } else
  3027.          *scared = 0;
  3028.  }
  3029. @@ -999,6 +1007,9 @@ register int after;
  3030.                      > ((ygold = findgold(g.invent)) ? ygold->quan : 0L))))
  3031.              appr = -1;
  3032.  
  3033. +        if (monsndx(ptr) == PM_AGENT && mon_has_amulet(mtmp))
  3034. +            appr = -1; /* objective secured, retreat */
  3035. +
  3036.          /* hostile monsters with ranged thrown weapons try to stay away */
  3037.          if (!mtmp->mpeaceful
  3038.              && (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) < 5*5)
  3039. diff --git c/src/monst.c i/src/monst.c
  3040. index 9b8961636..5a0364c33 100644
  3041. --- c/src/monst.c
  3042. +++ i/src/monst.c
  3043. @@ -2159,6 +2159,27 @@ struct permonst _mons2[] = {
  3044.          M1_HUMANOID | M1_POIS | M1_REGEN | M1_OMNIVORE,
  3045.          M2_NOPOLY | M2_WERE | M2_HOSTILE | M2_HUMAN | M2_COLLECT,
  3046.          M3_INFRAVISIBLE, 6, CLR_ORANGE),
  3047. +    /* Only generated when playing as Infidel.
  3048. +     * Has emin, so always appears as a "champion of [deity]".
  3049. +     * Note: the difficulty is purposefully lowered. */
  3050. +    MON("champion", S_HUMAN, LVL(12, 12, 6, 10, 0), (G_NOGEN | G_NOHELL | 2),
  3051. +        A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6), NO_ATTK,
  3052. +          NO_ATTK, NO_ATTK, NO_ATTK),
  3053. +        SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), MR_POISON, 0,
  3054. +        M1_HUMANOID | M1_OMNIVORE,
  3055. +        M2_NOPOLY | M2_HUMAN | M2_HOSTILE | M2_NASTY | M2_STRONG | M2_COLLECT,
  3056. +        M3_INFRAVISIBLE, 6, CLR_GRAY),
  3057. +    /* Only generated when playing as Infidel.
  3058. +     * Has emin, so always appears as an "agent of [deity]".
  3059. +     * Note: the difficulty is purposefully lowered. */
  3060. +    MON("agent", S_HUMAN, LVL(6, 18, 10, 10, -7), (G_NOGEN | G_NOHELL | 3),
  3061. +        A(ATTK(AT_WEAP, AD_SAMU, 1, 4), ATTK(AT_CLAW, AD_SAMU, 1, 1),
  3062. +          ATTK(AT_CLAW, AD_SAMU, 1, 1), ATTK(AT_CLAW, AD_SAMU, 1, 1),
  3063. +          NO_ATTK, NO_ATTK),
  3064. +        SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0,
  3065. +        M1_HUMANOID | M1_OMNIVORE | M1_TPORT,
  3066. +        M2_NOPOLY | M2_HUMAN | M2_HOSTILE | M2_STALK | M2_STRONG | M2_COLLECT,
  3067. +        M3_INFRAVISIBLE, 6, CLR_BLACK),
  3068.      MON("elf", S_HUMAN, LVL(0, 12, 10, 2, -3), G_NOGEN, /* for corpses */
  3069.          A(ATTK(AT_WEAP, AD_PHYS, 1, 8),
  3070.            NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
  3071. @@ -2626,6 +2647,14 @@ struct permonst _mons2[] = {
  3072.          SIZ(1500, 400, MS_DJINNI, MZ_HUMAN), MR_POISON | MR_STONE, 0,
  3073.          M1_HUMANOID | M1_FLY | M1_POIS, M2_NOPOLY | M2_STALK | M2_COLLECT,
  3074.          M3_INFRAVISIBLE, 8, CLR_YELLOW),
  3075. +    /* racial monster for crowned Infidels */
  3076. +    MON("demon", S_DEMON, LVL(10, 12, 10, 10, A_NONE), (G_NOGEN | G_NOCORPSE),
  3077. +        A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_STNG, AD_DRST, 2, 4),
  3078. +          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
  3079. +        SIZ(WT_HUMAN, 400, MS_GRUNT, MZ_HUMAN), MR_FIRE | MR_POISON, 0,
  3080. +        M1_HUMANOID | M1_FLY | M1_SEE_INVIS | M1_POIS,
  3081. +        M2_NOPOLY | M2_DEMON | M2_STALK | M2_HOSTILE | M2_COLLECT,
  3082. +        M3_INFRAVISIBLE | M3_INFRAVISION, 13, CLR_RED),
  3083.      /*
  3084.       * sea monsters
  3085.       */
  3086. @@ -2776,6 +2805,13 @@ struct permonst _mons2[] = {
  3087.          M1_HUMANOID | M1_OMNIVORE,
  3088.          M2_NOPOLY | M2_HUMAN | M2_STRONG | M2_COLLECT, M3_INFRAVISIBLE,
  3089.          12, HI_DOMESTIC),
  3090. +    MON("infidel", S_HUMAN, LVL(10, 12, 10, 2, A_NONE), G_NOGEN,
  3091. +        A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
  3092. +          NO_ATTK),
  3093. +        SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), MR_FIRE, 0,
  3094. +        M1_HUMANOID | M1_OMNIVORE,
  3095. +        M2_NOPOLY | M2_HUMAN | M2_STRONG | M2_COLLECT, M3_INFRAVISIBLE,
  3096. +        12, HI_DOMESTIC),
  3097.      MON("knight", S_HUMAN, LVL(10, 12, 10, 1, 3), G_NOGEN,
  3098.          A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK,
  3099.            NO_ATTK, NO_ATTK, NO_ATTK),
  3100. @@ -2903,6 +2939,17 @@ struct permonst _mons2[] = {
  3101.          M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
  3102.              | M2_COLLECT | M2_MAGIC,
  3103.          M3_CLOSE | M3_INFRAVISIBLE, 22, HI_LORD),
  3104. +    /* apparently she should be a "preacheress" if female,
  3105. +     * but that word just sounds silly, imo */
  3106. +    MON("preacher of Moloch", S_HUMAN, LVL(20, 12, 0, 40, A_NONE),
  3107. +        (G_NOGEN | G_UNIQ),
  3108. +        A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_CLRC, 0, 0), NO_ATTK,
  3109. +          NO_ATTK, NO_ATTK, NO_ATTK),
  3110. +        SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), MR_FIRE | MR_ELEC, 0,
  3111. +        M1_HUMANOID | M1_OMNIVORE,
  3112. +        M2_NOPOLY | M2_HUMAN | M2_PEACEFUL | M2_STRONG | M2_COLLECT
  3113. +            | M2_MAGIC,
  3114. +        M3_CLOSE | M3_INFRAVISIBLE, 23, CLR_RED),
  3115.      MON("King Arthur", S_HUMAN, LVL(20, 12, 0, 40, 20), (G_NOGEN | G_UNIQ),
  3116.          A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK,
  3117.            NO_ATTK, NO_ATTK, NO_ATTK),
  3118. @@ -3045,6 +3092,18 @@ struct permonst _mons2[] = {
  3119.              | M2_HOSTILE | M2_NASTY | M2_MALE | M2_JEWELS | M2_COLLECT,
  3120.          M3_WANTSARTI | M3_WAITFORU | M3_INFRAVISION | M3_INFRAVISIBLE,
  3121.          23, CLR_GRAY),
  3122. +    /* Has emin, so always appears as the "Paladin of [deity]". */
  3123. +    MON("Paladin", S_HUMAN, LVL(24, 12, 0, 50, 20),
  3124. +        (G_NOGEN | G_UNIQ | G_NOCORPSE),
  3125. +        A(ATTK(AT_WEAP, AD_PHYS, 4, 4), ATTK(AT_WEAP, AD_STUN, 2, 6),
  3126. +          ATTK(AT_MAGC, AD_CLRC, 1, 8), ATTK(AT_CLAW, AD_SAMU, 1, 6),
  3127. +          NO_ATTK, NO_ATTK),
  3128. +        SIZ(WT_HUMAN, 400, MS_NEMESIS, MZ_HUMAN), MR_POISON | MR_STONE, 0,
  3129. +        M1_HUMANOID | M1_OMNIVORE | M1_SEE_INVIS,
  3130. +        M2_NOPOLY | M2_HUMAN | M2_MINION | M2_LORD | M2_STRONG | M2_FEMALE
  3131. +            | M2_STALK | M2_HOSTILE | M2_NASTY | M2_COLLECT | M2_MAGIC,
  3132. +        M3_WANTSARTI | M3_WANTSAMUL | M3_WAITFORU | M3_INFRAVISIBLE,
  3133. +        29, HI_GOLD),
  3134.      MON("Ixoth", S_DRAGON, LVL(15, 12, -1, 20, -14), (G_NOGEN | G_UNIQ),
  3135.          A(ATTK(AT_BREA, AD_FIRE, 8, 6), ATTK(AT_BITE, AD_PHYS, 4, 8),
  3136.            ATTK(AT_MAGC, AD_SPEL, 0, 0), ATTK(AT_CLAW, AD_PHYS, 2, 4),
  3137. @@ -3167,6 +3226,21 @@ struct permonst _mons2[] = {
  3138.          M1_HUMANOID | M1_OMNIVORE,
  3139.          M2_NOPOLY | M2_HUMAN | M2_PEACEFUL | M2_STRONG | M2_COLLECT,
  3140.          M3_INFRAVISIBLE, 7, HI_DOMESTIC),
  3141. +    /* Has emin, so always appears as a "templar of [deity]". */
  3142. +    MON("templar", S_HUMAN, LVL(12, 10, 10, 20, 10), G_NOGEN,
  3143. +        A(ATTK(AT_WEAP, AD_PHYS, 3, 4), ATTK(AT_WEAP, AD_PHYS, 3, 4), NO_ATTK,
  3144. +          NO_ATTK, NO_ATTK, NO_ATTK),
  3145. +        SIZ(WT_HUMAN, 400, MS_HUMANOID, MZ_HUMAN), 0, 0,
  3146. +        M1_HUMANOID | M1_OMNIVORE,
  3147. +        M2_NOPOLY | M2_HUMAN | M2_HOSTILE | M2_STRONG | M2_COLLECT,
  3148. +        M3_INFRAVISIBLE, 14, CLR_BLUE),
  3149. +    MON("cultist", S_HUMAN, LVL(5, 12, 10, 10, A_NONE), G_NOGEN,
  3150. +        A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
  3151. +          NO_ATTK),
  3152. +        SIZ(WT_HUMAN, 400, MS_GUARDIAN, MZ_HUMAN), MR_FIRE, 0,
  3153. +        M1_HUMANOID | M1_OMNIVORE,
  3154. +        M2_NOPOLY | M2_HUMAN | M2_PEACEFUL | M2_STRONG | M2_COLLECT,
  3155. +        M3_INFRAVISIBLE, 7, HI_DOMESTIC),
  3156.      MON("page", S_HUMAN, LVL(5, 12, 10, 10, 3), G_NOGEN,
  3157.          A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK,
  3158.            NO_ATTK, NO_ATTK, NO_ATTK),
  3159. diff --git c/src/mplayer.c i/src/mplayer.c
  3160. index 13a44ed35..6925b1d25 100644
  3161. --- c/src/mplayer.c
  3162. +++ i/src/mplayer.c
  3163. @@ -195,6 +195,16 @@ register boolean special;
  3164.              if (rn2(2))
  3165.                  shield = STRANGE_OBJECT;
  3166.              break;
  3167. +        case PM_INFIDEL:
  3168. +            if (!rn2(4))
  3169. +                weapon = CRYSKNIFE;
  3170. +            if (rn2(3))
  3171. +                cloak = CLOAK_OF_PROTECTION;
  3172. +            if (rn2(4))
  3173. +                helm = rn2(2) ? HELM_OF_BRILLIANCE : HELM_OF_TELEPATHY;
  3174. +            if (rn2(2))
  3175. +                shield = STRANGE_OBJECT;
  3176. +            break;
  3177.          case PM_KNIGHT:
  3178.              if (rn2(4))
  3179.                  weapon = LONG_SWORD;
  3180. diff --git c/src/muse.c i/src/muse.c
  3181. index b0ff3427a..c80c244a5 100644
  3182. --- c/src/muse.c
  3183. +++ i/src/muse.c
  3184. @@ -2332,6 +2332,9 @@ struct obj *obj;
  3185.              return (boolean) !(nonliving(mon->data) || is_vampshifter(mon));
  3186.          if (typ == AMULET_OF_REFLECTION || typ == AMULET_OF_GUARDING)
  3187.              return TRUE;
  3188. +        if (typ == AMULET_OF_YENDOR || typ == FAKE_AMULET_OF_YENDOR)
  3189. +            return (boolean) (mon->data == &mons[PM_AGENT]
  3190. +                              && !mon_has_amulet(mon));
  3191.          break;
  3192.      case TOOL_CLASS:
  3193.          if (typ == PICK_AXE)
  3194. diff --git c/src/pickup.c i/src/pickup.c
  3195. index bd17ab0f9..e81f56778 100644
  3196. --- c/src/pickup.c
  3197. +++ i/src/pickup.c
  3198. @@ -2278,11 +2278,12 @@ register struct obj *obj;
  3199.          Norep("You cannot %s %s you are wearing.",
  3200.                Icebox ? "refrigerate" : "stash", something);
  3201.          return 0;
  3202. -    } else if ((obj->otyp == LOADSTONE) && obj->cursed) {
  3203. +    } else if ((obj->otyp == LOADSTONE) && cursed(obj, TRUE)) {
  3204.          set_bknown(obj, 1);
  3205.          pline_The("stone%s won't leave your person.", plur(obj->quan));
  3206.          return 0;
  3207.      } else if (obj->otyp == AMULET_OF_YENDOR
  3208. +               || Role_if(PM_INFIDEL) && is_quest_artifact(obj) && obj->spe
  3209.                 || obj->otyp == CANDELABRUM_OF_INVOCATION
  3210.                 || obj->otyp == BELL_OF_OPENING
  3211.                 || obj->otyp == SPE_BOOK_OF_THE_DEAD) {
  3212. diff --git c/src/polyself.c i/src/polyself.c
  3213. index b06f2287e..f45489007 100644
  3214. --- c/src/polyself.c
  3215. +++ i/src/polyself.c
  3216. @@ -38,9 +38,11 @@ void
  3217.  set_uasmon()
  3218.  {
  3219.      struct permonst *mdat = &mons[u.umonnum];
  3220. +    struct permonst *racedat; /* for infravision, flying */
  3221.      boolean was_vampshifter = valid_vampshiftform(g.youmonst.cham, u.umonnum);
  3222.  
  3223.      set_mon_data(&g.youmonst, mdat);
  3224. +    racedat = raceptr(&g.youmonst);
  3225.  
  3226.      if (Protection_from_shape_changers)
  3227.          g.youmonst.cham = NON_PM;
  3228. @@ -87,7 +89,7 @@ set_uasmon()
  3229.      PROPSET(SEE_INVIS, perceives(mdat));
  3230.      PROPSET(TELEPAT, telepathic(mdat));
  3231.      /* note that Infravision uses mons[race] rather than usual mons[role] */
  3232. -    PROPSET(INFRAVISION, infravision(Upolyd ? mdat : &mons[g.urace.malenum]));
  3233. +    PROPSET(INFRAVISION, infravision(racedat));
  3234.      PROPSET(INVIS, pm_invisible(mdat));
  3235.      PROPSET(TELEPORT, can_teleport(mdat));
  3236.      PROPSET(TELEPORT_CONTROL, control_teleport(mdat));
  3237. @@ -95,7 +97,9 @@ set_uasmon()
  3238.      /* floating eye is the only 'floater'; it is also flagged as a 'flyer';
  3239.         suppress flying for it so that enlightenment doesn't confusingly
  3240.         show latent flight capability always blocked by levitation */
  3241. -    PROPSET(FLYING, (is_flyer(mdat) && !is_floater(mdat)));
  3242. +    /* this property also checks race instead of role */
  3243. +    PROPSET(FLYING, (is_flyer(racedat) && !is_floater(racedat)));
  3244. +    check_wings(TRUE);
  3245.      PROPSET(SWIMMING, is_swimmer(mdat));
  3246.      /* [don't touch MAGICAL_BREATHING here; both Amphibious and Breathless
  3247.         key off of it but include different monster forms...] */
  3248. diff --git c/src/potion.c i/src/potion.c
  3249. index c07d96cab..f7b2fe722 100644
  3250. --- c/src/potion.c
  3251. +++ i/src/potion.c
  3252. @@ -657,8 +657,9 @@ register struct obj *otmp;
  3253.              break;
  3254.          }
  3255.          g.potion_unkn++;
  3256. -        if (is_undead(g.youmonst.data) || is_demon(g.youmonst.data)
  3257. -            || u.ualign.type == A_CHAOTIC) {
  3258. +        if (is_undead(g.youmonst.data) || is_demon(raceptr(&g.youmonst))
  3259. +            || u.ualign.type <= A_CHAOTIC) {
  3260. +            int dice = (u.ualign.type == A_NONE) ? 4 : 2;
  3261.              if (otmp->blessed) {
  3262.                  pline("This burns like %s!", hliquid("acid"));
  3263.                  exercise(A_CON, FALSE);
  3264. @@ -669,11 +670,11 @@ register struct obj *otmp;
  3265.                          you_unwere(FALSE);
  3266.                      set_ulycn(NON_PM); /* cure lycanthropy */
  3267.                  }
  3268. -                losehp(Maybe_Half_Phys(d(2, 6)), "potion of holy water",
  3269. +                losehp(Maybe_Half_Phys(d(dice, 6)), "potion of holy water",
  3270.                         KILLED_BY_AN);
  3271.              } else if (otmp->cursed) {
  3272.                  You_feel("quite proud of yourself.");
  3273. -                healup(d(2, 6), 0, 0, 0);
  3274. +                healup(d(dice, 6), 0, 0, 0);
  3275.                  if (u.ulycn >= LOW_PM && !Upolyd)
  3276.                      you_were();
  3277.                  exercise(A_CON, TRUE);
  3278. diff --git c/src/pray.c i/src/pray.c
  3279. index e0f104601..220a194e4 100644
  3280. --- c/src/pray.c
  3281. +++ i/src/pray.c
  3282. @@ -12,8 +12,6 @@ static void FDECL(angrygods, (ALIGNTYP_P));
  3283.  static void FDECL(at_your_feet, (const char *));
  3284.  static void NDECL(gcrownu);
  3285.  static void FDECL(pleased, (ALIGNTYP_P));
  3286. -static void FDECL(godvoice, (ALIGNTYP_P, const char *));
  3287. -static void FDECL(god_zaps_you, (ALIGNTYP_P));
  3288.  static void FDECL(fry_by_god, (ALIGNTYP_P, BOOLEAN_P));
  3289.  static void FDECL(gods_angry, (ALIGNTYP_P));
  3290.  static void FDECL(gods_upset, (ALIGNTYP_P));
  3291. @@ -22,7 +20,8 @@ static boolean FDECL(water_prayer, (BOOLEAN_P));
  3292.  static boolean FDECL(blocked_boulder, (int, int));
  3293.  
  3294.  /* simplify a few tests */
  3295. -#define Cursed_obj(obj, typ) ((obj) && (obj)->otyp == (typ) && (obj)->cursed)
  3296. +#define Cursed_obj(obj, typ) ((obj) && (obj)->otyp == (typ) \
  3297. +                              && cursed(obj, TRUE))
  3298.  
  3299.  /*
  3300.   * Logic behind deities and altars and such:
  3301. @@ -216,10 +215,11 @@ in_trouble()
  3302.          if (welded(uwep))
  3303.              return TROUBLE_UNUSEABLE_HANDS;
  3304.          if (Upolyd && nohands(g.youmonst.data)
  3305. -            && (!Unchanging || ((otmp = unchanger()) != 0 && otmp->cursed)))
  3306. +            && (!Unchanging || ((otmp = unchanger()) != 0
  3307. +                                && cursed(otmp, TRUE))))
  3308.              return TROUBLE_UNUSEABLE_HANDS;
  3309.      }
  3310. -    if (Blindfolded && ublindf->cursed)
  3311. +    if (Blindfolded && cursed(ublindf, TRUE))
  3312.          return TROUBLE_CURSED_BLINDFOLD;
  3313.  
  3314.      /*
  3315. @@ -269,6 +269,14 @@ worst_cursed_item()
  3316.  {
  3317.      register struct obj *otmp;
  3318.  
  3319. +    /* Infidels are immune to curses, but a cursed luckstone is still bad */
  3320. +    if (Role_if(PM_INFIDEL)) {
  3321. +        for (otmp = g.invent; otmp; otmp = otmp->nobj)
  3322. +            if (confers_luck(otmp) && otmp->cursed)
  3323. +                return otmp;
  3324. +        return (struct obj *) 0;
  3325. +    }
  3326. +
  3327.      /* if strained or worse, check for loadstone first */
  3328.      if (near_capacity() >= HVY_ENCUMBER) {
  3329.          for (otmp = g.invent; otmp; otmp = otmp->nobj)
  3330. @@ -447,7 +455,7 @@ int trouble;
  3331.              if (!Unchanging) {
  3332.                  Your("shape becomes uncertain.");
  3333.                  rehumanize(); /* "You return to {normal} form." */
  3334. -            } else if ((otmp = unchanger()) != 0 && otmp->cursed) {
  3335. +            } else if ((otmp = unchanger()) != 0 && cursed(otmp, TRUE)) {
  3336.                  /* otmp is an amulet of unchanging */
  3337.                  goto decurse;
  3338.              }
  3339. @@ -492,7 +500,7 @@ int trouble;
  3340.          if (otmp == uarmg && Glib) {
  3341.              make_glib(0);
  3342.              Your("%s are no longer slippery.", gloves_simple_name(uarmg));
  3343. -            if (!otmp->cursed)
  3344. +            if (!cursed(otmp, TRUE))
  3345.                  break;
  3346.          }
  3347.          if (!Blind || (otmp == ublindf && Blindfolded_only)) {
  3348. @@ -573,7 +581,7 @@ int trouble;
  3349.   * bathroom walls, but who is foiled by bathrobes." --Bertrand Russell, 1943
  3350.   * Divine wrath, dungeon walls, and armor follow the same principle.
  3351.   */
  3352. -static void
  3353. +void
  3354.  god_zaps_you(resp_god)
  3355.  aligntyp resp_god;
  3356.  {
  3357. @@ -761,14 +769,18 @@ gcrownu()
  3358.      boolean already_exists, in_hand;
  3359.      short class_gift;
  3360.      int sp_no;
  3361. +    xchar maxint, maxwis;
  3362.  #define ok_wep(o) ((o) && ((o)->oclass == WEAPON_CLASS || is_weptool(o)))
  3363.  
  3364.      HSee_invisible |= FROMOUTSIDE;
  3365.      HFire_resistance |= FROMOUTSIDE;
  3366. -    HCold_resistance |= FROMOUTSIDE;
  3367. -    HShock_resistance |= FROMOUTSIDE;
  3368. -    HSleep_resistance |= FROMOUTSIDE;
  3369.      HPoison_resistance |= FROMOUTSIDE;
  3370. +    if (u.ualign.type != A_NONE) {
  3371. +        /* demons don't get all the intrinsics */
  3372. +        HCold_resistance |= FROMOUTSIDE;
  3373. +        HShock_resistance |= FROMOUTSIDE;
  3374. +        HSleep_resistance |= FROMOUTSIDE;
  3375. +    }
  3376.      godvoice(u.ualign.type, (char *) 0);
  3377.  
  3378.      class_gift = STRANGE_OBJECT;
  3379. @@ -809,6 +821,22 @@ gcrownu()
  3380.                     || class_gift != STRANGE_OBJECT) ? "take lives"
  3381.                    : "steal souls");
  3382.          break;
  3383. +    case A_NONE:
  3384. +        u.uevent.uhand_of_elbereth = 4;
  3385. +        verbalize("I grant thee the gift of Demonhood!");
  3386. +        class_gift = SPE_FIREBALL; /* no special weapon */
  3387. +        if (Upolyd)
  3388. +            rehumanize(); /* return to human/orcish form -- not a demon yet */
  3389. +        pline1("Wings sprout from your back and you grow a barbed tail!");
  3390. +        maxint = g.urace.attrmax[A_INT];
  3391. +        maxwis = g.urace.attrmax[A_WIS];
  3392. +        g.urace = race_demon;
  3393. +        /* mental faculties are not changed by demonization */
  3394. +        g.urace.attrmax[A_INT] = maxint;
  3395. +        g.urace.attrmax[A_WIS] = maxwis;
  3396. +        set_uasmon();
  3397. +        retouch_equipment(2); /* silver */
  3398. +        break;
  3399.      }
  3400.  
  3401.      if (objects[class_gift].oc_class == SPBOOK_CLASS) {
  3402. @@ -886,6 +914,9 @@ gcrownu()
  3403.              discover_artifact(ART_STORMBRINGER);
  3404.          break;
  3405.      }
  3406. +    case A_NONE:
  3407. +        /* nothing to do */
  3408. +        break;
  3409.      default:
  3410.          obj = 0; /* lint */
  3411.          break;
  3412. @@ -1125,6 +1156,8 @@ aligntyp g_align;
  3413.                  You("are surrounded by %s aura.", an(hcolor(NH_LIGHT_BLUE)));
  3414.              for (otmp = g.invent; otmp; otmp = otmp->nobj) {
  3415.                  if (otmp->cursed
  3416. +                    /* Inf benefit from wearing cursed armor */
  3417. +                    && !(Role_if(PM_INFIDEL) && (otmp->owornmask & W_ARMOR))
  3418.                      && (otmp != uarmh /* [see worst_cursed_item()] */
  3419.                          || uarmh->otyp != HELM_OF_OPPOSITE_ALIGNMENT)) {
  3420.                      if (!Blind) {
  3421. @@ -1260,7 +1293,7 @@ boolean bless_water;
  3422.      return (boolean) (changed > 0L);
  3423.  }
  3424.  
  3425. -static void
  3426. +void
  3427.  godvoice(g_align, words)
  3428.  aligntyp g_align;
  3429.  const char *words;
  3430. @@ -1362,6 +1395,9 @@ dosacrifice()
  3431.      if (otmp->otyp == CORPSE) {
  3432.          register struct permonst *ptr = &mons[otmp->corpsenm];
  3433.          struct monst *mtmp;
  3434. +        /* is this a conversion attempt? */
  3435. +        boolean to_other_god =  ugod_is_angry() && !your_race(ptr)
  3436. +                                && u.ualign.type != altaralign;
  3437.  
  3438.          /* KMH, conduct */
  3439.          u.uconduct.gnostic++;
  3440. @@ -1372,31 +1408,54 @@ dosacrifice()
  3441.          if (rider_corpse_revival(otmp, FALSE))
  3442.              return 1;
  3443.  
  3444. -        if (otmp->corpsenm == PM_ACID_BLOB
  3445. +        if (otmp->corpsenm == PM_ACID_BLOB || your_race(ptr)
  3446.              || (g.monstermoves <= peek_at_iced_corpse_age(otmp) + 50)) {
  3447.              value = mons[otmp->corpsenm].difficulty + 1;
  3448. +            if (is_undead(ptr) /* Not demons--no demon corpses */
  3449. +            /* most undead that leave a corpse yield 'human' (or other race)
  3450. +               corpse so won't get here; the exception is wraith; give the
  3451. +               bonus for wraith to chaotics too because they are sacrificing
  3452. +               something valuable (unless hero refuses to eat such things) */
  3453. +                && (u.ualign.type > A_CHAOTIC
  3454. +            /* reaching this side of the 'or'
  3455. +             * means hero is chaotic (or unaligned) */
  3456. +                    || (ptr == &mons[PM_WRAITH] && u.uconduct.unvegetarian)))
  3457. +                value += 1;
  3458. +            if (is_unicorn(ptr))
  3459. +                value += 3;
  3460. +            if (uwep && uwep->oartifact == ART_SECESPITA)
  3461. +                value += value / 2;
  3462.              if (otmp->oeaten)
  3463.                  value = eaten_stat(value, otmp);
  3464. +            /* even cross-aligned sacrifices will count,
  3465. +             * as long as they're ultimately to Moloch */
  3466. +            if (u.ualign.type == A_NONE && !to_other_god) {
  3467. +                long new_timeout = g.moves + value * 500;
  3468. +                if (g.context.next_moloch_offering < new_timeout)
  3469. +                    g.context.next_moloch_offering = new_timeout;
  3470. +            }
  3471.          }
  3472.  
  3473.          /* same race or former pet results apply even if the corpse is
  3474.             too old (value==0) */
  3475.          if (your_race(ptr)) {
  3476. -            if (is_demon(g.youmonst.data)) {
  3477. +            if (is_demon(raceptr(&g.youmonst))) {
  3478.                  You("find the idea very satisfying.");
  3479.                  exercise(A_WIS, TRUE);
  3480. -            } else if (u.ualign.type != A_CHAOTIC) {
  3481. +            } else if (u.ualign.type > A_CHAOTIC) {
  3482.                  pline("You'll regret this infamous offense!");
  3483.                  exercise(A_WIS, FALSE);
  3484.              }
  3485.  
  3486.              if (highaltar
  3487. -                && (altaralign != A_CHAOTIC || u.ualign.type != A_CHAOTIC)) {
  3488. +                && (altaralign != A_CHAOTIC || u.ualign.type != A_CHAOTIC)
  3489. +                && (altaralign != A_NONE || u.ualign.type != A_NONE)) {
  3490.                  goto desecrate_high_altar;
  3491.              } else if (altaralign != A_CHAOTIC && altaralign != A_NONE) {
  3492.                  /* curse the lawful/neutral altar */
  3493.                  pline_The("altar is stained with %s blood.", g.urace.adj);
  3494. -                levl[u.ux][u.uy].altarmask = AM_CHAOTIC;
  3495. +                levl[u.ux][u.uy].altarmask = u.ualign.type == A_NONE
  3496. +                                             ? AM_NONE : AM_CHAOTIC;
  3497.                  newsym(u.ux, u.uy); /* in case Invisible to self */
  3498.                  angry_priest();
  3499.              } else {
  3500. @@ -1417,7 +1476,7 @@ dosacrifice()
  3501.                  } else {
  3502.                      /* either you're chaotic or altar is Moloch's or both */
  3503.                      pline_The("blood covers the altar!");
  3504. -                    change_luck(altaralign == A_NONE ? -2 : 2);
  3505. +                    change_luck(altaralign == u.ualign.type ? 2 : -2);
  3506.                      demonless_msg = "blood coagulates";
  3507.                  }
  3508.                  if ((pm = dlord(altaralign)) != NON_PM
  3509. @@ -1441,7 +1500,7 @@ dosacrifice()
  3510.                      pline_The("%s.", demonless_msg);
  3511.              }
  3512.  
  3513. -            if (u.ualign.type != A_CHAOTIC) {
  3514. +            if (u.ualign.type > A_CHAOTIC) {
  3515.                  adjalign(-5);
  3516.                  u.ugangr += 3;
  3517.                  (void) adjattrib(A_WIS, -1, TRUE);
  3518. @@ -1457,7 +1516,10 @@ dosacrifice()
  3519.              return 1;
  3520.          } else if (has_omonst(otmp)
  3521.                     && (mtmp = get_mtraits(otmp, FALSE)) != 0
  3522. -                   && mtmp->mtame) {
  3523. +                   && mtmp->mtame
  3524. +                   /* Moloch is OK with sacrificing pets,
  3525. +                    * but make sure we're offering to him */
  3526. +                   && (u.ualign.type != A_NONE || to_other_god)) {
  3527.                  /* mtmp is a temporary pointer to a tame monster's attributes,
  3528.                   * not a real monster */
  3529.              pline("So this is how you repay loyalty?");
  3530. @@ -1465,16 +1527,7 @@ dosacrifice()
  3531.              value = -1;
  3532.              HAggravate_monster |= FROMOUTSIDE;
  3533.          } else if (!value) {
  3534. -            ; /* too old; don't give undead or unicorn bonus or penalty */
  3535. -        } else if (is_undead(ptr)) { /* Not demons--no demon corpses */
  3536. -            /* most undead that leave a corpse yield 'human' (or other race)
  3537. -               corpse so won't get here; the exception is wraith; give the
  3538. -               bonus for wraith to chaotics too because they are sacrificing
  3539. -               something valuable (unless hero refuses to eat such things) */
  3540. -            if (u.ualign.type != A_CHAOTIC
  3541. -                /* reaching this side of the 'or' means hero is chaotic */
  3542. -                || (ptr == &mons[PM_WRAITH] && u.uconduct.unvegetarian))
  3543. -                value += 1;
  3544. +            ; /* too old; don't give unicorn bonus or penalty */
  3545.          } else if (is_unicorn(ptr)) {
  3546.              int unicalign = sgn(ptr->maligntyp);
  3547.  
  3548. @@ -1495,7 +1548,7 @@ dosacrifice()
  3549.                  else
  3550.                      You_feel("you are thoroughly on the right path.");
  3551.                  adjalign(5);
  3552. -                value += 3;
  3553. +                /* value += 3; -- now applied above */
  3554.              } else if (unicalign == u.ualign.type) {
  3555.                  /* When sacrificing unicorn of your alignment to altar not of
  3556.                   * your alignment, your god gets angry and it's a conversion.
  3557. @@ -1507,7 +1560,7 @@ dosacrifice()
  3558.                   * and different from the altar's.  It's an ordinary (well,
  3559.                   * with a bonus) sacrifice on a cross-aligned altar.
  3560.                   */
  3561. -                value += 3;
  3562. +                /* value += 3; -- now applied above */
  3563.              }
  3564.          }
  3565.      } /* corpse */
  3566. @@ -1515,7 +1568,7 @@ dosacrifice()
  3567.      if (otmp->otyp == AMULET_OF_YENDOR) {
  3568.          if (!highaltar) {
  3569.   too_soon:
  3570. -            if (altaralign == A_NONE && Inhell)
  3571. +            if (altaralign == A_NONE && u.ualign.type != A_NONE && Inhell)
  3572.                  /* hero has left Moloch's Sanctum so is in the process
  3573.                     of getting away with the Amulet (outside of Gehennom,
  3574.                     fall through to the "ashamed" feedback) */
  3575. @@ -1526,7 +1579,9 @@ dosacrifice()
  3576.                              ? "homesick"
  3577.                              /* if on track, give a big hint */
  3578.                              : (altaralign == u.ualign.type)
  3579. -                               ? "an urge to return to the surface"
  3580. +                               ? (Role_if(PM_INFIDEL)
  3581. +                                  ? "an urge to descend deeper"
  3582. +                                  : "an urge to return to the surface")
  3583.                                 /* else headed towards celestial disgrace */
  3584.                                 : "ashamed");
  3585.              return 1;
  3586. @@ -1541,6 +1596,33 @@ dosacrifice()
  3587.              You("offer the Amulet of Yendor to %s...", a_gname());
  3588.              if (altaralign == A_NONE) {
  3589.                  /* Moloch's high altar */
  3590. +                if (Role_if(PM_INFIDEL)) {
  3591. +                    /* Infidels still have an ascension run,
  3592. +                     * they just carry a different McGuffin */
  3593. +                    u.uevent.ascended = 1; /* a misnomer in this case */
  3594. +                    record_achievement(ACH_AMUL);
  3595. +                    otmp = find_quest_artifact(1 << OBJ_INVENT);
  3596. +                    godvoice(A_NONE, (char *) 0);
  3597. +                    if (!otmp)
  3598. +                        qt_pager("moloch_missing");
  3599. +                    else {
  3600. +                        qt_pager("moloch");
  3601. +                        if (otmp->where == OBJ_CONTAINED) {
  3602. +                            /* the Idol cannot be contained now,
  3603. +                             * so we have to remove it */
  3604. +                            obj_extract_self(otmp);
  3605. +                            (void) hold_another_object(otmp, "Oops!",
  3606. +                                                       (const char *) 0,
  3607. +                                                       (const char *) 0);
  3608. +                        }
  3609. +                        You_feel("strange energies envelop %s.",
  3610. +                                 the(xname(otmp)));
  3611. +                        otmp->spe = 1;
  3612. +                        if (otmp->where == OBJ_INVENT)
  3613. +                            u.uhave.amulet = 1;
  3614. +                    }
  3615. +                    return 1;
  3616. +                }
  3617.                  if (u.ualign.record > -99)
  3618.                      u.ualign.record = -99;
  3619.                  pline(
  3620. @@ -1600,8 +1682,10 @@ dosacrifice()
  3621.              if (Deaf)
  3622.                  pline("Oh, no."); /* didn't hear thunderclap */
  3623.              change_luck(-3);
  3624. -            adjalign(-1);
  3625. -            u.ugangr += 3;
  3626. +            if (u.ualign.type != A_NONE) {
  3627. +                adjalign(-1);
  3628. +                u.ugangr += 3;
  3629. +            }
  3630.              value = -3;
  3631.          }
  3632.      } /* fake Amulet */
  3633. @@ -1634,9 +1718,10 @@ dosacrifice()
  3634.          if (u.ualign.type != altaralign) {
  3635.              /* Is this a conversion ? */
  3636.              /* An unaligned altar in Gehennom will always elicit rejection. */
  3637. +            /* Infidels will also never be accepted. */
  3638.              if (ugod_is_angry() || (altaralign == A_NONE && Inhell)) {
  3639.                  if (u.ualignbase[A_CURRENT] == u.ualignbase[A_ORIGINAL]
  3640. -                    && altaralign != A_NONE) {
  3641. +                    && altaralign != A_NONE && !Role_if(PM_INFIDEL)) {
  3642.                      You("have a strong feeling that %s is angry...",
  3643.                          u_gname());
  3644.                      consume_offering(otmp);
  3645. @@ -1661,7 +1746,11 @@ dosacrifice()
  3646.                  consume_offering(otmp);
  3647.                  You("sense a conflict between %s and %s.", u_gname(),
  3648.                      a_gname());
  3649. -                if (rn2(8 + u.ulevel) > 5) {
  3650. +                if (rn2(8 + u.ulevel) > 5
  3651. +                    /* Infidels have difficulty converting altars. */
  3652. +                    && !(u.ualign.type == A_NONE
  3653. +                         && !(Role_if(PM_INFIDEL) && u.uhave.questart)
  3654. +                         && depth(&u.uz) < depth(&valley_level) && rn2(5))) {
  3655.                      struct monst *pri;
  3656.                      boolean shrine;
  3657.  
  3658. @@ -1677,9 +1766,11 @@ dosacrifice()
  3659.                          pline_The("altar glows %s.",
  3660.                                    hcolor((u.ualign.type == A_LAWFUL)
  3661.                                              ? NH_WHITE
  3662. -                                            : u.ualign.type
  3663. -                                               ? NH_BLACK
  3664. -                                               : (const char *) "gray"));
  3665. +                                            : u.ualign.type == A_NONE
  3666. +                                                ? NH_RED
  3667. +                                                : u.ualign.type
  3668. +                                                    ? NH_BLACK
  3669. +                                                    : (const char *) "gray"));
  3670.  
  3671.                      if (rnl(u.ulevel) > 6 && u.ualign.record > 0
  3672.                          && rnd(u.ualign.record) > (3 * ALIGNLIM) / 4)
  3673. @@ -1704,8 +1795,9 @@ dosacrifice()
  3674.          consume_offering(otmp);
  3675.          /* OK, you get brownie points. */
  3676.          if (u.ugangr) {
  3677. -            u.ugangr -= ((value * (u.ualign.type == A_CHAOTIC ? 2 : 3))
  3678. -                         / MAXVALUE);
  3679. +            u.ugangr -= ((value * (u.ualign.type == A_NONE ? 3
  3680. +                                   : u.ualign.type == A_CHAOTIC ? 4 : 6))
  3681. +                         / (MAXVALUE * 2));
  3682.              if (u.ugangr < 0)
  3683.                  u.ugangr = 0;
  3684.              if (u.ugangr != saved_anger) {
  3685. @@ -1737,7 +1829,7 @@ dosacrifice()
  3686.              adjalign(value);
  3687.              You_feel("partially absolved.");
  3688.          } else if (u.ublesscnt > 0) {
  3689. -            u.ublesscnt -= ((value * (u.ualign.type == A_CHAOTIC ? 500 : 300))
  3690. +            u.ublesscnt -= ((value * (u.ualign.type <= A_CHAOTIC ? 500 : 300))
  3691.                              / MAXVALUE);
  3692.              if (u.ublesscnt < 0)
  3693.                  u.ublesscnt = 0;
  3694. @@ -1817,8 +1909,8 @@ boolean praying; /* false means no messages should be given */
  3695.      g.p_aligntyp = on_altar() ? a_align(u.ux, u.uy) : u.ualign.type;
  3696.      g.p_trouble = in_trouble();
  3697.  
  3698. -    if (is_demon(g.youmonst.data) /* ok if chaotic or none (Moloch) */
  3699. -        && (g.p_aligntyp == A_LAWFUL || g.p_aligntyp != A_NEUTRAL)) {
  3700. +    if (is_demon(raceptr(&g.youmonst)) /* ok if chaotic or none (Moloch) */
  3701. +        && (g.p_aligntyp == A_LAWFUL || g.p_aligntyp == A_NEUTRAL)) {
  3702.          if (praying)
  3703.              pline_The("very idea of praying to a %s god is repugnant to you.",
  3704.                        g.p_aligntyp ? "lawful" : "neutral");
  3705. @@ -1835,7 +1927,8 @@ boolean praying; /* false means no messages should be given */
  3706.      else
  3707.          alignment = u.ualign.record;
  3708.  
  3709. -    if (g.p_aligntyp == A_NONE) /* praying to Moloch */
  3710. +    if (g.p_aligntyp == A_NONE && u.ualign.type != A_NONE)
  3711. +        /* praying to Moloch */
  3712.          g.p_type = -2;
  3713.      else if ((g.p_trouble > 0) ? (u.ublesscnt > 200) /* big trouble */
  3714.               : (g.p_trouble < 0) ? (u.ublesscnt > 100) /* minor difficulties */
  3715. @@ -1851,14 +1944,15 @@ boolean praying; /* false means no messages should be given */
  3716.      }
  3717.  
  3718.      if (is_undead(g.youmonst.data) && !Inhell
  3719. -        && (g.p_aligntyp == A_LAWFUL
  3720. -            || (g.p_aligntyp == A_NEUTRAL && !rn2(10))))
  3721. +        && (g.p_aligntyp == A_LAWFUL || (g.p_aligntyp == A_NEUTRAL && praying
  3722. +                                         && !rn2(10))))
  3723.          g.p_type = -1;
  3724. -    /* Note:  when !praying, the random factor for neutrals makes the
  3725. -       return value a non-deterministic approximation for enlightenment.
  3726. -       This case should be uncommon enough to live with... */
  3727. +    if (g.p_aligntyp == A_NONE && !on_altar()
  3728. +        && depth(&u.uz) < depth(&valley_level)
  3729. +        && !(Role_if(PM_INFIDEL) && u.uhave.questart) && praying && rn2(5))
  3730. +        g.p_type = -3; /* Moloch can't hear you */
  3731.  
  3732. -    return !praying ? (boolean) (g.p_type == 3 && !Inhell) : TRUE;
  3733. +    return praying || g.p_type == 3 && (!Inhell || u.ualign.type == A_NONE);
  3734.  }
  3735.  
  3736.  /* #pray commmand */
  3737. @@ -1892,7 +1986,7 @@ dopray()
  3738.      g.nomovemsg = "You finish your prayer.";
  3739.      g.afternmv = prayer_done;
  3740.  
  3741. -    if (g.p_type == 3 && !Inhell) {
  3742. +    if (g.p_type == 3 && (!Inhell || u.ualign.type == A_NONE)) {
  3743.          /* if you've been true to your god you can't die while you pray */
  3744.          if (!Blind)
  3745.              You("are surrounded by a shimmering light.");
  3746. @@ -1934,7 +2028,13 @@ prayer_done() /* M. Stephenson (1.0.3b) */
  3747.          exercise(A_CON, FALSE);
  3748.          return 1;
  3749.      }
  3750. -    if (Inhell) {
  3751. +    if (g.p_type == -3) {
  3752. +        pline("Unfortunately, this close to the surface %s can't hear you.",
  3753. +              align_gname(alignment));
  3754. +        /* no further effects */
  3755. +        return 0;
  3756. +    }
  3757. +    if (Inhell && u.ualign.type != A_NONE) {
  3758.          pline("Since you are in Gehennom, %s can't help you.",
  3759.                align_gname(alignment));
  3760.          /* haltingly aligned is least likely to anger */
  3761. @@ -2012,7 +2112,7 @@ doturn()
  3762.          return (u.uconduct.gnostic == 1);
  3763.      }
  3764.      if ((u.ualign.type != A_CHAOTIC
  3765. -         && (is_demon(g.youmonst.data)
  3766. +         && (is_demon(raceptr(&g.youmonst))
  3767.               || is_undead(g.youmonst.data) || is_vampshifter(&g.youmonst)))
  3768.          || u.ugangr > 6) { /* "Die, mortal!" */
  3769.          pline("For some reason, %s seems to ignore you.", Gname);
  3770. @@ -2265,6 +2365,9 @@ aligntyp alignment;
  3771.      const char *gnam, *result = "god";
  3772.  
  3773.      switch (alignment) {
  3774. +    case A_NONE:
  3775. +        gnam = Moloch;
  3776. +        break;
  3777.      case A_LAWFUL:
  3778.          gnam = g.urole.lgod;
  3779.          break;
  3780. @@ -2283,6 +2386,23 @@ aligntyp alignment;
  3781.      return result;
  3782.  }
  3783.  
  3784. +/* return an alignment from a (lawful, neutral, chaotic) permutation
  3785. + * randomly chosen at game start; only relevant to Infidels */
  3786. +aligntyp
  3787. +inf_align(num)
  3788. +int num; /* 1..3 */
  3789. +{
  3790. +    aligntyp first, other;
  3791. +    first = g.context.inf_aligns % 3 - 1;
  3792. +    if (num == 1)
  3793. +        return first;
  3794. +    other = (g.context.inf_aligns + num) % 2;
  3795. +    if (other <= first)
  3796. +        other--;
  3797. +    return other;
  3798. +
  3799. +}
  3800. +
  3801.  void
  3802.  altar_wrath(x, y)
  3803.  register int x, y;
  3804. diff --git c/src/priest.c i/src/priest.c
  3805. index 1b5bd3824..5596c9073 100644
  3806. --- c/src/priest.c
  3807. +++ i/src/priest.c
  3808. @@ -263,7 +263,7 @@ boolean sanctum; /* is it the seat of the high priest? */
  3809.  
  3810.          /* now his/her goodies... */
  3811.          if (sanctum && EPRI(priest)->shralign == A_NONE
  3812. -            && on_level(&sanctum_level, &u.uz)) {
  3813. +            && on_level(&sanctum_level, &u.uz) && !Role_if(PM_INFIDEL)) {
  3814.              (void) mongets(priest, AMULET_OF_YENDOR);
  3815.          }
  3816.          /* 2 to 4 spellbooks */
  3817. @@ -401,7 +401,7 @@ int roomno;
  3818.  {
  3819.      struct monst *priest, *mtmp;
  3820.      struct epri *epri_p;
  3821. -    boolean shrined, sanctum, can_speak;
  3822. +    boolean shrined, sanctum, can_speak, call_guards;
  3823.      long *this_time, *other_time;
  3824.      const char *msg1, *msg2;
  3825.      char buf[BUFSZ];
  3826. @@ -419,6 +419,7 @@ int roomno;
  3827.          sanctum = (priest->data == &mons[PM_HIGH_PRIEST]
  3828.                     && (Is_sanctum(&u.uz) || In_endgame(&u.uz)));
  3829.          can_speak = (priest->mcanmove && !priest->msleeping);
  3830. +        call_guards = FALSE;
  3831.          if (can_speak && !Deaf && g.moves >= epri_p->intone_time) {
  3832.              unsigned save_priest = priest->ispriest;
  3833.  
  3834. @@ -436,11 +437,20 @@ int roomno;
  3835.              epri_p->enter_time = 0L;
  3836.          }
  3837.          msg1 = msg2 = 0;
  3838. -        if (sanctum && Is_sanctum(&u.uz)) {
  3839. +        if ((sanctum && Is_sanctum(&u.uz) || u.ualign.type == A_NONE)
  3840. +            && !p_coaligned(priest)) {
  3841. +            /* either a non-Infidel in the Sanctum, or an Infidel in any
  3842. +             * non-Moloch temple; either way, the priest is not happy */
  3843.              if (priest->mpeaceful) {
  3844.                  /* first time inside */
  3845. -                msg1 = "Infidel, you have entered Moloch's Sanctum!";
  3846. -                msg2 = "Be gone!";
  3847. +                if (u.ualign.type == A_NONE) {
  3848. +                    msg1 = "Begone, infidel!";
  3849. +                    msg2 = "This place is barred for your cult!";
  3850. +                    call_guards = in_town(priest->mx, priest->my);
  3851. +                } else {
  3852. +                    msg1 = "Infidel, you have entered Moloch's Sanctum!";
  3853. +                    msg2 = "Be gone!";
  3854. +                }
  3855.                  priest->mpeaceful = 0;
  3856.                  /* became angry voluntarily; no penalty for attacking him */
  3857.                  set_malign(priest);
  3858. @@ -459,6 +469,11 @@ int roomno;
  3859.                  verbalize1(msg2);
  3860.              epri_p->enter_time = g.moves + (long) d(10, 100); /* ~505 */
  3861.          }
  3862. +        /* for Infidels, visiting the Minetown temple is a very bad idea */
  3863. +        if (call_guards) {
  3864. +            pline("%s calls for guards!", Monnam(priest));
  3865. +            (void) angry_guards(FALSE);
  3866. +        }
  3867.          if (!sanctum) {
  3868.              if (!shrined || !p_coaligned(priest)
  3869.                  || u.ualign.record <= ALGN_SINNED) {
  3870. @@ -560,7 +575,8 @@ register struct monst *priest;
  3871.  
  3872.      /* priests don't chat unless peaceful and in their own temple */
  3873.      if (!inhistemple(priest) || !priest->mpeaceful
  3874. -        || !priest->mcanmove || priest->msleeping) {
  3875. +        || !priest->mcanmove || priest->msleeping
  3876. +        || u.ualign.type == A_NONE && !coaligned) {
  3877.          static const char *cranky_msg[3] = {
  3878.              "Thou wouldst have words, eh?  I'll give thee a word or two!",
  3879.              "Talk?  Here is what I have to say!",
  3880. @@ -587,7 +603,19 @@ register struct monst *priest;
  3881.          return;
  3882.      }
  3883.      if (!money_cnt(g.invent)) {
  3884. -        if (coaligned && !strayed) {
  3885. +        if (Role_if(PM_INFIDEL) && u.uevent.ascended
  3886. +            && priest->data == &mons[PM_HIGH_PRIEST] && Is_sanctum(&u.uz)) {
  3887. +            /* give a hint about the correct high altar */
  3888. +            aligntyp saved_align = u.ualignbase[A_ORIGINAL];
  3889. +            uchar saved_godgend = g.quest_status.godgend;
  3890. +            /* a hack for displaying a different god's name in the message */
  3891. +            u.ualignbase[A_ORIGINAL] = inf_align(3);
  3892. +            /* "god"[3] == 0; "goddess"[3] != 0 */
  3893. +            g.quest_status.godgend = !!align_gtitle(inf_align(3))[3];
  3894. +            qt_pager("high_priest");
  3895. +            u.ualignbase[A_ORIGINAL] = saved_align;
  3896. +            g.quest_status.godgend = saved_godgend;
  3897. +        } else if (coaligned && !strayed) {
  3898.              long pmoney = money_cnt(priest->minvent);
  3899.              if (pmoney > 0L) {
  3900.                  const char *bits;
  3901. diff --git c/src/quest.c i/src/quest.c
  3902. index a74cdf41b..7ae442b3c 100644
  3903. --- c/src/quest.c
  3904. +++ i/src/quest.c
  3905. @@ -218,8 +218,21 @@ finish_quest(obj)
  3906.  struct obj *obj; /* quest artifact; possibly null if carrying Amulet */
  3907.  {
  3908.      struct obj *otmp;
  3909. +    aligntyp saved_align;
  3910. +    uchar saved_godgend;
  3911.  
  3912. -    if (u.uhave.amulet) { /* unlikely but not impossible */
  3913. +    if (Role_if(PM_INFIDEL) && u.uevent.ascended) {
  3914. +        saved_align = u.ualignbase[A_ORIGINAL];
  3915. +        saved_godgend = g.quest_status.godgend;
  3916. +        /* a hack for displaying a different god's name in the message */
  3917. +        u.ualignbase[A_ORIGINAL] = inf_align(2);
  3918. +        /* "god"[3] == 0; "goddess"[3] != 0 */
  3919. +        g.quest_status.godgend = !!align_gtitle(inf_align(2))[3];
  3920. +        qt_pager("delivered_amulet");
  3921. +        u.ualignbase[A_ORIGINAL] = saved_align;
  3922. +        g.quest_status.godgend = saved_godgend;
  3923. +    } else if (u.uhave.amulet && !Role_if(PM_INFIDEL)) {
  3924. +        /* unlikely but not impossible */
  3925.          qt_pager("hasamulet");
  3926.          /* leader IDs the real amulet but ignores any fakes */
  3927.          if ((otmp = carrying(AMULET_OF_YENDOR)) != 0)
  3928. @@ -229,7 +242,7 @@ struct obj *obj; /* quest artifact; possibly null if carrying Amulet */
  3929.          /* should have obtained bell during quest;
  3930.             if not, suggest returning for it now */
  3931.          if ((otmp = carrying(BELL_OF_OPENING)) == 0)
  3932. -            com_pager("quest_complete_no_bell");
  3933. +            qt_pager("quest_complete_no_bell");
  3934.      }
  3935.      Qstat(got_thanks) = TRUE;
  3936.  
  3937. @@ -254,7 +267,7 @@ chat_with_leader()
  3938.       */
  3939.      if (Qstat(got_thanks)) {
  3940.          /* Rule 1: You've gone back with/without the amulet. */
  3941. -        if (u.uhave.amulet)
  3942. +        if (Role_if(PM_INFIDEL) ? u.uevent.ascended : u.uhave.amulet)
  3943.              finish_quest((struct obj *) 0);
  3944.  
  3945.          /* Rule 2: You've gone back before going for the amulet. */
  3946. diff --git c/src/read.c i/src/read.c
  3947. index 353f9bac2..9f3505528 100644
  3948. --- c/src/read.c
  3949. +++ i/src/read.c
  3950. @@ -950,6 +950,7 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
  3951.                  uncurse(otmp);
  3952.              otmp->known = 1;
  3953.              setworn(otmp, W_ARM);
  3954. +            check_wings(TRUE);
  3955.              if (otmp->unpaid)
  3956.                  alter_cost(otmp, 0L); /* shop bill */
  3957.              break;
  3958. @@ -2015,7 +2016,9 @@ do_class_genocide()
  3959.                          /* non-leader/nemesis/guardian role-specific monster
  3960.                             */
  3961.                          && (i != PM_NINJA /* nuisance */
  3962. -                            || Role_if(PM_SAMURAI))) {
  3963. +                            || Role_if(PM_SAMURAI))
  3964. +                        && (i != PM_TEMPLAR && i != PM_CHAMPION
  3965. +                            && i != PM_AGENT || Role_if(PM_INFIDEL))) {
  3966.                          boolean named, uniq;
  3967.  
  3968.                          named = type_is_pname(&mons[i]) ? TRUE : FALSE;
  3969. diff --git c/src/restore.c i/src/restore.c
  3970. index 2f9191255..789dbc147 100644
  3971. --- c/src/restore.c
  3972. +++ i/src/restore.c
  3973. @@ -614,13 +614,13 @@ unsigned int *stuckid, *steedid;
  3974.          mread(nhfp->fd, (genericptr_t) &sysflags, sizeof(struct sysflag));
  3975.  #endif
  3976.  
  3977. -    role_init(); /* Reset the initial role, race, gender, and alignment */
  3978.  #ifdef AMII_GRAPHICS
  3979.      amii_setpens(amii_numcolors); /* use colors from save file */
  3980.  #endif
  3981.      if (nhfp->structlevel)
  3982.          mread(nhfp->fd, (genericptr_t) &u, sizeof(struct you));
  3983.      g.youmonst.cham = u.mcham;
  3984. +    role_init(); /* Reset the initial role, race, gender, and alignment */
  3985.          
  3986.      if (nhfp->structlevel)
  3987.          mread(nhfp->fd, (genericptr_t) timebuf, 14);
  3988. diff --git c/src/role.c i/src/role.c
  3989. index a31700369..0e6b32928 100644
  3990. --- c/src/role.c
  3991. +++ i/src/role.c
  3992. @@ -192,6 +192,47 @@ const struct Role roles[NUM_ROLES+1] = {
  3993.        A_WIS,
  3994.        SPE_CURE_SICKNESS,
  3995.        -4 },
  3996. +    { { "Infidel", 0 },
  3997. +      { { "Apostate", 0 },
  3998. +        { "Heathen", 0 },
  3999. +        { "Heretic", 0 },
  4000. +        { "Idolater", "Idolatress" },
  4001. +        { "Cultist", 0 },
  4002. +        { "Splanchomancer", 0 },
  4003. +        { "Maleficus", "Malefica" },
  4004. +        { "Demonologist", 0 },
  4005. +        { "Heresiarch", 0 } },
  4006. +      0, 0, 0, /* uses a random role's pantheon */
  4007. +      "Inf",
  4008. +      "the Hidden Temple",
  4009. +      "the Howling Forest",
  4010. +      PM_INFIDEL,
  4011. +      NON_PM,
  4012. +      PM_HOMUNCULUS,
  4013. +      PM_PREACHER_OF_MOLOCH,
  4014. +      PM_CULTIST,
  4015. +      PM_PALADIN,
  4016. +      PM_AGENT,
  4017. +      PM_CHAMPION,
  4018. +      S_DOG,
  4019. +      S_UNICORN,
  4020. +      ART_IDOL_OF_MOLOCH,                         /* actually unaligned */
  4021. +      MH_HUMAN | MH_ORC | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
  4022. +      /* Str Int Wis Dex Con Cha */
  4023. +      { 7, 7, 10, 7, 7, 7 },
  4024. +      { 20, 10, 25, 15, 20, 10 },
  4025. +      /* Init   Lower  Higher */
  4026. +      { 10, 0, 0, 8, 1, 0 }, /* Hit points */
  4027. +      { 4, 3, 0, 1, 0, 2 },
  4028. +      10, /* Energy */
  4029. +      10,
  4030. +      3,
  4031. +      1,
  4032. +      2,
  4033. +      10,
  4034. +      A_WIS,
  4035. +      SPE_FIREBALL,
  4036. +      -4 },
  4037.      { { "Knight", 0 },
  4038.        { { "Gallant", 0 },
  4039.          { "Esquire", 0 },
  4040. @@ -697,6 +738,29 @@ const struct Race races[] = {
  4041.      { 0, 0, 0, 0 }
  4042.  };
  4043.  
  4044. +/* Special race for crowned Infidels. */
  4045. +struct Race race_demon = {
  4046. +    "demon",
  4047. +    "demonic",
  4048. +    "demonkind",
  4049. +    "Dem",
  4050. +    { 0, 0 },
  4051. +    PM_DEMON,
  4052. +    NON_PM,
  4053. +    NON_PM,
  4054. +    NON_PM,
  4055. +    MH_DEMON | ROLE_MALE | ROLE_FEMALE, /* not available at start */
  4056. +    MH_DEMON,
  4057. +    MH_DEMON,
  4058. +    MH_HUMAN | MH_ELF | MH_DWARF | MH_GNOME,
  4059. +    /*  Str    Int Wis Dex Con Cha */
  4060. +    { 3, 3, 3, 3, 3, 3 },
  4061. +    { STR18(100), 18, 18, 20, 20, 18 }, /* max Int & Wis are variable */
  4062. +    /* Init   Lower  Higher */
  4063. +    { 8, 0, 0, 8, 4, 0 }, /* Hit points */
  4064. +    { 4, 0, 6, 0, 6, 0 }  /* Energy */
  4065. +};
  4066. +
  4067.  /* Table of all genders */
  4068.  const struct Gender genders[] = {
  4069.      { "male", "he", "him", "his", "Mal", ROLE_MALE },
  4070. @@ -722,6 +786,16 @@ static int FDECL(race_alignmentcount, (int));
  4071.  /* used by str2XXX() */
  4072.  static char NEARDATA randomstr[] = "random";
  4073.  
  4074. +/* Inf are listed as chaotic above, but actually are unaligned. */
  4075. +int
  4076. +special_alignment(rolenum, alignnum)
  4077. +int rolenum, alignnum;
  4078. +{
  4079. +    if (roles[rolenum].malenum == PM_INFIDEL)
  4080. +        return 3; /* aligns[unaligned] */
  4081. +    return alignnum;
  4082. +}
  4083. +
  4084.  boolean
  4085.  validrole(rolenum)
  4086.  int rolenum;
  4087. @@ -1438,12 +1512,12 @@ int buflen, rolenum, racenum, gendnum, alignnum;
  4088.          if ((racenum >= 0) && (aligncount > 1)) {
  4089.              if (donefirst)
  4090.                  Strcat(buf, " ");
  4091. -            Strcat(buf, aligns[alignnum].adj);
  4092. +            Strcat(buf, aligns[special_alignment(rolenum, alignnum)].adj);
  4093.              donefirst = TRUE;
  4094.          } else {
  4095.              if (donefirst)
  4096.                  Strcat(buf, " ");
  4097. -            Strcat(buf, aligns[alignnum].adj);
  4098. +            Strcat(buf, aligns[special_alignment(rolenum, alignnum)].adj);
  4099.              donefirst = TRUE;
  4100.          }
  4101.      } else {
  4102. @@ -1737,6 +1811,7 @@ winid where;
  4103.              a = 2; /* alings[chaotic] */
  4104.          /* [c never forces gender] */
  4105.      }
  4106. +    a = special_alignment(r, a); /* special case (Infidel) */
  4107.      /* [g and a don't constrain anything sufficiently
  4108.         to narrow something done to a single choice] */
  4109.  
  4110. @@ -1873,6 +1948,7 @@ boolean preselect;
  4111.                  a = 1; /* aligns[neutral] */
  4112.              else if (allowmask == AM_CHAOTIC)
  4113.                  a = 2; /* aligns[chaotic] */
  4114. +            a = special_alignment(r, a); /* special case (Infidel) */
  4115.              if (a >= 0)
  4116.                  constrainer = "role";
  4117.          }
  4118. @@ -1952,7 +2028,7 @@ boolean preselect;
  4119.  void
  4120.  role_init()
  4121.  {
  4122. -    int alignmnt;
  4123. +    int alignmnt, malignmnt;
  4124.      struct permonst *pm;
  4125.  
  4126.      /* Strip the role letter out of the player name.
  4127. @@ -1991,11 +2067,21 @@ role_init()
  4128.      if (!validalign(flags.initrole, flags.initrace, flags.initalign))
  4129.          /* Pick a random alignment */
  4130.          flags.initalign = randalign(flags.initrole, flags.initrace);
  4131. -    alignmnt = aligns[flags.initalign].value;
  4132. +    /* Infidels are actually unaligned */
  4133. +    flags.initalign = special_alignment(flags.initrole, flags.initalign);
  4134. +    alignmnt = malignmnt = aligns[flags.initalign].value;
  4135. +    if (alignmnt != A_NONE)
  4136. +        malignmnt *= 3;
  4137.  
  4138.      /* Initialize g.urole and g.urace */
  4139.      g.urole = roles[flags.initrole];
  4140. -    g.urace = races[flags.initrace];
  4141. +    if (u.uevent.uhand_of_elbereth == 4) { /* crowned as a demon */
  4142. +        g.urace = race_demon;
  4143. +        /* mental faculties are not changed by demonization */
  4144. +        g.urace.attrmax[A_INT] = races[flags.initrace].attrmax[A_INT];
  4145. +        g.urace.attrmax[A_WIS] = races[flags.initrace].attrmax[A_WIS];
  4146. +    } else
  4147. +        g.urace = races[flags.initrace];
  4148.  
  4149.      /* Fix up the quest leader */
  4150.      if (g.urole.ldrnum != NON_PM) {
  4151. @@ -2003,7 +2089,7 @@ role_init()
  4152.          pm->msound = MS_LEADER;
  4153.          pm->mflags2 |= (M2_PEACEFUL);
  4154.          pm->mflags3 |= M3_CLOSE;
  4155. -        pm->maligntyp = alignmnt * 3;
  4156. +        pm->maligntyp = malignmnt;
  4157.          /* if gender is random, we choose it now instead of waiting
  4158.             until the leader monster is created */
  4159.          g.quest_status.ldrgend =
  4160. @@ -2016,7 +2102,7 @@ role_init()
  4161.      if (g.urole.guardnum != NON_PM) {
  4162.          pm = &mons[g.urole.guardnum];
  4163.          pm->mflags2 |= (M2_PEACEFUL);
  4164. -        pm->maligntyp = alignmnt * 3;
  4165. +        pm->maligntyp = malignmnt;
  4166.      }
  4167.  
  4168.      /* Fix up the quest nemesis */
  4169. @@ -2033,6 +2119,14 @@ role_init()
  4170.                                     : is_male(pm) ? 0 : (rn2(100) < 50);
  4171.      }
  4172.  
  4173. +    /* Enable special Inf enemies */
  4174. +    if (Role_if(PM_INFIDEL)) {
  4175. +        if (g.urole.enemy1num != NON_PM)
  4176. +            mons[g.urole.enemy1num].geno &= ~G_NOGEN;
  4177. +        if (g.urole.enemy2num != NON_PM)
  4178. +            mons[g.urole.enemy2num].geno &= ~G_NOGEN;
  4179. +    }
  4180. +
  4181.      /* Fix up the god names */
  4182.      if (flags.pantheon == -1) {             /* new game */
  4183.          int trycnt = 0;
  4184. diff --git c/src/shk.c i/src/shk.c
  4185. index bd91495d4..45abf9bc0 100644
  4186. --- c/src/shk.c
  4187. +++ i/src/shk.c
  4188. @@ -4764,7 +4764,7 @@ boolean altusage; /* used as a verbalized exclamation:  \"Cad! ...\" */
  4189.  {
  4190.      const char *res = 0;
  4191.  
  4192. -    switch (is_demon(g.youmonst.data) ? 3 : poly_gender()) {
  4193. +    switch (is_demon(raceptr(&g.youmonst)) ? 3 : poly_gender()) {
  4194.      case 0:
  4195.          res = "cad";
  4196.          break;
  4197. diff --git c/src/sounds.c i/src/sounds.c
  4198. index 28c3369fd..624513767 100644
  4199. --- c/src/sounds.c
  4200. +++ i/src/sounds.c
  4201. @@ -1154,7 +1154,7 @@ tiphat()
  4202.          return 0;
  4203.  
  4204.      res = uarmh->bknown ? 0 : 1;
  4205. -    if (cursed(uarmh)) /* "You can't.  It is cursed." */
  4206. +    if (cursed(uarmh, FALSE)) /* "You can't.  It is cursed." */
  4207.          return res; /* if learned of curse, use a move */
  4208.  
  4209.      /* might choose a position, but dealing with direct lines is simpler */
  4210. diff --git c/src/sp_lev.c i/src/sp_lev.c
  4211. old mode 100755
  4212. new mode 100644
  4213. index b85c4ab75..494554b9c
  4214. --- c/src/sp_lev.c
  4215. +++ i/src/sp_lev.c
  4216. @@ -1802,6 +1802,8 @@ aligntyp alignment;
  4217.  {
  4218.      int k;
  4219.  
  4220. +    if (alignment == A_NONE)
  4221. +        return rn1(3, -1);
  4222.      k = rn2(2);
  4223.      if (!alignment)
  4224.          return (k ? -1 : 1);
  4225. diff --git c/src/spell.c i/src/spell.c
  4226. index ebf2f5d7d..89fc6f3e1 100644
  4227. --- c/src/spell.c
  4228. +++ i/src/spell.c
  4229. @@ -54,6 +54,7 @@ static boolean FDECL(spell_aim_step, (genericptr_t, int, int));
  4230.   *      Bar abhor magic (Conan finds it "interferes with his animal instincts")
  4231.   *      Cav are ignorant to magic
  4232.   *      Hea are very aware of healing magic through medical research
  4233. + *      Inf learned a lot of black magic from their cult
  4234.   *      Kni are moderately aware of healing from Paladin training
  4235.   *      Mon use magic to attack and defend in lieu of weapons and armor
  4236.   *      Pri are very aware of healing magic through theological research
  4237. @@ -74,6 +75,7 @@ static boolean FDECL(spell_aim_step, (genericptr_t, int, int));
  4238.   *      Bar fugue/berserker (SPE_HASTE_SELF)
  4239.   *      Cav born to dig (SPE_DIG)
  4240.   *      Hea to heal (SPE_CURE_SICKNESS)
  4241. + *      Inf to channel hellfire (SPE_FIREBALL)
  4242.   *      Kni to turn back evil (SPE_TURN_UNDEAD)
  4243.   *      Mon to preserve their abilities (SPE_RESTORE_ABILITY)
  4244.   *      Pri to bless (SPE_REMOVE_CURSE)
  4245. @@ -1740,6 +1742,25 @@ int spell;
  4246.      if (uarmf && is_metallic(uarmf))
  4247.          splcaster += uarmfbon;
  4248.  
  4249. +    /* Infidels have a special penalty for wearing blessed armor. */
  4250. +    if (Role_if(PM_INFIDEL)) {
  4251. +        static struct obj **const armor[] = { &uarm, &uarmc, &uarmh, &uarms,
  4252. +                                              &uarmg, &uarmf, &uarmu };
  4253. +        int penalty = 0;
  4254. +        int i;
  4255. +
  4256. +        for (i = 0; i < SIZE(armor); i++) {
  4257. +            if (!*armor[i])
  4258. +                continue;
  4259. +            if ((*armor[i])->blessed)
  4260. +                penalty += 2;
  4261. +            else if ((*armor[i])->cursed)
  4262. +                penalty--;
  4263. +        }
  4264. +        if (penalty > 0)
  4265. +            splcaster += penalty;
  4266. +    }
  4267. +
  4268.      if (spellid(spell) == g.urole.spelspec)
  4269.          splcaster += g.urole.spelsbon;
  4270.  
  4271. diff --git c/src/teleport.c i/src/teleport.c
  4272. index a29808b00..7a4109eba 100644
  4273. --- c/src/teleport.c
  4274. +++ i/src/teleport.c
  4275. @@ -863,12 +863,25 @@ level_tele()
  4276.  
  4277.                  newlevel.dnum = destdnum;
  4278.                  newlevel.dlevel = destlev;
  4279. -                if (In_endgame(&newlevel) && !In_endgame(&u.uz)) {
  4280. +                if (In_endgame(&newlevel) && !In_endgame(&u.uz)
  4281. +                    && !u.uhave.amulet) {
  4282.                      struct obj *amu;
  4283.  
  4284. -                    if (!u.uhave.amulet
  4285. -                        && (amu = mksobj(AMULET_OF_YENDOR, TRUE, FALSE))
  4286. -                               != 0) {
  4287. +                    if (!Role_if(PM_INFIDEL)) {
  4288. +                        amu = mksobj(AMULET_OF_YENDOR, TRUE, FALSE);
  4289. +                    } else if (amu = find_quest_artifact(1 << OBJ_INVENT)) {
  4290. +                        obj_extract_self(amu); /* may be contained */
  4291. +                        amu->spe = 1;
  4292. +                    } else {
  4293. +                        const char *idol = artiname(ART_IDOL_OF_MOLOCH);
  4294. +                        amu = mksobj(FIGURINE, TRUE, FALSE);
  4295. +                        artifact_exists(amu, idol, TRUE);
  4296. +                        new_oname(amu, strlen(idol) + 1);
  4297. +                        Strcpy(ONAME(amu), idol);
  4298. +                        amu->spe = 1;
  4299. +                    }
  4300. +
  4301. +                    if (amu) {
  4302.                          /* ordinarily we'd use hold_another_object()
  4303.                             for something like this, but we don't want
  4304.                             fumbling or already full pack to interfere */
  4305. diff --git c/src/trap.c i/src/trap.c
  4306. index b94f2c7cd..9625c090a 100644
  4307. --- c/src/trap.c
  4308. +++ i/src/trap.c
  4309. @@ -3731,10 +3731,10 @@ boolean *lostsome;
  4310.                   * in removing them + loadstone and other cursed stuff
  4311.                   * for obvious reasons.
  4312.                   */
  4313. -                if (!((obj->otyp == LOADSTONE && obj->cursed) || obj == uamul
  4314. -                      || obj == uleft || obj == uright || obj == ublindf
  4315. -                      || obj == uarm || obj == uarmc || obj == uarmg
  4316. -                      || obj == uarmf || obj == uarmu
  4317. +                if (!((obj->otyp == LOADSTONE && cursed(obj, TRUE))
  4318. +                      || obj == uamul || obj == uleft || obj == uright
  4319. +                      || obj == ublindf || obj == uarm || obj == uarmc
  4320. +                      || obj == uarmg || obj == uarmf || obj == uarmu
  4321.                        || (obj->cursed && (obj == uarmh || obj == uarms))
  4322.                        || welded(obj)))
  4323.                      otmp = obj;
  4324. diff --git c/src/u_init.c i/src/u_init.c
  4325. index 4b0e9f74a..d6fbd8b45 100644
  4326. --- c/src/u_init.c
  4327. +++ i/src/u_init.c
  4328. @@ -21,6 +21,7 @@ static boolean FDECL(restricted_spell_discipline, (int));
  4329.  #define UNDEF_TYP 0
  4330.  #define UNDEF_SPE '\177'
  4331.  #define UNDEF_BLESS 2
  4332. +#define CURSED 3
  4333.  
  4334.  /*
  4335.   *      Initial inventory for the various roles.
  4336. @@ -70,6 +71,19 @@ static struct trobj Healer[] = {
  4337.      { APPLE, 0, FOOD_CLASS, 5, 0 },
  4338.      { 0, 0, 0, 0, 0 }
  4339.  };
  4340. +static struct trobj Infidel[] = {
  4341. +    { AMULET_OF_YENDOR, 0, AMULET_CLASS, 1, 0 },
  4342. +    { DAGGER, 1, WEAPON_CLASS, 1, 0 },
  4343. +    { LEATHER_JACKET, 1, ARMOR_CLASS, 1, CURSED },
  4344. +    { CLOAK_OF_PROTECTION, 0, ARMOR_CLASS, 1, CURSED },
  4345. +    { POT_WATER, 0, POTION_CLASS, 3, CURSED },
  4346. +    { SPE_DRAIN_LIFE, 0, SPBOOK_CLASS, 1, 0 },
  4347. +    { UNDEF_TYP, UNDEF_SPE, SPBOOK_CLASS, 1, 0 },
  4348. +    { FIRE_HORN, UNDEF_SPE, TOOL_CLASS, 1, 0 },
  4349. +    { MAGIC_MARKER, UNDEF_SPE, TOOL_CLASS, 1, 0 },
  4350. +    { 0, 0, 0, 0, 0 }
  4351. +
  4352. +};
  4353.  static struct trobj Knight[] = {
  4354.      { LONG_SWORD, 1, WEAPON_CLASS, 1, UNDEF_BLESS },
  4355.      { LANCE, 1, WEAPON_CLASS, 1, UNDEF_BLESS },
  4356. @@ -324,6 +338,30 @@ static const struct def_skill Skill_H[] = {
  4357.      { P_BARE_HANDED_COMBAT, P_BASIC },
  4358.      { P_NONE, 0 }
  4359.  };
  4360. +static const struct def_skill Skill_Inf[] = {
  4361. +    { P_DAGGER, P_EXPERT },
  4362. +    { P_KNIFE, P_EXPERT },
  4363. +    { P_SHORT_SWORD, P_SKILLED },
  4364. +    { P_BROAD_SWORD, P_BASIC },
  4365. +    { P_SCIMITAR, P_SKILLED },
  4366. +    { P_SABER, P_BASIC },
  4367. +    { P_CLUB, P_BASIC },
  4368. +    { P_HAMMER, P_BASIC },
  4369. +    { P_QUARTERSTAFF, P_SKILLED },
  4370. +    { P_POLEARMS, P_SKILLED },
  4371. +    { P_SPEAR, P_BASIC },
  4372. +    { P_SLING, P_BASIC },
  4373. +    { P_CROSSBOW, P_SKILLED },
  4374. +    { P_DART, P_BASIC },
  4375. +    { P_WHIP, P_SKILLED },
  4376. +    { P_ATTACK_SPELL, P_EXPERT },
  4377. +    { P_DIVINATION_SPELL, P_SKILLED },
  4378. +    { P_ENCHANTMENT_SPELL, P_BASIC },
  4379. +    { P_CLERIC_SPELL, P_EXPERT },
  4380. +    { P_BARE_HANDED_COMBAT, P_SKILLED },
  4381. +    { P_RIDING, P_SKILLED },
  4382. +    { P_NONE, 0 }
  4383. +};
  4384.  static const struct def_skill Skill_K[] = {
  4385.      { P_DAGGER, P_BASIC },
  4386.      { P_KNIFE, P_BASIC },
  4387. @@ -701,6 +739,12 @@ u_init()
  4388.          knows_object(POT_FULL_HEALING);
  4389.          skill_init(Skill_H);
  4390.          break;
  4391. +    case PM_INFIDEL:
  4392. +        u.umoney0 = rn1(251, 250);
  4393. +        ini_inv(Infidel);
  4394. +        knows_object(SCR_CHARGING); /* that's what the marker is for */
  4395. +        skill_init(Skill_Inf);
  4396. +        break;
  4397.      case PM_KNIGHT:
  4398.          ini_inv(Knight);
  4399.          knows_class(WEAPON_CLASS);
  4400. @@ -927,6 +971,9 @@ int otyp;
  4401.      case PM_HEALER:
  4402.          skills = Skill_H;
  4403.          break;
  4404. +    case PM_INFIDEL:
  4405. +        skills = Skill_Inf;
  4406. +        break;
  4407.      case PM_KNIGHT:
  4408.          skills = Skill_K;
  4409.          break;
  4410. @@ -1011,6 +1058,8 @@ register struct trobj *trop;
  4411.                     || (otyp == SCR_ENCHANT_WEAPON && Role_if(PM_MONK))
  4412.                     /* wizard patch -- they already have one */
  4413.                     || (otyp == SPE_FORCE_BOLT && Role_if(PM_WIZARD))
  4414. +                   /* same for infidels */
  4415. +                   || (otyp == SPE_DRAIN_LIFE && Role_if(PM_INFIDEL))
  4416.                     /* powerful spells are either useless to
  4417.                        low level players or unbalancing; also
  4418.                        spells in restricted skill categories */
  4419. @@ -1086,7 +1135,7 @@ register struct trobj *trop;
  4420.                  obj->cknown = obj->lknown = 1;
  4421.                  obj->otrapped = 0;
  4422.              }
  4423. -            obj->cursed = 0;
  4424. +            obj->cursed = (trop->trbless == CURSED);
  4425.              if (obj->opoisoned && u.ualign.type != A_CHAOTIC)
  4426.                  obj->opoisoned = 0;
  4427.              if (obj->oclass == WEAPON_CLASS || obj->oclass == TOOL_CLASS) {
  4428. @@ -1096,10 +1145,14 @@ register struct trobj *trop;
  4429.                         && obj->otyp != FLINT) {
  4430.                  obj->quan = 1L;
  4431.              }
  4432. +            if (Role_if(PM_INFIDEL) && obj->oclass == ARMOR_CLASS) {
  4433. +                /* Infidels are used to playing with fire */
  4434. +                obj->oerodeproof = 1;
  4435. +            }
  4436.              if (trop->trspe != UNDEF_SPE)
  4437.                  obj->spe = trop->trspe;
  4438.              if (trop->trbless != UNDEF_BLESS)
  4439. -                obj->blessed = trop->trbless;
  4440. +                obj->blessed = (trop->trbless == 1);
  4441.          }
  4442.          /* defined after setting otyp+quan + blessedness */
  4443.          obj->owt = weight(obj);
  4444. diff --git c/src/uhitm.c i/src/uhitm.c
  4445. index 0f7f2eba8..9de49f6f7 100644
  4446. --- c/src/uhitm.c
  4447. +++ i/src/uhitm.c
  4448. @@ -20,7 +20,7 @@ static int FDECL(explum, (struct monst *, struct attack *));
  4449.  static void FDECL(start_engulf, (struct monst *));
  4450.  static void NDECL(end_engulf);
  4451.  static int FDECL(gulpum, (struct monst *, struct attack *));
  4452. -static boolean FDECL(hmonas, (struct monst *));
  4453. +static boolean FDECL(hmonas, (struct monst *, int, boolean));
  4454.  static void FDECL(nohandglow, (struct monst *));
  4455.  static boolean FDECL(shade_aware, (struct obj *));
  4456.  
  4457. @@ -431,7 +431,7 @@ register struct monst *mtmp;
  4458.      }
  4459.  
  4460.      if (Upolyd)
  4461. -        (void) hmonas(mtmp);
  4462. +        (void) hmonas(mtmp, NON_PM, TRUE);
  4463.      else
  4464.          (void) hitum(mtmp, g.youmonst.data->mattk);
  4465.      mtmp->mstrategy &= ~STRAT_WAITMASK;
  4466. @@ -634,6 +634,20 @@ struct attack *uattk;
  4467.          if (mhit)
  4468.              (void) passive(mon, uswapwep, mhit, malive, AT_WEAP, !uswapwep);
  4469.      }
  4470. +
  4471. +    /* your race may grant extra attacks */
  4472. +    if (!Upolyd && malive) {
  4473. +        int i;
  4474. +        int race = (flags.female && g.urace.femalenum != NON_PM)
  4475. +                   ? g.urace.femalenum : g.urace.malenum;
  4476. +        struct attack *attacks = mons[race].mattk;
  4477. +        for (i = 0; i < NATTK; i++) {
  4478. +            if (attacks[i].aatyp != AT_WEAP && attacks[i].aatyp != AT_NONE) {
  4479. +                malive = hmonas(mon, race, FALSE);
  4480. +                break;
  4481. +            }
  4482. +        }
  4483. +    }
  4484.      return malive;
  4485.  }
  4486.  
  4487. @@ -1323,6 +1337,16 @@ int dieroll;
  4488.                  pline("%s appears confused.", Monnam(mon));
  4489.          }
  4490.      }
  4491. +    if (DEADMONSTER(mon) && attacks(AD_DREN, obj)
  4492. +        && !nonliving(mdat) && u.uen < u.uenmax) {
  4493. +        int energy = mon->m_lev + 1;
  4494. +        energy += rn2(energy);
  4495. +        pline_The("ritual knife captures the evanescent life force.");
  4496. +        u.uen += energy;
  4497. +        if (u.uen > u.uenmax)
  4498. +            u.uen = u.uenmax;
  4499. +        g.context.botl = TRUE;
  4500. +    }
  4501.      if (unpoisonmsg)
  4502.          Your("%s %s no longer poisoned.", saved_oname,
  4503.               vtense(saved_oname, "are"));
  4504. @@ -1646,7 +1670,7 @@ int specialdmg; /* blessed and/or silver bonus against various things */
  4505.  
  4506.      if (is_demon(g.youmonst.data) && !rn2(13) && !uwep
  4507.          && u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS
  4508. -        && u.umonnum != PM_BALROG) {
  4509. +        && u.umonnum != PM_BALROG && u.umonnum != PM_DEMON) {
  4510.          demonpet();
  4511.          return 0;
  4512.      }
  4513. @@ -2353,12 +2377,14 @@ boolean wouldhavehit;
  4514.  
  4515.  /* attack monster as a monster; returns True if mon survives */
  4516.  static boolean
  4517. -hmonas(mon)
  4518. +hmonas(mon, as, weapon_attacks)
  4519.  register struct monst *mon;
  4520. +int as;
  4521. +boolean weapon_attacks; /* skip weapon attacks if false */
  4522.  {
  4523.      struct attack *mattk, alt_attk;
  4524.      struct obj *weapon, **originalweapon;
  4525. -    boolean altwep = FALSE, weapon_used = FALSE, odd_claw = TRUE;
  4526. +    boolean altwep = FALSE, weapon_used = !weapon_attacks, odd_claw = TRUE;
  4527.      int i, tmp, armorpenalty, sum[NATTK], nsum = 0, dhit = 0, attknum = 0;
  4528.      int dieroll, multi_claw = 0;
  4529.  
  4530. @@ -2367,8 +2393,11 @@ register struct monst *mon;
  4531.         whether silver ring causes successful hit */
  4532.      for (i = 0; i < NATTK; i++) {
  4533.          sum[i] = 0;
  4534. -        mattk = getmattk(&g.youmonst, mon, i, sum, &alt_attk);
  4535. -        if (mattk->aatyp == AT_WEAP
  4536. +        if (as != NON_PM)
  4537. +            mattk = &mons[as].mattk[i];
  4538. +        else
  4539. +            mattk = getmattk(&g.youmonst, mon, i, sum, &alt_attk);
  4540. +        if (mattk->aatyp == AT_WEAP && weapon_attacks
  4541.              || mattk->aatyp == AT_CLAW || mattk->aatyp == AT_TUCH)
  4542.              ++multi_claw;
  4543.      }
  4544. @@ -2376,11 +2405,16 @@ register struct monst *mon;
  4545.  
  4546.      for (i = 0; i < NATTK; i++) {
  4547.          /* sum[i] = 0; -- now done above */
  4548. -        mattk = getmattk(&g.youmonst, mon, i, sum, &alt_attk);
  4549. +        if (as != NON_PM)
  4550. +            mattk = &mons[as].mattk[i];
  4551. +        else
  4552. +            mattk = getmattk(&g.youmonst, mon, i, sum, &alt_attk);
  4553.          weapon = 0;
  4554.          switch (mattk->aatyp) {
  4555.          case AT_WEAP:
  4556.              /* if (!uwep) goto weaponless; */
  4557. +            if (!weapon_attacks)
  4558. +                continue;
  4559.   use_weapon:
  4560.              odd_claw = !odd_claw; /* see case AT_CLAW,AT_TUCH below */
  4561.              /* if we've already hit with a two-handed weapon, we don't
  4562. diff --git c/src/weapon.c i/src/weapon.c
  4563. index faaadc0b9..af8068a0d 100644
  4564. --- c/src/weapon.c
  4565. +++ i/src/weapon.c
  4566. @@ -1658,6 +1658,8 @@ const struct def_skill *class_skill;
  4567.      /* set skills for magic */
  4568.      if (Role_if(PM_HEALER) || Role_if(PM_MONK)) {
  4569.          P_SKILL(P_HEALING_SPELL) = P_BASIC;
  4570. +    } else if (Role_if(PM_INFIDEL)) {
  4571. +        P_SKILL(P_ATTACK_SPELL) = P_BASIC;
  4572.      } else if (Role_if(PM_PRIEST)) {
  4573.          P_SKILL(P_CLERIC_SPELL) = P_BASIC;
  4574.      } else if (Role_if(PM_WIZARD)) {
  4575. diff --git c/src/wield.c i/src/wield.c
  4576. index 2382a0e3c..7b98aee79 100644
  4577. --- c/src/wield.c
  4578. +++ i/src/wield.c
  4579. @@ -64,6 +64,8 @@ static int FDECL(ready_weapon, (struct obj *));
  4580.  /* used by welded(), and also while wielding */
  4581.  #define will_weld(optr) \
  4582.      ((optr)->cursed && (erodeable_wep(optr) || (optr)->otyp == TIN_OPENER))
  4583. +/* Infidels are immune to curses */
  4584. +#define will_weld_to_you(optr) (will_weld(optr) && !Role_if(PM_INFIDEL))
  4585.  
  4586.  /* to dual-wield, 'obj' must be a weapon or a weapon-tool, and not a bow
  4587.     or arrow or missile (dart, shuriken, boomerang), so not matching the
  4588. @@ -174,7 +176,7 @@ struct obj *wep;
  4589.      } else {
  4590.          /* Weapon WILL be wielded after this point */
  4591.          res++;
  4592. -        if (will_weld(wep)) {
  4593. +        if (will_weld_to_you(wep)) {
  4594.              const char *tmp = xname(wep), *thestr = "The ";
  4595.  
  4596.              if (strncmp(tmp, thestr, 4) && !strncmp(The(tmp), thestr, 4))
  4597. @@ -659,7 +661,7 @@ const char *verb; /* "rub",&c */
  4598.      } else {
  4599.          struct obj *oldwep = uwep;
  4600.  
  4601. -        if (will_weld(obj)) {
  4602. +        if (will_weld_to_you(obj)) {
  4603.              /* hope none of ready_weapon()'s early returns apply here... */
  4604.              (void) ready_weapon(obj);
  4605.          } else {
  4606. @@ -955,7 +957,7 @@ int
  4607.  welded(obj)
  4608.  register struct obj *obj;
  4609.  {
  4610. -    if (obj && obj == uwep && will_weld(obj)) {
  4611. +    if (obj && obj == uwep && will_weld_to_you(obj)) {
  4612.          set_bknown(obj, 1);
  4613.          return 1;
  4614.      }
  4615. diff --git c/src/wizard.c i/src/wizard.c
  4616. index a2b5d4f31..89b53ab37 100644
  4617. --- c/src/wizard.c
  4618. +++ i/src/wizard.c
  4619. @@ -67,7 +67,9 @@ amulet()
  4620.          return;
  4621.  #endif
  4622.      if ((((amu = uamul) != 0 && amu->otyp == AMULET_OF_YENDOR)
  4623. -         || ((amu = uwep) != 0 && amu->otyp == AMULET_OF_YENDOR))
  4624. +         || ((amu = uwep) != 0 && (amu->otyp == AMULET_OF_YENDOR
  4625. +                                   || amu->oartifact == ART_IDOL_OF_MOLOCH
  4626. +                                      && amu->spe)))
  4627.          && !rn2(15)) {
  4628.          for (ttmp = g.ftrap; ttmp; ttmp = ttmp->ntrap) {
  4629.              if (ttmp->ttyp == MAGIC_PORTAL) {
  4630. @@ -107,7 +109,8 @@ register struct monst *mtmp;
  4631.      register struct obj *otmp;
  4632.  
  4633.      for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
  4634. -        if (otmp->otyp == AMULET_OF_YENDOR)
  4635. +        if (otmp->otyp == AMULET_OF_YENDOR
  4636. +            || otmp->oartifact == ART_IDOL_OF_MOLOCH && otmp->spe)
  4637.              return 1;
  4638.      return 0;
  4639.  }
  4640. diff --git c/src/worn.c i/src/worn.c
  4641. index 231df0961..af764acbf 100644
  4642. --- c/src/worn.c
  4643. +++ i/src/worn.c
  4644. @@ -590,6 +590,10 @@ boolean racialexception;
  4645.                  continue;
  4646.              if (racialexception && (racial_exception(mon, obj) < 1))
  4647.                  continue;
  4648. +            /* monsters won't sacrifice flight for AC */
  4649. +            if (big_wings(mon->data) && !Is_dragon_scales(obj)
  4650. +                && obj->otyp != LEATHER_JACKET)
  4651. +                continue;
  4652.              break;
  4653.          }
  4654.          if (obj->owornmask)
  4655. diff --git c/src/zap.c i/src/zap.c
  4656. index 950949d35..7d9e4665e 100644
  4657. --- c/src/zap.c
  4658. +++ i/src/zap.c
  4659. @@ -1229,6 +1229,7 @@ struct obj *obj;
  4660.  int ochance, achance; /* percent chance for ordinary objects, artifacts */
  4661.  {
  4662.      if (obj->otyp == AMULET_OF_YENDOR
  4663. +        || Role_if(PM_INFIDEL) && is_quest_artifact(obj)
  4664.          || obj->otyp == SPE_BOOK_OF_THE_DEAD
  4665.          || obj->otyp == CANDELABRUM_OF_INVOCATION
  4666.          || obj->otyp == BELL_OF_OPENING
  4667. @@ -2517,7 +2518,7 @@ boolean ordinary;
  4668.  
  4669.      case WAN_DEATH:
  4670.      case SPE_FINGER_OF_DEATH:
  4671. -        if (nonliving(g.youmonst.data) || is_demon(g.youmonst.data)) {
  4672. +        if (nonliving(g.youmonst.data) || is_demon(raceptr(&g.youmonst))) {
  4673.              pline((obj->otyp == WAN_DEATH)
  4674.                        ? "The wand shoots an apparently harmless beam at you."
  4675.                        : "You seem no deader than before.");
  4676. @@ -3890,7 +3891,8 @@ xchar sx, sy;
  4677.                  (void) destroy_arm(uarmc);
  4678.              if (uarmu)
  4679.                  (void) destroy_arm(uarmu);
  4680. -        } else if (nonliving(g.youmonst.data) || is_demon(g.youmonst.data)) {
  4681. +        } else if (nonliving(g.youmonst.data)
  4682. +                   || is_demon(raceptr(&g.youmonst))) {
  4683.              shieldeff(sx, sy);
  4684.              You("seem unaffected.");
  4685.              break;
  4686. diff --git c/sys/unix/NetHack.xcodeproj/project.pbxproj i/sys/unix/NetHack.xcodeproj/project.pbxproj
  4687. index 692f2e998..26e93dbeb 100644
  4688. --- c/sys/unix/NetHack.xcodeproj/project.pbxproj
  4689. +++ i/sys/unix/NetHack.xcodeproj/project.pbxproj
  4690. @@ -1138,6 +1138,11 @@
  4691.                 "$(NH_DAT_DIR)/Hea-goal.lua",
  4692.                 "$(NH_DAT_DIR)/Hea-loca.lua",
  4693.                 "$(NH_DAT_DIR)/Hea-strt.lua",
  4694. +               "$(NH_DAT_DIR)/Inf-fila.lua",
  4695. +               "$(NH_DAT_DIR)/Inf-filb.lua",
  4696. +               "$(NH_DAT_DIR)/Inf-goal.lua",
  4697. +               "$(NH_DAT_DIR)/Inf-loca.lua",
  4698. +               "$(NH_DAT_DIR)/Inf-strt.lua",
  4699.                 "$(NH_DAT_DIR)/Kni-fila.lua",
  4700.                 "$(NH_DAT_DIR)/Kni-filb.lua",
  4701.                 "$(NH_DAT_DIR)/Kni-goal.lua",
  4702. diff --git c/win/tty/wintty.c i/win/tty/wintty.c
  4703. index bb993aa54..27787ff55 100644
  4704. --- c/win/tty/wintty.c
  4705. +++ i/win/tty/wintty.c
  4706. @@ -926,6 +926,7 @@ tty_player_selection()
  4707.       */
  4708.      getconfirmation = (picksomething && pick4u != 'a' && !flags.randomall);
  4709.      while (getconfirmation) {
  4710. +        int real_algn = special_alignment(ROLE, ALGN);
  4711.          tty_clear_nhwindow(BASE_WINDOW);
  4712.          role_selection_prolog(ROLE_NONE, BASE_WINDOW);
  4713.          win = create_nhwindow(NHW_MENU);
  4714. @@ -938,8 +939,8 @@ tty_player_selection()
  4715.              Sprintf(plbuf, " %s", genders[GEND].adj);
  4716.          else
  4717.              *plbuf = '\0'; /* omit redundant gender */
  4718. -        Sprintf(pbuf, "%s, %s%s %s %s", g.plname, aligns[ALGN].adj, plbuf,
  4719. -                races[RACE].adj,
  4720. +        Sprintf(pbuf, "%s, %s%s %s %s", g.plname, aligns[real_algn].adj,
  4721. +                plbuf, races[RACE].adj,
  4722.                  (GEND == 1 && roles[ROLE].name.f) ? roles[ROLE].name.f
  4723.                                                    : roles[ROLE].name.m);
  4724.          add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, pbuf,
  4725. diff --git c/win/win32/vs2017/files.props i/win/win32/vs2017/files.props
  4726. index c388b6898..ad3886d4f 100644
  4727. --- c/win/win32/vs2017/files.props
  4728. +++ i/win/win32/vs2017/files.props
  4729. @@ -97,6 +97,11 @@
  4730.      <Luafiles Include = "hea-goal.lua"/>
  4731.      <Luafiles Include = "hea-loca.lua"/>
  4732.      <Luafiles Include = "hea-strt.lua"/>
  4733. +    <Luafiles Include = "inf-fila.lua"/>
  4734. +    <Luafiles Include = "inf-filb.lua"/>
  4735. +    <Luafiles Include = "inf-goal.lua"/>
  4736. +    <Luafiles Include = "inf-loca.lua"/>
  4737. +    <Luafiles Include = "inf-strt.lua"/>
  4738.      <Luafiles Include = "kni-fila.lua"/>
  4739.      <Luafiles Include = "kni-filb.lua"/>
  4740.      <Luafiles Include = "kni-goal.lua"/>
Add Comment
Please, Sign In to add comment