summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Borowski <kilobyte@angband.pl>2012-04-12 03:09:08 +0200
committerAdam Borowski <kilobyte@angband.pl>2012-04-12 03:09:08 +0200
commit64d4ef277c5500fa5b4f65a6a96768605ec6fd75 (patch)
tree8487dfd6b4af109efadcc60a88fccfb433f69d5a
parent7ff52721aa186489a3a27074a2e95e9f0471eb02 (diff)
parent3e11d7d1fd1154c0c458eb8482c56aae6c69b7ea (diff)
downloadcrawl-ref-64d4ef277c5500fa5b4f65a6a96768605ec6fd75.tar.gz
crawl-ref-64d4ef277c5500fa5b4f65a6a96768605ec6fd75.zip
Merge branch 'master' into portal_branches
-rw-r--r--crawl-ref/CREDITS.txt2
-rw-r--r--crawl-ref/docs/crawl_manual.reST23
-rw-r--r--crawl-ref/docs/fight_simulator.txt105
-rwxr-xr-xcrawl-ref/git-hooks/crawl-ref-cia1
-rw-r--r--crawl-ref/settings/runrest_messages.txt4
-rw-r--r--crawl-ref/source/Makefile18
-rw-r--r--crawl-ref/source/Makefile.obj1
-rw-r--r--crawl-ref/source/abl-show.cc27
-rw-r--r--crawl-ref/source/abyss.cc4
-rw-r--r--crawl-ref/source/acquire.cc3
-rw-r--r--crawl-ref/source/actor.h1
-rw-r--r--crawl-ref/source/areas.cc4
-rw-r--r--crawl-ref/source/art-data.txt45
-rw-r--r--crawl-ref/source/artefact.cc55
-rw-r--r--crawl-ref/source/beam.cc85
-rw-r--r--crawl-ref/source/chardump.cc22
-rw-r--r--crawl-ref/source/cloud.cc34
-rw-r--r--crawl-ref/source/command.cc6
-rw-r--r--crawl-ref/source/dat/database/godspeak.txt49
-rw-r--r--crawl-ref/source/dat/database/monspeak.txt42
-rw-r--r--crawl-ref/source/dat/database/pl/godspeak.txt765
-rw-r--r--crawl-ref/source/dat/database/quotes.txt450
-rw-r--r--crawl-ref/source/dat/database/randname.txt49
-rw-r--r--crawl-ref/source/dat/database/wpnnoise.txt2
-rw-r--r--crawl-ref/source/dat/des/branches/elf.des100
-rw-r--r--crawl-ref/source/dat/des/branches/hells.des301
-rw-r--r--crawl-ref/source/dat/des/branches/lair.des44
-rw-r--r--crawl-ref/source/dat/des/branches/orc.des57
-rw-r--r--crawl-ref/source/dat/des/branches/snake.des237
-rw-r--r--crawl-ref/source/dat/des/branches/spider.des258
-rw-r--r--crawl-ref/source/dat/des/branches/vaults.des6
-rw-r--r--crawl-ref/source/dat/des/branches/zot.des80
-rw-r--r--crawl-ref/source/dat/des/builder/shops.des2
-rw-r--r--crawl-ref/source/dat/des/entry/twisted.des39
-rw-r--r--crawl-ref/source/dat/des/portals/icecave.des6
-rw-r--r--crawl-ref/source/dat/des/portals/trove.des8
-rw-r--r--crawl-ref/source/dat/des/portals/volcano.des2
-rw-r--r--crawl-ref/source/dat/des/portals/wizlab.des209
-rw-r--r--crawl-ref/source/dat/des/sprint/sprint_mu.des4
-rw-r--r--crawl-ref/source/dat/des/sprint/sprint_v.des5
-rw-r--r--crawl-ref/source/dat/des/traps/beogh_trap.des7
-rw-r--r--crawl-ref/source/dat/des/traps/boulders.des214
-rw-r--r--crawl-ref/source/dat/des/variable/mini_monsters.des46
-rw-r--r--crawl-ref/source/dat/descript/features.txt14
-rw-r--r--crawl-ref/source/dat/descript/items.txt10
-rw-r--r--crawl-ref/source/dat/descript/monsters.txt21
-rw-r--r--crawl-ref/source/dat/descript/pl/items.txt7
-rw-r--r--crawl-ref/source/dat/descript/skills.txt2
-rw-r--r--crawl-ref/source/dat/descript/spells.txt4
-rw-r--r--crawl-ref/source/dat/dlua/ziggurat.lua4
-rw-r--r--crawl-ref/source/dat/lua/autofight.lua30
-rw-r--r--crawl-ref/source/database.cc10
-rw-r--r--crawl-ref/source/decks.cc25
-rw-r--r--crawl-ref/source/decks.h4
-rw-r--r--crawl-ref/source/defines.h18
-rw-r--r--crawl-ref/source/delay.cc9
-rw-r--r--crawl-ref/source/describe.cc14
-rw-r--r--crawl-ref/source/dgn-labyrinth.cc3
-rw-r--r--crawl-ref/source/dgn-layouts.cc20
-rw-r--r--crawl-ref/source/directn.cc2
-rw-r--r--crawl-ref/source/dungeon.cc26
-rw-r--r--crawl-ref/source/effects.cc15
-rw-r--r--crawl-ref/source/enum.h48
-rw-r--r--crawl-ref/source/evoke.cc25
-rw-r--r--crawl-ref/source/exercise.cc4
-rw-r--r--crawl-ref/source/feature.cc7
-rw-r--r--crawl-ref/source/fight.cc14
-rw-r--r--crawl-ref/source/fight.h3
-rw-r--r--crawl-ref/source/files.cc1
-rw-r--r--crawl-ref/source/food.cc229
-rw-r--r--crawl-ref/source/format.cc8
-rw-r--r--crawl-ref/source/format.h1
-rw-r--r--crawl-ref/source/fprop.h1
-rw-r--r--crawl-ref/source/godabil.cc149
-rw-r--r--crawl-ref/source/goditem.cc207
-rw-r--r--crawl-ref/source/goditem.h31
-rw-r--r--crawl-ref/source/godprayer.cc6
-rw-r--r--crawl-ref/source/godwrath.cc1
-rw-r--r--crawl-ref/source/hints.cc1
-rw-r--r--crawl-ref/source/initfile.cc31
-rw-r--r--crawl-ref/source/invent.cc86
-rw-r--r--crawl-ref/source/invent.h15
-rw-r--r--crawl-ref/source/item_use.cc122
-rw-r--r--crawl-ref/source/itemname.cc23
-rw-r--r--crawl-ref/source/itemprop-enum.h2
-rw-r--r--crawl-ref/source/itemprop.cc77
-rw-r--r--crawl-ref/source/items.cc44
-rw-r--r--crawl-ref/source/json.cc1944
-rw-r--r--crawl-ref/source/l_crawl.cc3
-rw-r--r--crawl-ref/source/l_dgn.cc10
-rw-r--r--crawl-ref/source/l_item.cc8
-rw-r--r--crawl-ref/source/l_moninf.cc76
-rw-r--r--crawl-ref/source/l_view.cc28
-rw-r--r--crawl-ref/source/l_you.cc15
-rw-r--r--crawl-ref/source/lang-fake.cc381
-rw-r--r--crawl-ref/source/lang-fake.h2
-rw-r--r--crawl-ref/source/libutil.cc26
-rw-r--r--crawl-ref/source/libutil.h11
-rw-r--r--crawl-ref/source/libw32c.cc12
-rw-r--r--crawl-ref/source/main.cc48
-rw-r--r--crawl-ref/source/makeitem.cc29
-rw-r--r--crawl-ref/source/makeitem.h1
-rw-r--r--crawl-ref/source/map_knowledge.cc7
-rw-r--r--crawl-ref/source/map_knowledge.h2
-rw-r--r--crawl-ref/source/mapdef.cc11
-rw-r--r--crawl-ref/source/mapmark.cc6
-rw-r--r--crawl-ref/source/maps.cc42
-rw-r--r--crawl-ref/source/maps.h11
-rw-r--r--crawl-ref/source/melee_attack.cc352
-rw-r--r--crawl-ref/source/melee_attack.h2
-rw-r--r--crawl-ref/source/message.cc15
-rw-r--r--crawl-ref/source/misc.cc133
-rw-r--r--crawl-ref/source/misc.h4
-rw-r--r--crawl-ref/source/mon-abil.cc52
-rw-r--r--crawl-ref/source/mon-abil.h1
-rw-r--r--crawl-ref/source/mon-act.cc35
-rw-r--r--crawl-ref/source/mon-cast.cc68
-rw-r--r--crawl-ref/source/mon-data.h27
-rw-r--r--crawl-ref/source/mon-death.cc7
-rw-r--r--crawl-ref/source/mon-ench.cc30
-rw-r--r--crawl-ref/source/mon-gear.cc41
-rw-r--r--crawl-ref/source/mon-info.cc9
-rw-r--r--crawl-ref/source/mon-info.h1
-rw-r--r--crawl-ref/source/mon-pick.cc441
-rw-r--r--crawl-ref/source/mon-place.cc42
-rw-r--r--crawl-ref/source/mon-place.h5
-rw-r--r--crawl-ref/source/mon-project.cc305
-rw-r--r--crawl-ref/source/mon-project.h3
-rw-r--r--crawl-ref/source/mon-speak.cc4
-rw-r--r--crawl-ref/source/mon-spll.h6
-rw-r--r--crawl-ref/source/mon-stuff.cc41
-rw-r--r--crawl-ref/source/mon-stuff.h4
-rw-r--r--crawl-ref/source/mon-util.cc28
-rw-r--r--crawl-ref/source/mon-util.h5
-rw-r--r--crawl-ref/source/monster.cc25
-rw-r--r--crawl-ref/source/monster.h2
-rw-r--r--crawl-ref/source/mutation.cc16
-rw-r--r--crawl-ref/source/ng-init.cc8
-rw-r--r--crawl-ref/source/ng-setup.cc6
-rw-r--r--crawl-ref/source/options.h4
-rw-r--r--crawl-ref/source/ouch.cc32
-rw-r--r--crawl-ref/source/output.cc32
-rw-r--r--crawl-ref/source/player-act.cc4
-rw-r--r--crawl-ref/source/player-equip.cc4
-rw-r--r--crawl-ref/source/player-stats.cc45
-rw-r--r--crawl-ref/source/player.cc957
-rw-r--r--crawl-ref/source/player.h23
-rw-r--r--crawl-ref/source/process_desc.h28
-rw-r--r--crawl-ref/source/religion.cc5
-rw-r--r--crawl-ref/source/rltiles/dc-dngn/dngn_teleporter.png (renamed from crawl-ref/source/rltiles/dc-dngn/vaults/the_teleporter_vaults.png)bin515 -> 515 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_shoals.pngbin0 -> 671 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_slime.pngbin0 -> 889 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_snake.pngbin0 -> 422 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_swamp.pngbin0 -> 1160 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-dngn/vaults/teleporter_ice_cave.png (renamed from crawl-ref/source/rltiles/dc-dngn/vaults/the_teleporter_ice_cave.png)bin1484 -> 1484 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-feat.txt160
-rw-r--r--crawl-ref/source/rltiles/dc-item.txt2
-rw-r--r--crawl-ref/source/rltiles/dc-misc.txt5
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red.pngbin1323 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red00.pngbin0 -> 786 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red01.pngbin0 -> 853 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red02.pngbin0 -> 761 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red03.pngbin0 -> 624 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red04.pngbin0 -> 719 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red05.pngbin0 -> 615 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red06.pngbin0 -> 577 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red07.pngbin0 -> 793 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red08.pngbin0 -> 740 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red09.pngbin0 -> 690 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red1.pngbin1359 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red10.pngbin0 -> 1213 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red11.pngbin0 -> 900 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red12.pngbin0 -> 884 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red13.pngbin0 -> 958 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red14.pngbin0 -> 1088 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red15.pngbin0 -> 1136 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red16.pngbin0 -> 1151 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red17.pngbin0 -> 1154 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red18.pngbin0 -> 1022 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red19.pngbin0 -> 907 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red2.pngbin1588 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red20.pngbin0 -> 1057 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red21.pngbin0 -> 869 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red22.pngbin0 -> 1059 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red23.pngbin0 -> 1151 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red24.pngbin0 -> 1121 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red25.pngbin0 -> 1099 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red26.pngbin0 -> 1289 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red27.pngbin0 -> 1311 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red28.pngbin0 -> 1178 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red29.pngbin0 -> 1116 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red3.pngbin1618 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/blood_red4.pngbin1574 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_e.pngbin0 -> 1289 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_n.pngbin0 -> 1401 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_s.pngbin0 -> 935 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_w.pngbin0 -> 1316 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_e.pngbin0 -> 1029 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_n.pngbin0 -> 1061 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_s.pngbin0 -> 785 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_w.pngbin0 -> 1047 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_e.pngbin0 -> 1503 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_n.pngbin0 -> 1688 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_s.pngbin0 -> 1061 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_w.pngbin0 -> 1550 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_e.pngbin0 -> 1500 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_n.pngbin0 -> 1571 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_s.pngbin0 -> 1087 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_w.pngbin0 -> 1478 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_e.pngbin0 -> 901 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_n.pngbin0 -> 1042 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_s.pngbin0 -> 637 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_w.pngbin0 -> 937 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_e.pngbin0 -> 1477 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_n.pngbin0 -> 1544 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_s.pngbin0 -> 987 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_w.pngbin0 -> 1471 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_e.pngbin0 -> 1161 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_n.pngbin0 -> 1207 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_s.pngbin0 -> 761 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_w.pngbin0 -> 1163 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_e.pngbin0 -> 1241 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_n.pngbin0 -> 1340 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_s.pngbin0 -> 854 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_w.pngbin0 -> 1237 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_e.pngbin0 -> 1342 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_n.pngbin0 -> 1331 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_s.pngbin0 -> 939 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_w.pngbin0 -> 1321 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_e.pngbin0 -> 617 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_n.pngbin0 -> 682 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_s.pngbin0 -> 395 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_w.pngbin0 -> 628 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_e.pngbin0 -> 1865 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_n.pngbin0 -> 1948 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_s.pngbin0 -> 1342 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_w.pngbin0 -> 1908 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_e.pngbin0 -> 1095 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_n.pngbin0 -> 1178 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_s.pngbin0 -> 775 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_w.pngbin0 -> 1130 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_e.pngbin0 -> 927 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_n.pngbin0 -> 890 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_s.pngbin0 -> 529 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_w.pngbin0 -> 891 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_e.pngbin0 -> 1057 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_n.pngbin0 -> 1181 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_s.pngbin0 -> 847 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_w.pngbin0 -> 1106 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_e.pngbin0 -> 1158 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_n.pngbin0 -> 1219 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_s.pngbin0 -> 794 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_w.pngbin0 -> 1186 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_e.pngbin0 -> 1108 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_n.pngbin0 -> 1119 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_s.pngbin0 -> 908 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_w.pngbin0 -> 1098 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_e.pngbin0 -> 925 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_n.pngbin0 -> 1025 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_s.pngbin0 -> 639 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_w.pngbin0 -> 986 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_e.pngbin0 -> 1505 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_n.pngbin0 -> 1583 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_s.pngbin0 -> 1049 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_w.pngbin0 -> 1519 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_e.pngbin1679 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_n.pngbin1748 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_s.pngbin1433 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_w.pngbin1689 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_e.pngbin967 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_n.pngbin994 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_s.pngbin763 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_w.pngbin954 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_e.pngbin811 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_n.pngbin799 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_s.pngbin527 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_w.pngbin808 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_e.pngbin928 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_n.pngbin1050 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_s.pngbin852 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_w.pngbin948 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_e.pngbin959 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_n.pngbin1045 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_s.pngbin789 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_w.pngbin988 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_e.pngbin937 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_n.pngbin935 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_s.pngbin681 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_w.pngbin928 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_e.pngbin886 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_n.pngbin942 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_s.pngbin636 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_w.pngbin902 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_e.pngbin1411 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_n.pngbin1430 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_s.pngbin1102 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_w.pngbin1415 -> 0 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood00.pngbin0 -> 914 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood01.pngbin0 -> 940 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood02.pngbin0 -> 1212 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood03.pngbin0 -> 982 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood04.pngbin0 -> 1018 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood05.pngbin0 -> 1188 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood06.pngbin0 -> 1253 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood07.pngbin0 -> 1019 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood08.pngbin0 -> 949 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood09.pngbin0 -> 1107 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-mon.txt4
-rw-r--r--crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling0.pngbin0 -> 345 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling1.pngbin0 -> 348 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling2.pngbin0 -> 349 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling3.pngbin0 -> 347 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-mon/demons/hell_sentinel.pngbin866 -> 473 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-player.txt2
-rw-r--r--crawl-ref/source/rltiles/effect/cloud_dust_trail0.pngbin0 -> 741 bytes
-rw-r--r--crawl-ref/source/rltiles/effect/cloud_dust_trail1.pngbin0 -> 999 bytes
-rw-r--r--crawl-ref/source/rltiles/effect/cloud_dust_trail2.pngbin0 -> 1502 bytes
-rw-r--r--crawl-ref/source/rltiles/effect/cloud_dust_trail3.pngbin0 -> 1707 bytes
-rw-r--r--crawl-ref/source/rltiles/item/weapon/elven_dagger1.pngbin678 -> 211 bytes
-rw-r--r--crawl-ref/source/rltiles/item/weapon/elven_dagger2.pngbin384 -> 215 bytes
-rw-r--r--crawl-ref/source/rltiles/item/weapon/elven_short_sword1.pngbin1197 -> 227 bytes
-rw-r--r--crawl-ref/source/rltiles/item/weapon/elven_short_sword2.pngbin490 -> 235 bytes
-rw-r--r--crawl-ref/source/scripts/csim.lua29
-rw-r--r--crawl-ref/source/shopping.cc2
-rw-r--r--crawl-ref/source/show.cc10
-rw-r--r--crawl-ref/source/showsymb.cc2
-rw-r--r--crawl-ref/source/skills.cc13
-rw-r--r--crawl-ref/source/skills2.cc4
-rw-r--r--crawl-ref/source/spl-book.cc4
-rw-r--r--crawl-ref/source/spl-cast.cc15
-rw-r--r--crawl-ref/source/spl-damage.cc2
-rw-r--r--crawl-ref/source/spl-data.h4
-rw-r--r--crawl-ref/source/spl-goditem.cc27
-rw-r--r--crawl-ref/source/spl-miscast.cc151
-rw-r--r--crawl-ref/source/spl-other.cc2
-rw-r--r--crawl-ref/source/spl-selfench.cc9
-rw-r--r--crawl-ref/source/spl-summoning.cc17
-rw-r--r--crawl-ref/source/spl-summoning.h3
-rw-r--r--crawl-ref/source/spl-tornado.cc8
-rw-r--r--crawl-ref/source/spl-transloc.cc22
-rw-r--r--crawl-ref/source/spl-util.cc3
-rw-r--r--crawl-ref/source/stairs.cc3
-rw-r--r--crawl-ref/source/status.cc35
-rw-r--r--crawl-ref/source/status.h1
-rw-r--r--crawl-ref/source/stuff.cc2
-rw-r--r--crawl-ref/source/tag-version.h1
-rw-r--r--crawl-ref/source/tags.cc40
-rw-r--r--crawl-ref/source/target.cc2
-rw-r--r--crawl-ref/source/terrain.cc37
-rw-r--r--crawl-ref/source/terrain.h4
-rw-r--r--crawl-ref/source/test/rune-gen.lua1
-rw-r--r--crawl-ref/source/test/stress/abyss.rc2
-rw-r--r--crawl-ref/source/tilecell.h6
-rw-r--r--crawl-ref/source/tiledgnbuf.cc4
-rw-r--r--crawl-ref/source/tiledoll.cc6
-rw-r--r--crawl-ref/source/tilepick-p.cc2
-rw-r--r--crawl-ref/source/tilepick.cc61
-rw-r--r--crawl-ref/source/tilereg-doll.cc24
-rw-r--r--crawl-ref/source/tileview.cc16
-rw-r--r--crawl-ref/source/tileweb.cc2
-rw-r--r--crawl-ref/source/transform.cc32
-rw-r--r--crawl-ref/source/traps.cc4
-rw-r--r--crawl-ref/source/travel.cc29
-rw-r--r--crawl-ref/source/viewchar.cc37
-rw-r--r--crawl-ref/source/viewchar.h2
-rw-r--r--crawl-ref/source/webserver/game_data/static/display.js9
-rw-r--r--crawl-ref/source/webserver/ws_handler.py12
-rw-r--r--crawl-ref/source/wiz-dgn.cc10
-rw-r--r--crawl-ref/source/wiz-fsim.cc899
-rw-r--r--crawl-ref/source/wiz-fsim.h14
-rw-r--r--crawl-ref/source/wiz-you.cc12
-rw-r--r--crawl-ref/source/wiz-you.h1
-rw-r--r--crawl-ref/source/xom.cc295
-rw-r--r--crawl-ref/source/xom.h15
-rw-r--r--crawl-ref/source/zap-data.h6
-rw-r--r--crawl-ref/source/zotdef.cc3
376 files changed, 8096 insertions, 4354 deletions
diff --git a/crawl-ref/CREDITS.txt b/crawl-ref/CREDITS.txt
index 0a2a2a04de..e2ed9bb01e 100644
--- a/crawl-ref/CREDITS.txt
+++ b/crawl-ref/CREDITS.txt
@@ -56,6 +56,7 @@ Trent W. Buck
Joe Buzzelli
Henry Cipolla
Aaron Curtis
+Simon Curtis
Denzi
Lothar Dierkes
Mike Drinen
@@ -136,6 +137,7 @@ Solf
Michael Spang
Jan 'heftig' Steffens
Johan Strandell
+Ben Striegel
Pavel 'Curio' Svinarchuk
Matthew Tadd
William Tanksley, Jr.
diff --git a/crawl-ref/docs/crawl_manual.reST b/crawl-ref/docs/crawl_manual.reST
index 66f2fa1c62..f934666bc2 100644
--- a/crawl-ref/docs/crawl_manual.reST
+++ b/crawl-ref/docs/crawl_manual.reST
@@ -1555,8 +1555,8 @@ Nagas
and cannot move them around as quickly as can other creatures' legs (this only
affects their movement rate; all other actions are at normal speed). Their
body shape also prevents them from gaining full protection from most armour. A
- Naga's biggest forte is stealth: Nagas are very good at moving unnoticed. They
- can also use their tails to constrict their foes.
+ Naga's biggest forte is stealth: Nagas are very good at moving unnoticed. Their
+ tails eventually grow strong enough to constrict their foes in combat.
Every now and then, a Naga can spit poison; the range, accuracy and damage of
this poison increases with the Naga's experience level.
@@ -1835,7 +1835,8 @@ Grey Draconians
Black Draconians
can unleash huge electrical discharges, and are naturally insulated. They are
- good at air magic but feel cumbersome with earth magic.
+ good at air magic but feel cumbersome with earth magic. Their wings will
+ eventually grow larger, allowing them to fly temporarily.
Mottled Draconians
are somewhat in touch with fire, yet are not weak with ice. They can spit
@@ -2104,8 +2105,8 @@ There are a number of individual weapon skills for missile weapons:
Throwing is the skill for all things hurled without a launcher: axes, spears,
stones, nets, etc. The other skills refer to various types of missiles shot with
a launcher. An exception to this are needles: these are launched using blowguns,
-an action which uses the Throwing skill. Since stones can be thrown
-without launchers to good effect, these skills crosstrain:
+an action which uses the Throwing skill. Since stones can be thrown without
+launchers to good effect, these skills crosstrain:
* Throwing and Slings
@@ -2161,9 +2162,9 @@ Dodging
Stealth
Helps you avoid being noticed, and makes monsters more likely to lose track of
- you when you leave their line of sight. Try not to wear heavy armour or be
- encumbered if you want to be stealthy. Large creatures (like Trolls) are bad
- at stealth. The big exception are Nagas, which are unusually stealthy.
+ you when you leave their line of sight. Wearing heavy armour or being
+ encumbered penalises stealth attempts. Large creatures (like Trolls) are bad
+ at stealth, except for Nagas, which are unusually stealthy.
Stabbing
Lets you make a very powerful first strike against a sleeping/resting monster
@@ -2197,10 +2198,10 @@ Evocations
have certain powers (like crystal balls) work better for characters trained in
this skill. Like Invocations, Evocations is easier to learn than other skills.
- Invocations and Evocations also both affect your maximum magical reserves,
+ Invocations and Evocations can increase your maximum magical reserves,
although both have a smaller effect than Spellcasting in this regard. The
- bonuses are not cumulative - the highest contribution from Spellcasting,
- Invocations and Evocations is used.
+ bonuses are not cumulative; the highest contribution from Spellcasting,
+ Invocations or Evocations is used.
****************************************
4. List of keys and commands
diff --git a/crawl-ref/docs/fight_simulator.txt b/crawl-ref/docs/fight_simulator.txt
new file mode 100644
index 0000000000..ec094f7f24
--- /dev/null
+++ b/crawl-ref/docs/fight_simulator.txt
@@ -0,0 +1,105 @@
+The crawl fight simulator is a set of commands available in wizard mode to
+generate statistical data of player vs monsters combat. It is useful to test
+and balance new formulae, changes to weapon stats or brand effect for example.
+
+There are 3 commands to start the fight simulator. Each of them will start by
+prompting you to select a monster among the ones in sight. If there is none (or
+if you cancel the selection), you will be prompted to type a monster name.
+
+&f: Quick simulation. This command runs one attack simulation (player attack
+monster) and one defense simulation (monster attack player). It uses the
+current character skills and stats without any change. The output looks like
+this:
+
+
+ AvHitDam | MaxDam | Accuracy | AvDam | AvTime | AvEffDam
+ Attacking: 3.9 | 10 | 81% | 3.2 | 1.3 | 2.5
+ Defending: 5.9 | 32 | 100% | 5.9 | 1.0 | 5.9
+
+AvHitDam : Average damage per round which have hit.
+MaxDam : Highest damage dealt in a single round.
+Accuracy : Percentage of attacks which hit their target, including the ones
+ which did no damage. For monsters with multiple attacks, if at least
+ one has hit, the attack round counts has having hit.
+AvDam : The average damage per round, including the missed ones. It should
+ be equal to AvHitDam * Accuracy.
+AvTime : Average duration of an attack round.
+AvEffDam : Average damage per turn (10 aut). This accounts for accuracy and
+ attack speed and is the accurate indicator of how effective an
+ attack is.
+
+&F: Simple scale simulation. This command will start by asking for (A)ttack or
+(D)efense simulation. It will then run the simulation 28 times while
+incrementing a skill from level 0 to level 27.
+By default, the skill scaled is the weapon skill in attack mode and armour in
+defense mode. The weapon skill can be Unarmed Combat, Throwing or a launcher
+skill depending on what equipement is currently wielded/quivered. The skill can
+be changed using the fsim_scale option (see below).
+The results are presented in a table similar to the one generated by the quick
+simulation command. Results are displayed in the in-game message area, and also
+appended to the fight.stat file.
+
+&^F (& followed by ctrl+F): Double scale simulation. Like the simple scale
+command, it starts by asking for attack or defense mode and output the results
+in the fight.stat file.
+2 skills are scaled from 1 to 27 by steps of 2 levels. In attack mode, the
+skills are weapon and fighting. In defense mode, they are armour and dodging.
+Only AvEffDam is calculated and the results are presented in a 2 dimensional
+array like this:
+
+Fighting(x) vs Long Blades(y)
+ 1 3 5 7 9 11 13 15 17 19 21 23 25 27
+ 1 4.3 4.2 4.7 4.8 4.6 5.0 5.3 5.3 5.5 5.4 5.7 6.1 6.6 6.8
+ 3 4.6 4.6 4.7 5.3 5.2 5.4 5.8 5.7 6.1 6.1 6.5 6.5 6.3 7.0
+ 5 5.0 5.1 5.3 5.6 6.1 5.6 6.1 6.5 6.6 7.1 7.6 7.6 7.9 7.8
+ 7 5.6 6.0 6.1 6.3 6.5 6.5 7.2 7.7 7.5 8.1 8.0 8.1 8.4 8.1
+ 9 6.3 6.5 6.7 7.3 7.4 7.5 8.0 8.0 8.1 8.5 9.0 9.0 9.8 9.9
+11 7.1 7.1 7.2 7.8 7.8 8.4 8.8 8.9 9.0 9.9 9.7 10.5 10.7 11.0
+13 8.0 8.2 8.8 9.2 9.6 9.3 9.8 10.0 11.0 10.6 11.1 11.8 11.6 12.5
+15 9.0 9.5 9.4 9.7 10.2 10.7 11.3 12.2 11.6 12.7 12.7 12.4 13.3 13.3
+17 10.2 10.5 11.1 11.0 11.8 12.1 12.1 12.5 13.3 13.5 14.2 15.4 15.1 15.5
+19 11.7 11.9 12.0 12.7 13.8 14.3 14.1 15.2 14.9 16.3 16.8 17.1 17.0 18.0
+21 13.9 14.4 15.2 14.9 15.6 16.3 16.3 17.4 18.5 18.7 18.4 20.7 20.4 20.6
+23 16.1 17.5 16.4 17.9 17.7 18.4 20.8 19.8 20.7 20.9 21.8 22.6 24.4 24.7
+25 18.1 19.1 19.1 19.5 19.9 21.9 22.7 22.1 22.7 24.3 23.9 26.3 26.5 26.5
+27 18.3 19.4 19.0 20.8 22.1 21.3 23.7 22.3 22.9 24.3 24.5 25.1 26.8 26.9
+
+The following options can be used to configure the fight simulator:
+
+fsim_mode : set it to "attack" or "defense" to skip the prompt.
+fsim_mons : if set to a valid monster type, it will be used instead of asking
+ to select a monster.
+fsim_rounds: the number of rounds run ar each skill level. It defaults to 4000
+ and range from 1000 to 500 000.
+
+fsim_scale: It's used to configure which skills are used as a scale in simple
+scale mode. By default, only the weapon skill is scaled.
+It takes a list of skills separated by commas. An optional divider can be
+specified after a /. The word "weapon" can be used in place of a skill name to
+refer to the default weapon skill for the simulation. For example:
+
+ fsim_scale = weapon, fighting/2
+
+The weapon skill will be scaled from 0 to 27, while the fighting skill will be
+kept at half the level of the weapon skill. This used to be the behaviour of
+the simulator in versions 0.10 and earlier.
+
+if XL is specified instead of a skill, then it will be used as the scale.
+Skills will be trained automatically, and the number provided for each skill
+will be used to set the training weight. For example:
+
+ fsim_scale = XL, weapon:5, fighting:2
+
+It means that 5/7 of XP will be used to train the weapon skill and 2/7 to train
+the fighting skill.
+
+/ and : are both recognised as separators in normal and XL mode. However,
+given that there meaning is completely different, it is recommended to use
+/ in normal mode and : in XL mode.
+
+fsim_kit: This option is useful to run a batch of simulations with different
+equipment. It takes a list of weapons separated by commas. Missiles can be
+specified after a /. The items won't be generated, they need to be in the
+character's inventory at the start of the simulation. Example:
+
+ fsim_kit = broad axe, crossbow / steel bolts, /javelins
diff --git a/crawl-ref/git-hooks/crawl-ref-cia b/crawl-ref/git-hooks/crawl-ref-cia
index 5fc3ee5434..52da83a4dd 100755
--- a/crawl-ref/git-hooks/crawl-ref-cia
+++ b/crawl-ref/git-hooks/crawl-ref-cia
@@ -189,6 +189,7 @@ $user =~ s/bstriegs/Wensley/;
$user =~ s/lothar.dierkes/ldierk/;
$user =~ s/brendan/bmh/;
$user =~ s/sbalady/nfogravity/;
+$user =~ s/ben\.striegel/Wensley/;
$rev = substr($commit, 0, 12);
diff --git a/crawl-ref/settings/runrest_messages.txt b/crawl-ref/settings/runrest_messages.txt
index 8d02d713f7..ef883e791c 100644
--- a/crawl-ref/settings/runrest_messages.txt
+++ b/crawl-ref/settings/runrest_messages.txt
@@ -39,6 +39,10 @@ stop = Your stomach is not as upset anymore. and you want to eat\.
stop = If you dropped the corpses? in your pack you could butcher
ignore = Your stomach is not as upset anymore
+# Enchantments
+#
+ignore = Your skin is crawling a little less now.
+
# Ghouls
#
: if you.race() == "Ghoul" then
diff --git a/crawl-ref/source/Makefile b/crawl-ref/source/Makefile
index c2252e777d..bd728b16d0 100644
--- a/crawl-ref/source/Makefile
+++ b/crawl-ref/source/Makefile
@@ -43,10 +43,15 @@
# USE_ICC -- set to use Intel's compiler
# LTO -- set for better optimization but slower compilation,
# requires gcc4.6+
-# ASSERTS -- set to enable assertion checks (implied in debug mode)
+# NOASSERTS -- set to disable assertion checks (ignored in debug mode)
# NOWIZARD -- set to disable wizard mode. Use if you have untrusted
# remote players without DGL.
#
+# PROPORTIONAL_FONT -- set to a .ttf file you want to use for a proportional
+# font; if not set, a copy of Bitstream Vera Sans
+# shipped with Crawl will be used
+# MONOSPACED_FONT -- monospaced font; Bitstream Vera Mono Sans
+#
# WEBTILES -- set to anything to compile for Webtiles
# WEBDIR -- place to hold the Webtiles client data. Can be either
# relative to prefix or absolute.
@@ -61,8 +66,6 @@
GAME = crawl
-ASSERTS = yes
-
# Disable GNU Make implicit rules and variables. Leaving them enabled will slow
# down MinGW and Cygwin builds by a very VERY noticeable degree. Besides, we have
# _explicit_ rules defined for everything. So we don't need them.
@@ -702,7 +705,7 @@ export CCACHE_CPP2 = yes
endif
endif
-ifdef ASSERTS
+ifndef NOASSERTS
DEFINES += -DASSERTS
endif
@@ -1158,8 +1161,8 @@ endif
do echo "dgn.load_des_file('$$x')"; \
done >>$(datadir_fp)/dat/dlua/loadmaps.lua
$(COPY) dat/lua/*.lua $(datadir_fp)/dat/lua/
- $(COPY) dat/database/*.txt $(datadir_fp)/dat/database/
- $(COPY) dat/descript/*.txt $(datadir_fp)/dat/descript/
+ $(COPY_R) dat/database/* $(datadir_fp)/dat/database/
+ $(COPY_R) dat/descript/* $(datadir_fp)/dat/descript/
$(COPY) ../docs/*.txt $(datadir_fp)/docs/
$(COPY) ../docs/develop/*.txt $(datadir_fp)/docs/develop/
$(COPY) ../docs/develop/levels/*.txt $(datadir_fp)/docs/develop/levels/
@@ -1288,6 +1291,9 @@ ifdef NO_INLINE_DEPGEN
$(QUIET_DEPEND)$(or $(DEPCXX),$(CXX)) -MM $(ALL_CFLAGS) -MT $*.o $< > $*.d
endif
$(QUIET_CXX)$(CXX) $(ALL_CFLAGS) $(INLINE_DEPGEN_CFLAGS) -c $< -o $@
+ifndef NO_INLINE_DEPGEN
+ @if [ -f $(@:%.o=%.d) ]; then touch -r $@ $(@:%.o=%.d); fi
+endif
icon.o: util/crawl.rc util/crawl.ico .cflags
$(QUIET_WINDRES)$(WINDRES) util/crawl.rc icon.o
diff --git a/crawl-ref/source/Makefile.obj b/crawl-ref/source/Makefile.obj
index b04b4dca92..89fa193a77 100644
--- a/crawl-ref/source/Makefile.obj
+++ b/crawl-ref/source/Makefile.obj
@@ -108,6 +108,7 @@ l_subvault.o \
l_travel.o \
l_view.o \
l_you.o \
+lang-fake.o \
lev-pand.o \
libutil.o \
los.o \
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc
index b45fb96d4d..37f0811cfc 100644
--- a/crawl-ref/source/abl-show.cc
+++ b/crawl-ref/source/abl-show.cc
@@ -445,9 +445,9 @@ static const ability_def Ability_List[] =
{ ABIL_MAKE_OKLOB_SAPLING, "Make oklob sapling", 0, 0, 0, 0, 60, ABFLAG_ZOTDEF},
{ ABIL_MAKE_BURNING_BUSH, "Make burning bush", 0, 0, 0, 0, 200, ABFLAG_ZOTDEF},
{ ABIL_MAKE_OKLOB_PLANT, "Make oklob plant", 0, 0, 0, 0, 250, ABFLAG_ZOTDEF},
- { ABIL_MAKE_ICE_STATUE, "Make ice statue", 0, 0, 50, 0, 2000, ABFLAG_ZOTDEF},
- { ABIL_MAKE_OCS, "Make crystal statue", 0, 0, 200, 0, 2000, ABFLAG_ZOTDEF},
- { ABIL_MAKE_SILVER_STATUE, "Make silver statue", 0, 0, 400, 0, 3000, ABFLAG_ZOTDEF},
+ { ABIL_MAKE_ICE_STATUE, "Make ice statue", 0, 0, 0, 0, 2000, ABFLAG_ZOTDEF},
+ { ABIL_MAKE_OCS, "Make crystal statue", 0, 0, 0, 0, 2000, ABFLAG_ZOTDEF},
+ { ABIL_MAKE_SILVER_STATUE, "Make silver statue", 0, 0, 0, 0, 3000, ABFLAG_ZOTDEF},
{ ABIL_MAKE_CURSE_SKULL, "Make curse skull",
0, 0, 600, 0, 10000, ABFLAG_ZOTDEF|ABFLAG_NECRO_MISCAST_MINOR},
{ ABIL_MAKE_TELEPORT, "Zot-teleport", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
@@ -472,9 +472,9 @@ static const ability_def Ability_List[] =
0, 30, 0, 0, 100, ABFLAG_ZOTDEF|ABFLAG_PERMANENT_HP},
{ ABIL_MAKE_ALTAR, "Make altar", 0, 0, 0, 0, 50, ABFLAG_ZOTDEF},
{ ABIL_MAKE_GRENADES, "Make grenades", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
- { ABIL_MAKE_SAGE, "Sage", 0, 0, 300, 0, 0, ABFLAG_ZOTDEF|ABFLAG_INSTANT},
+ { ABIL_MAKE_SAGE, "Sage", 0, 0, 0, 0, 0, ABFLAG_ZOTDEF|ABFLAG_STAT_DRAIN},
{ ABIL_REMOVE_CURSE, "Remove Curse",
- 0, 0, 300, 0, 0, ABFLAG_ZOTDEF|ABFLAG_STAT_DRAIN},
+ 0, 0, 0, 0, 0, ABFLAG_ZOTDEF|ABFLAG_STAT_DRAIN},
{ ABIL_RENOUNCE_RELIGION, "Renounce Religion", 0, 0, 0, 0, 0, ABFLAG_NONE},
};
@@ -1772,8 +1772,11 @@ static bool _do_ability(const ability_def& abil)
case ABIL_MAKE_SILVER_STATUE:
case ABIL_MAKE_CURSE_SKULL:
case ABIL_MAKE_LIGHTNING_SPIRE:
- if (!create_zotdef_ally(_monster_for_ability(abil), _zd_mons_description_for_ability(abil).c_str()))
+ if (!create_zotdef_ally(_monster_for_ability(abil),
+ _zd_mons_description_for_ability(abil).c_str()))
+ {
return (false);
+ }
break;
// End ZotDef Allies
@@ -1783,6 +1786,7 @@ static bool _do_ability(const ability_def& abil)
// ZotDef traps
case ABIL_MAKE_TELEPORT_TRAP:
+ // BUG: it's the trap's position, not yours, that should matter.
if ((you.pos() - env.orb_pos).abs() < 100)
{
mpr("Radiation from the Orb interferes with the trap's magic!");
@@ -1881,11 +1885,12 @@ static bool _do_ability(const ability_def& abil)
case ABIL_REMOVE_CURSE:
remove_curse();
- lose_stat(STAT_RANDOM, (1 + random2avg(4, 2)), false, "zot ability");
+ lose_stat(STAT_RANDOM, 1, false, "zot ability");
break;
case ABIL_MAKE_SAGE:
sage_card(20, DECK_RARITY_RARE);
+ lose_stat(STAT_RANDOM, 1 + random2(3), false, "zot ability");
break;
case ABIL_MUMMY_RESTORATION:
@@ -2173,8 +2178,8 @@ static bool _do_ability(const ability_def& abil)
break;
case ABIL_END_TRANSFORMATION:
- mpr("You feel almost normal.");
- you.set_duration(DUR_TRANSFORMATION, 2);
+ you.time_taken = div_rand_round(you.time_taken * 3, 2);
+ untransform();
break;
// INVOCATIONS:
@@ -3080,8 +3085,7 @@ std::vector<talent> your_talents(bool check_confused)
if (you.species == SP_TENGU
&& !you.attribute[ATTR_PERM_LEVITATION]
&& you.experience_level >= 5
- && (you.experience_level >= 15 || !you.airborne())
- && (!form_changed_physiology() || you.form == TRAN_LICH))
+ && (you.experience_level >= 15 || !you.airborne()))
{
// Tengu can fly, but only from the ground
// (until level 15, when it becomes permanent until revoked).
@@ -3097,7 +3101,6 @@ std::vector<talent> your_talents(bool check_confused)
}
if (you.attribute[ATTR_PERM_LEVITATION]
- && (!form_changed_physiology() || you.form == TRAN_LICH)
&& you.species == SP_TENGU && you.experience_level >= 5)
{
_add_talent(talents, ABIL_STOP_FLYING, check_confused);
diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc
index b63ab126f1..b6bc2823e0 100644
--- a/crawl-ref/source/abyss.cc
+++ b/crawl-ref/source/abyss.cc
@@ -385,7 +385,11 @@ static int _abyss_create_items(const map_mask &abyss_genlevel_mask,
true, items_level, 250);
move_item_to_grid(&thing_created, place);
if (thing_created != NON_ITEM)
+ {
items_placed++;
+ if (one_chance_in(ITEM_MIMIC_CHANCE))
+ mitm[thing_created].flags |= ISFLAG_MIMIC;
+ }
}
}
diff --git a/crawl-ref/source/acquire.cc b/crawl-ref/source/acquire.cc
index 04cd7f1d52..03d2be6a2c 100644
--- a/crawl-ref/source/acquire.cc
+++ b/crawl-ref/source/acquire.cc
@@ -669,7 +669,8 @@ static int _acquirement_staff_subtype(const has_vector& already_has)
bool found_enhancer = false;
int result = random2(NUM_STAVES);
-#define TRY_GIVE(x) { if (you.type_ids[OBJ_STAVES][x] != ID_KNOWN_TYPE) {result = x; found_enhancer = true;} }
+#define TRY_GIVE(x) { if (you.type_ids[OBJ_STAVES][x] != ID_KNOWN_TYPE) \
+ {result = x; found_enhancer = true;} }
switch (best_spell_skill)
{
case SK_FIRE_MAGIC: TRY_GIVE(STAFF_FIRE); break;
diff --git a/crawl-ref/source/actor.h b/crawl-ref/source/actor.h
index 48a6d7b50c..af20cb2c0a 100644
--- a/crawl-ref/source/actor.h
+++ b/crawl-ref/source/actor.h
@@ -106,6 +106,7 @@ public:
{
return const_cast<actor*>(this)->weapon(0);
}
+ virtual int has_claws(bool allow_tran = true) const = 0;
virtual item_def *shield() = 0;
virtual item_def *slot_item(equipment_type eq,
bool include_melded=false) = 0;
diff --git a/crawl-ref/source/areas.cc b/crawl-ref/source/areas.cc
index 708a8c32d8..6a5ff79905 100644
--- a/crawl-ref/source/areas.cc
+++ b/crawl-ref/source/areas.cc
@@ -170,8 +170,10 @@ static void _update_agrid()
}
- if (you.char_direction == GDT_ASCENDING && !env.orb_pos.origin())
+ if (you.char_direction == GDT_ASCENDING)
{
+ ASSERT(!env.orb_pos.origin());
+
const int r = 5;
_agrid_centres.push_back(area_centre(AREA_ORB, env.orb_pos, r));
los_glob los(env.orb_pos, LOS_DEFAULT);
diff --git a/crawl-ref/source/art-data.txt b/crawl-ref/source/art-data.txt
index 3f7f84326f..298416b34e 100644
--- a/crawl-ref/source/art-data.txt
+++ b/crawl-ref/source/art-data.txt
@@ -1053,6 +1053,51 @@ INT: 1
DEX: 1
BOOL: unided
+# This is the first of two amulets used to test suppression aura.
+# Together, they confer every randart effect except for a few that are
+# determined explicitly by checking whether a certain amulet is worn
+# (such as stasis is).
+# The first amulet tests all properties, but since some properties can have
+# either positive or negative levels (or some properties are mutually
+# exclusive), the second amulet tests negative and exclusive effects.
+# Obviously, because it contains every positive property in the game,
+# this should never be randomly generated!
+NAME: milk chocolate
+OBJ: OBJ_JEWELLERY/AMU_STASIS
+COLOUR: BROWN
+ACC: 60
+ANGRY: 1
+COLD: 3
+DAM: 60
+DEX: 3
+EV: 3
+FIRE: 3
+INT: 3
+MAGIC: 100
+METAB: 10
+MP: 10
+MUTATE: 6
+STEALTH: 100
+STR: 3
+BOOL: nogen, berserk, blink, cursed, elec, inv, lev, life, nospell, notelep, poison, seeinv
+
+# This is the second of two amulets used to test suppression. See above.
+NAME: dark chocolate
+OBJ: OBJ_JEWELLERY/AMU_RESIST_CORROSION
+COLOUR: DARKGREY
+ACC: -60
+COLD: -3
+DAM: -60
+DEX: -3
+EV: -3
+FIRE: -3
+INT: -3
+METAB: -10
+MP: -10
+STEALTH: -100
+STR: -3
+BOOL: nogen, rnd_tele
+
# This entry must always be last.
ENUM: DUMMY2
NAME: DUMMY UNRANDART 2
diff --git a/crawl-ref/source/artefact.cc b/crawl-ref/source/artefact.cc
index 1da45feb76..c93f03283d 100644
--- a/crawl-ref/source/artefact.cc
+++ b/crawl-ref/source/artefact.cc
@@ -731,39 +731,24 @@ static void _get_randart_properties(const item_def &item,
if (is_range_weapon(item))
{
- proprt[ARTP_BRAND] = SPWPN_NORMAL;
-
- if (one_chance_in(3))
+ proprt[ARTP_BRAND] = random_choose_weighted(
+ 2, SPWPN_SPEED,
+ 4, SPWPN_VENOM,
+ 4, SPWPN_VORPAL,
+ 4, SPWPN_FLAME,
+ 4, SPWPN_FROST,
+ 0);
+
+ if (atype == WPN_BLOWGUN)
+ proprt[ARTP_BRAND] = coinflip() ? SPWPN_SPEED : SPWPN_EVASION;
+ else if (atype == WPN_CROSSBOW)
{
- int tmp = random2(20);
-
- proprt[ARTP_BRAND] = (tmp >= 18) ? SPWPN_SPEED :
- (tmp >= 14) ? SPWPN_PENETRATION :
- (tmp >= 12) ? SPWPN_REAPING :
- (tmp >= 8) ? SPWPN_VENOM
- : SPWPN_VORPAL + random2(3);
-
- if (atype == WPN_BLOWGUN)
- proprt[ARTP_BRAND] = coinflip() ? SPWPN_SPEED : SPWPN_EVASION;
-
- // Removed slings from getting the venom attribute: they can
- // be branded with it now using Poison Weapon, and perma-branded
- // via vorpalise weapon.
-
- if (atype == WPN_CROSSBOW && one_chance_in(5))
+ // Penetration and electrocution are only allowed on
+ // crossbows. This may change in future.
+ if (one_chance_in(5))
proprt[ARTP_BRAND] = SPWPN_ELECTROCUTION;
-
- // XXX: Penetration is only allowed on crossbows. This may change
- // in future.
- if (atype != WPN_CROSSBOW && proprt[ARTP_BRAND] == SPWPN_PENETRATION)
- proprt[ARTP_BRAND] = SPWPN_NORMAL;
-
- // XXX: Only allow reaping brand on bows. This may change.
- if (atype != WPN_BOW && atype != WPN_LONGBOW
- && proprt[ARTP_BRAND] == SPWPN_REAPING)
- {
- proprt[ARTP_BRAND] = SPWPN_NORMAL;
- }
+ else if (one_chance_in(5))
+ proprt[ARTP_BRAND] = SPWPN_PENETRATION;
}
}
@@ -957,15 +942,11 @@ static void _get_randart_properties(const item_def &item,
power_level++;
}
- // prot_life - no necromantic brands on weapons allowed
+ // prot_life
if (!done_powers
&& one_chance_in(4 + power_level)
&& (aclass != OBJ_JEWELLERY || atype != RING_LIFE_PROTECTION)
- && (aclass != OBJ_ARMOUR || atype != ARM_PEARL_DRAGON_ARMOUR)
- && proprt[ARTP_BRAND] != SPWPN_DRAINING
- && proprt[ARTP_BRAND] != SPWPN_VAMPIRICISM
- && proprt[ARTP_BRAND] != SPWPN_PAIN
- && proprt[ARTP_BRAND] != SPWPN_REAPING)
+ && (aclass != OBJ_ARMOUR || atype != ARM_PEARL_DRAGON_ARMOUR))
{
proprt[ARTP_NEGATIVE_ENERGY] = 1;
power_level++;
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 0e9f6336ef..45c3116f82 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -454,7 +454,7 @@ static void _zappy(zap_type z_type, int power, bolt &pbolt)
else
{
pbolt.hit = (*zinfo->tohit)(power);
- if (wearing_amulet(AMU_INACCURACY))
+ if (player_effect_inaccuracy())
pbolt.hit = std::max(0, pbolt.hit - 5);
}
@@ -463,8 +463,10 @@ static void _zappy(zap_type z_type, int power, bolt &pbolt)
// One special case
if (z_type == ZAP_ICE_STORM)
+ {
pbolt.ench_power = power; // used for radius
-
+ pbolt.ex_size = power > 76 ? 3 : 2; // for tracer, overwritten later
+ }
if (pbolt.loudness == 0)
pbolt.loudness = zinfo->hit_loudness;
}
@@ -2253,6 +2255,63 @@ static void _create_feat_splash(coord_def center,
}
}
+static void _imb_explosion(actor *agent,
+ coord_def origin,
+ coord_def center,
+ dice_def dam)
+{
+ const int dist = grid_distance(center, origin);
+ if (dist == 0 || !x_chance_in_y(3, 2 + 2 * dist))
+ return;
+ bolt beam;
+ beam.name = "mystic blast";
+ beam.aux_source = "orb of energy";
+ beam.beam_source = agent->mindex();
+ beam.thrower = agent->is_player() ? KILL_YOU_MISSILE : KILL_MON_MISSILE;
+ beam.range = 3;
+ beam.hit = AUTOMATIC_HIT;
+ beam.damage = dam;
+ beam.glyph = dchar_glyph(DCHAR_FIRED_ZAP);
+ beam.colour = MAGENTA;
+ beam.flavour = BEAM_MMISSILE;
+ beam.obvious_effect = true;
+ beam.is_beam = false;
+ beam.is_explosion = false;
+ beam.is_tracer = false;
+ beam.aimed_at_spot = true;
+ if (you.see_cell(center))
+ beam.seen = true;
+ if (const monster* mons = agent->as_monster())
+ beam.source_name = mons->name(DESC_PLAIN, true);
+ beam.source = center;
+ bool first = true;
+ for (int x = -1; x <= 1; x++)
+ {
+ for (int y = -1; y <= 1; y++)
+ {
+ if (x == 0 && y == 0)
+ continue;
+ // Don't hit the caster (the explosion doesn't reach back that far).
+ if (origin == center + coord_def(x, y) || origin == center + coord_def(2 * x, 2 * y))
+ continue;
+ // Don't go far away from the caster (not enough momentum).
+ if (distance(origin, center + coord_def(2 * x, 2 * y)) > LOS_RADIUS_SQ)
+ continue;
+ if (x_chance_in_y(3, 4))
+ {
+ if (first)
+ {
+ mpr("The orb of energy explodes!");
+ noisy(10, center);
+ first = false;
+ }
+ beam.target = center + coord_def(2 * x, 2 * y);
+ beam.fire();
+ }
+ }
+ }
+}
+
bool bolt::is_bouncy(dungeon_feature_type feat) const
{
if (real_flavour == BEAM_CHAOS && feat_is_solid(feat))
@@ -2406,6 +2465,9 @@ void bolt::affect_endpoint()
{
place_cloud(CLOUD_FIRE, pos(), 5 + random2(5), agent());
}
+
+ if (name == "orb of energy")
+ _imb_explosion(agent(), source, pos(), damage);
}
bool bolt::stop_at_target() const
@@ -2499,11 +2561,8 @@ void bolt::affect_ground()
if (is_explosion && flavour == BEAM_SPORE
&& this->agent() && !this->agent()->is_summoned())
{
- if (env.grid(pos()) >= DNGN_FLOOR_MIN
- && env.grid(pos())<= DNGN_FLOOR_MAX)
- {
+ if (env.grid(pos()) == DNGN_FLOOR)
env.pgrid(pos()) |= FPROP_MOLD;
- }
if (x_chance_in_y(2, 21)
&& !crawl_state.game_is_zotdef() // Turn off in Zotdef
@@ -4403,6 +4462,10 @@ void bolt::affect_monster(monster* mon)
beam_hit -= 2 + random2(4);
}
+ // The monster may block the beam.
+ if (!engulfs && is_blockable() && attempt_block(mon))
+ return;
+
defer_rand r;
int rand_ev = random2(mon->ev);
int defl = mon->missile_deflection();
@@ -4438,10 +4501,6 @@ void bolt::affect_monster(monster* mon)
return;
}
- // The monster may block the beam.
- if (!engulfs && is_blockable() && attempt_block(mon))
- return;
-
update_hurt_or_helped(mon);
enable_attack_conducts(conducts);
@@ -5144,12 +5203,6 @@ void bolt::refine_for_explosion()
ex_size = 2;
}
- if (name == "orb of energy")
- {
- seeMsg = "The orb of energy explodes!";
- hearMsg = "You hear an explosion!";
- }
-
if (name == "metal orb")
{
seeMsg = "The orb explodes into a blast of deadly shrapnel!";
diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc
index 0b5ec54335..59d7e36c6d 100644
--- a/crawl-ref/source/chardump.cc
+++ b/crawl-ref/source/chardump.cc
@@ -195,6 +195,15 @@ static void _sdump_header(dump_params &par)
type += " DCSS";
par.text += " " + type + " version " + Version::Long();
+#ifdef USE_TILE_LOCAL
+ par.text += " (tiles)";
+#elif defined(USE_TILE_WEB)
+ if (::tiles.is_controlled_from_web())
+ par.text += " (webtiles)";
+ else
+#else
+ par.text += " (console)";
+#endif
par.text += " character file.\n\n";
}
@@ -1109,7 +1118,10 @@ static bool _sort_by_first(std::pair<int, FixedVector<int, 28> > a,
static void _sdump_spell_usage(dump_params &par)
{
std::vector<std::pair<int, FixedVector<int, 28> > > usage_vec;
- for (std::map<std::pair<caction_type, int>, FixedVector<int, 27> >::const_iterator sp = you.action_count.begin(); sp != you.action_count.end(); ++sp)
+ for (std::map<std::pair<caction_type, int>,
+ FixedVector<int, 27> >::const_iterator sp = you.action_count.begin();
+ sp != you.action_count.end();
+ ++sp)
{
if (sp->first.first != CACT_CAST)
continue;
@@ -1246,7 +1258,9 @@ static void _sdump_action_counts(dump_params &par)
for (int cact = 0; cact < NUM_CACTIONS; cact++)
{
std::vector<std::pair<int, FixedVector<int, 28> > > action_vec;
- for (std::map<std::pair<caction_type, int>, FixedVector<int, 27> >::const_iterator ac = you.action_count.begin(); ac != you.action_count.end(); ++ac)
+ for (std::map<std::pair<caction_type, int>,
+ FixedVector<int, 27> >::const_iterator ac =
+ you.action_count.begin(); ac != you.action_count.end(); ++ac)
{
if (ac->first.first != cact)
continue;
@@ -1261,7 +1275,9 @@ static void _sdump_action_counts(dump_params &par)
}
std::sort(action_vec.begin(), action_vec.end(), _sort_by_first);
- for (std::vector<std::pair<int, FixedVector<int, 28> > >::const_iterator ac = action_vec.begin(); ac != action_vec.end(); ++ac)
+ for (std::vector<std::pair<int, FixedVector<int, 28> > >
+ ::const_iterator ac = action_vec.begin();
+ ac != action_vec.end(); ++ac)
{
if (ac == action_vec.begin())
{
diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc
index 0eaf1d43bd..5386b71acf 100644
--- a/crawl-ref/source/cloud.cc
+++ b/crawl-ref/source/cloud.cc
@@ -23,6 +23,7 @@
#include "fprop.h"
#include "godconduct.h"
#include "los.h"
+#include "misc.h"
#include "mon-behv.h"
#include "monster.h"
#include "mapmark.h"
@@ -1106,7 +1107,10 @@ int actor_apply_cloud(actor *act)
cloud.announce_actor_engulfed(act);
}
if (player && cloud_max_base_damage > 0 && resist > 0)
+ {
canned_msg(MSG_YOU_RESIST);
+ maybe_id_resist(cloud_flavour);
+ }
if (player && cloud_flavour != BEAM_NONE)
expose_player_to_element(cloud_flavour, 7);
@@ -1191,6 +1195,7 @@ bool is_harmless_cloud(cloud_type type)
case CLOUD_NONE:
case CLOUD_TLOC_ENERGY:
case CLOUD_MAGIC_TRAIL:
+ case CLOUD_DUST_TRAIL:
case CLOUD_GLOOM:
case CLOUD_INK:
case CLOUD_DEBUGGING:
@@ -1240,9 +1245,17 @@ static const char *_terse_cloud_names[] =
"flame", "noxious fumes", "freezing vapour", "poison gas",
"black smoke", "grey smoke", "blue smoke",
"purple smoke", "translocational energy", "fire",
- "steam", "gloom", "ink", "blessed fire", "foul pestilence", "thin mist",
+ "steam", "gloom", "ink",
+#if TAG_MAJOR_VERSION > 32
+ "calcifying dust",
+#endif
+ "blessed fire", "foul pestilence", "thin mist",
"seething chaos", "rain", "mutagenic fog", "magical condensation",
- "raging winds", "calcifying dust",
+ "raging winds",
+#if TAG_MAJOR_VERSION == 32
+ "calcifying dust",
+#endif
+ "sparse dust",
};
static const char *_verbose_cloud_names[] =
@@ -1251,9 +1264,16 @@ static const char *_verbose_cloud_names[] =
"roaring flames", "noxious fumes", "freezing vapours", "poison gas",
"black smoke", "grey smoke", "blue smoke",
"purple smoke", "translocational energy", "roaring flames",
- "a cloud of scalding steam", "thick gloom", "ink", "blessed fire",
- "dark miasma", "thin mist", "seething chaos", "the rain",
- "mutagenic fog", "magical condensation", "raging winds", "calcifying dust",
+ "a cloud of scalding steam", "thick gloom", "ink",
+#if TAG_MAJOR_VERSION > 32
+ "calcifying dust",
+#endif
+ "blessed fire", "dark miasma", "thin mist", "seething chaos", "the rain",
+ "mutagenic fog", "magical condensation", "raging winds",
+#if TAG_MAJOR_VERSION == 32
+ "calcifying dust",
+#endif
+ "sparse dust",
};
std::string cloud_type_name(cloud_type type, bool terse)
@@ -1443,6 +1463,10 @@ int get_cloud_colour(int cloudno)
which_colour = ETC_MAGIC;
break;
+ case CLOUD_DUST_TRAIL:
+ which_colour = ETC_EARTH;
+ break;
+
case CLOUD_HOLY_FLAMES:
which_colour = ETC_HOLY;
break;
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index f2838e488a..874513f724 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -2651,9 +2651,9 @@ int list_wizard_commands(bool do_redraw_screen)
"<w>J</w> : Jiyva off-level sacrifice\n"
"\n"
"<yellow>Debugging commands</yellow>\n"
- "<w>f</w> : player combat damage stats\n"
- "<w>F</w> : combat stats with fsim_kit\n"
- "<w>Ctrl-F</w> : combat stats (monster vs PC)\n"
+ "<w>f</w> : quick fight simulation\n"
+ "<w>F</w> : single scale fsim\n"
+ "<w>Ctrl-F</w> : double scale fsim\n"
"<w>Ctrl-I</w> : item generation stats\n"
"<w>O</w> : measure exploration time\n"
"<w>Ctrl-t</w> : enter in-game Lua interpreter\n"
diff --git a/crawl-ref/source/dat/database/godspeak.txt b/crawl-ref/source/dat/database/godspeak.txt
index 4464bb4933..3c235a5b17 100644
--- a/crawl-ref/source/dat/database/godspeak.txt
+++ b/crawl-ref/source/dat/database/godspeak.txt
@@ -36,57 +36,8 @@ Xom grants you an implement of some kind.
"Take this token of my esteem."
Xom smiles on you.
-%%%%
-# Xom will give you a ring or amulet you can't currently use, due to
-# cursed equipment.
-Xom cursed gift
-
-"Perhaps you should try this instead."
-
-"Maybe this would work better."
"Catch!"
-
-w:1
-"Vanity is a pleasure."
-%%%%
-# If you're wearing a cursed ring, Xom will give you another ring.
-Xom ring gift
-
-"Try this."
-
-"Take this!"
-
-"Catch!"
-
-w:1
-"There is a nice ring to it."
-%%%%
-# Xom will choose a weapon of a different subtype from the one you're
-# currently wielding.
-Xom weapon gift
-
-"Perhaps you should try this instead."
-
-"Have you considered using one of these?"
-
-"How about this?"
-
-w:1
-"Variety is the spice of life."
-%%%%
-# If you're wearing a cursed cloak, Xom will give you either a cloak
-# or body armour.
-Xom armour gift
-
-"Perhaps you should try this instead."
-
-"Have you considered wearing one of these?"
-
-"Here you go."
-
-w:1
-"It's marvellous!"
%%%%
####################
# friendly summons
diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt
index 54e4cd5670..4b0d68c6f5 100644
--- a/crawl-ref/source/dat/database/monspeak.txt
+++ b/crawl-ref/source/dat/database/monspeak.txt
@@ -137,7 +137,7 @@ trick
gambit
-strategy
+trap
%%%%
_smoke_or_steam_
@@ -2703,7 +2703,7 @@ w:50
@The_monster@ says, "Did all the warriors here go to shield school or something?"
-@The_monster@ says, "So, are the fast ones nagas, or not?"
+@The_monster@ says, "So, why is that serpent talking?"
@The_monster@ says, "What sort of name is 'naga' anyway? They're not even good at nagging."
@@ -2713,7 +2713,7 @@ w:50
@The_monster@ says, "I'm sick of this place. Or maybe that's poison..."
-@The_monster@ says, "At least the fast ones don't have weapons."
+@The_monster@ says, "I hate mutated serpents."
@The_monster@ says, "So, nagas are stealthy? Don't make me laugh."
@@ -2953,6 +2953,10 @@ w:2
@The_monster@ says, "Maybe you can tell me! What exactly is a 'death cob'?"
@The_monster@ says, "Zombies? Skeletons? Don't you get bored without any real company?"
+
+@The_monster@ says, "Angels painted black are so last century."
+
+@The_monster@ says, "If you wanted the light to be dimmer, you could have said so."
%%%%
Okawaru Donald
@@ -4180,6 +4184,22 @@ _Ijyb_rare_
@The_monster@ screams @at_foe@, "No! No, no, no, no!"
@The_monster@ screams @at_foe@, "I no like you!"
+%%%%
+confused Ijyb
+
+@The_monster@ cowers and screams, "My head! Aaaah! Get out now!"
+
+@The_monster@ screams @at_foe@, "Me give you whole level! Then you leave me be!"
+
+@The_monster@ screams @at_foe@, "Me still stronger! You very nasty!"
+
+@The_monster@ screams @at_foe@, "Me deserve better than this!"
+
+@The_monster@ screams @at_foe@, "Me be nice to you! Me promise!"
+
+@The_monster@ screams @at_foe@, "Me back to killing you soon!"
+
+VISUAL:@The_monster@ clutches @possessive@ head and gibbers rapidly, swaying.
## END Ijyb ##
%%%%
############ ILSUIW ### a pretty merfolk witch
@@ -4669,6 +4689,20 @@ _Maud_rare_
@The_monster@ screams @at_foe@, "If you give me 'Entarex', I'll let you live!"
@The_monster@ asks @foe,@ "Will you think of me as you die?"
+%%%%
+confused Maud
+
+@The_monster@ thinks out loud, "I seem to be forgetting something..."
+
+@The_monster@ asks @foe,@ "What was I looking for, again?"
+
+@The_monster@ thinks out loud, "Enter... Enterror?"
+
+@The_monster@ wonders, "Who am I anyway?"
+
+VISUAL:@The_monster@'s expression loosens as @possessive@ mind turns inward.
+
+VISUAL:@The_monster@ slowly smiles as @possessive@ mind releases itself from mundane concerns.
## END Maud ##
%%%%
############ MAURICE ### A thief.
@@ -5625,8 +5659,6 @@ VISUAL:@The_monster@ bares @possessive@ teeth.
@The_monster@ says @to_foe@, "Don't bother to defend, it's @_pointless_@."
-@The_monster@ says @to_foe@, "I'll show you a few @_ploy_@s."
-
@The_monster@ shouts @at_foe@, "Now you die!"
@The_monster@ shouts @at_foe@, "@_ATTACK_@!!!"
diff --git a/crawl-ref/source/dat/database/pl/godspeak.txt b/crawl-ref/source/dat/database/pl/godspeak.txt
new file mode 100644
index 0000000000..9598f879e9
--- /dev/null
+++ b/crawl-ref/source/dat/database/pl/godspeak.txt
@@ -0,0 +1,765 @@
+############################################################
+# godspeak.txt contains the messages for divine speech.
+#
+# For an explanation of how to read godspeak.txt and how to
+# add new messages, see monster_speech.txt in the
+# docs/develop/ directory.
+############################################################
+%%%%
+# fall-back in case a keyword can't be found
+Xom general effect
+
+Xom chichocze.
+
+„A może spróbujemy tego?”
+
+„Albo może eksperyment, hmmm?”
+
+w:1
+„Ciekawe... Co ten przycisk robi?”
+%%%%
+##############################
+# Xom throwing stuff at you.
+##############################
+Xom general gift
+
+Xom udziela ci daru!
+
+„Łap!”
+
+„Trzymaj.”
+
+Xom manifestuje swą dobroć.
+
+Xom daje ci coś.
+
+„Weź to ustrojstwo.”
+
+„Weż to w dowód mego uszanowania.”
+
+Xom uśmiecha się do ciebie.
+
+„Proszę.”
+%%%%
+####################
+# friendly summons
+####################
+Xom single summon
+
+„Służ śmiertelnemu, moje dziecko!”
+
+„Służ mej zabawce!”
+
+Xom otwiera przejście.
+%%%%
+Xom single holy summon
+
+„Służ śmiertelnemu, moje zmylone dziecko!”
+
+„Służ mej zabawce, me wygnane dziecko!”
+
+Xom wzywa zaciekawionego sługę innego boga.
+
+Xom przynęca kogoś na ten świat.
+
+„Zabawka dla zabawki!”
+
+„Ciekawe która zabawka dłużej wytrzyma.”
+
+Xom otwiera przejście.
+%%%%
+# higher demonic being
+Xom single major demon summon
+
+Xom daje ci demonicznego asystenta.
+
+Xom daje ci demonicznego sługę.
+
+Xom otwiera przejście.
+%%%%
+Xom single major holy summon
+
+Xom daje ci asystenta wziętego innemu bogu.
+
+Xom przekabaca sługę innego boga, aby ci służył.
+
+„A skąd to przyszło? Dobrze, dobrze.”
+
+Ciekawe skąd Xom wziął tą istotę.
+
+Wygląda że Xomowi udało się znowu zmylić jakiegoś innego boga.
+
+Xom otwiera przejście.
+%%%%
+# several demons
+Xom multiple summons
+
+„Służcie śmiertelnemu, me dzieci!”
+
+Xom daje ci tymczasową pomoc.
+
+Xom na chwilę otwiera przejście.
+%%%%
+# holy beings and demons at the same time
+Xom multiple mixed summons
+
+Xom wzywa mieszane towarzystwo.
+
+„Służcie zabawce, moja zbieranino!”
+
+Xom przyzywa pomieszaną pomoc.
+
+„O, jaki fajny plac zabaw!”
+
+Xom sprowadza kilka różnych istot na ten świat.
+
+Xom na chwilę otwiera kilka przejść.
+%%%%
+Xom multiple holy summons
+
+Xom miesza wśród sług innych bogów.
+
+Xom wzywa marnotrawne sługi innych bogów.
+
+Xom mąci innym bogom, wzywając ich sługi.
+
+„Inny bóg, inna zabawka.”
+
+Xom otwiera przejście.
+%%%%
+# changing the scenery
+Xom scenery
+
+Dotyk Xoma muska twe otoczenie.
+
+Xom robi małe zmiany.
+
+Xom narzeka na dekoracje.
+
+Xom przerabia loch wokół ciebie.
+
+„Tak chyba wygląda lepiej.”
+
+„Tylko tą małą poprawkę...”
+%%%%
+##################
+# Xom nastiness
+##################
+# miscast strength 0, mostly harmless
+Xom zero miscast effect
+
+Xom niemal cię zauważa.
+
+Xom prawie zwraca na ciebie uwagę.
+
+Moc Xoma prawie cię dotyka.
+
+Niemal słyszysz szalony śmiech Xoma.
+%%%%
+# miscast strength random2(2), harmless/annoying
+Xom minor miscast effect
+
+Xom cię zauważa.
+
+Xom wraca na na ciebie uwagę.
+
+Moc Xoma cię dotyka.
+
+Słyszysz szalony śmiech Xoma.
+%%%%
+# miscast strength random2(3), mostly annoying
+Xom medium miscast effect
+
+@Xom minor miscast effect@
+%%%%
+# miscast strength random2(4), up to really nasty
+Xom major miscast effect
+
+„Spróbuj tego.”
+
+Xom patrzy na ciebię.
+
+Moc Xoma cię dotyka.
+
+Xom dziko chichocze.
+
+w:1
+„Zróbmy trochę crash testów na tej zabawce.”
+%%%%
+Xom lose stats
+
+„Cierp!”
+
+Czujesz na sobie złośliwy wzrok Xoma.
+
+Moc Xoma cię dotyka.
+
+Słyszysz szalony śmiech Xoma.
+%%%%
+Xom rearrange the pieces
+
+Xom przestawia.
+
+„Najpierw tu, potem tam.”
+
+„Tak chyba będzie lepiej!”
+%%%%
+Xom swap weapons
+
+@Xom rearrange the pieces@
+%%%%
+Xom teleportation journey
+
+„Jauuuu!”
+
+„Chodźmy na przejażdżkę!”
+
+„Dokąd to prowadzi, któż to wie!”
+
+Xom zakrzywia przestrzeń wokół ciebie.
+%%%%
+Xom confusion
+
+„He he he...”
+
+Moc Xoma ćmi ci umysł.
+
+Xom nerwowo chichocze.
+%%%%
+# 25% chance of draining, else torment
+Xom draining or torment
+
+„Zezłościłeś mnie, śmiertelniku.”
+
+„A ty myślisz że kim jesteś?”
+
+„Znaj swe miejsce!”
+
+Słyszysz szalony śmiech Xoma.
+%%%%
+# 25% chance dancing weapon, else summon hostile monster
+Xom hostile monster
+
+„Czas na zabawę!”
+
+„Walcz o życie, śmiertelniku!”
+
+„Zobaczmy czy zabawka sobie z tym poradzi.”
+
+Słyszysz szalony śmiech Xoma.
+%%%%
+Xom animate monster weapon
+
+@Xom hostile monster@
+%%%%
+Xom banishment
+
+„Zbyt się przywiązujesz do tego świata, śmiertelniku!”
+
+Xom rzuca cię w Otchłań!
+
+Świat wiruje, a w uszach dzwoni ci śmiechem Xoma.
+%%%%
+Xom revert banishment
+
+w:30
+„Żartowałem!”
+
+„A w zasadzie, ...”
+
+„Nie, jednak nie.”
+
+Xom wciąga cię z powrotem.
+%%%%
+# Xom upgrades a nearby hostile monster's weapon to a chaos brand
+Xom chaos upgrade
+
+Moc Xoma dotyka pobliskiej broni.
+
+„Poczuj smak chaosu.”
+
+Xom rechocze.
+%%%%
+#####################
+# other effects
+#####################
+Xom potion effect
+
+„Idź i niszcz!”
+
+„Idź i rozrabiaj!”
+
+Xom daje ci pomniejszą łaskę.
+
+Xom się do ciebie uśmiecha.
+%%%%
+# random divination (magic mapping, detect items, detect creatures)
+Xom divination
+
+„Zobacz co ja widzę, me dziecko!”
+
+Xom oświeca cię.
+
+Xom się głupio uśmiecha.
+%%%%
+# cast a random spell
+Xom spell effect
+
+Moc Xoma płynie przez ciebie!
+
+Xom bawi się rzeczywistością.
+
+Xom rubasznie rechocze.
+%%%%
+# multicoloured smoke trail
+Xom colour smoke trail
+
+„Idź i dekoruj, me dziecię!”
+
+„Przydałoby się trochę nastroju.”
+%%%%
+# turns walls into glass
+Xom vitrification
+
+Widać cię!
+
+Czujesz na sobie wzrok wszystkich wokół.
+
+Ściany wokół robią się przejrzyste.
+
+Xom dotyka lochów wokół ciebie.
+%%%%
+# strengthens friendlies, weakens hostiles
+Xom good monster polymorph
+
+„Tak będzie lepiej!”
+
+„Tam dam tam dam...”
+
+Xom dotyka kogoś w pobliżu.
+
+Słyszysz ojcowski chichot Xoma.
+%%%%
+# weakens friendlies, strengthens hostiles
+Xom bad monster polymorph
+
+@Xom good monster polymorph@
+%%%%
+Xom good mutations
+
+„Potrzebujesz małych poprawek, śmiertelniku!”
+
+„Pozwól mi cię poprawić.”
+
+Xom zmienia twe ciało.
+
+Słyszysz szalony chichot Xoma.
+%%%%
+Xom random mutations
+
+„Potrzebujesz małych poprawek, śmiertelniku!”
+
+„Pozwól mi cię zmienić.”
+
+Moc Xoma przenicowuje cię na chwilę.
+
+Słyszysz ojcowski chichot Xoma.
+%%%%
+Xom snakes to sticks
+
+Xom przemienia węże.
+
+„Wolę tak.”
+
+„Nigdy nie lubiłem tych oślizgłych paskudztw.”
+
+@Xom good monster polymorph@
+%%%%
+Xom inner flame
+
+„Płoń!”
+
+„Niech wszystko spłonie!”
+
+Xom podkręca ogrzewanie.
+%%%%
+Xom accidental homicide
+
+„Uuups, to nie miało tak być!”
+
+„To nie tak, przepraszam.”
+%%%%
+Xom weird death
+
+„A jak »to« się stało? Dziwne.”
+%%%%
+Xom resurrection
+
+„Pozwól mi cię naprawić.”
+
+Xom cię ożywia.
+
+Nawet Śmierć boi się szajby Xoma.
+
+Xom przywraca cię do życia.
+
+Xom się do ciebie uśmiecha.
+%%%%
+Xom repel stairs
+
+Xom zmienia architekturę.
+
+Xom dotyka @staircase@.
+
+„Berek!”
+%%%%
+Xom life saving general
+
+„Jak? Poczekaj, nie!”
+
+„Eee, już robiło się ciekawie.”
+
+„NIEEEEEE, nie moja @xom_plaything@!”
+
+„Nie tak, nie teraz.”
+
+Xom ma dobry nastrój.
+%%%%
+Xom life saving actor
+
+w:20
+@Xom life saving general@
+
+„Hej, to moja @xom_plaything@!”
+
+„O nie, łapy precz!”
+
+„To moja @xom_plaything@, znajdź sobie własną!”
+
+„Zostaw moją zabawkę w spokoju!”
+%%%%
+Xom boring death
+
+Xom głośno ziewa!
+
+„Nudne życie, nudna śmierć...”
+
+„Co, już?”
+
+„Taak, potrzeba mi lepszej rozrywki.”
+
+„Eee, nudy.”
+%%%%
+# Xom laughing
+# (Currently only used post-game in response to "You die...")
+Xom laughter
+
+Xom rechocze.
+
+Xom ryczy ze śmiechu.
+
+Xom uważa że to zabawne.
+
+Xom chichocze.
+
+Xom się smieje.
+%%%%
+############################################
+# Beogh rants on destroying an orcish idol #
+############################################
+# Beogh's messiah has destroyed an idol
+Beogh idol follower
+
+Beogh się złości: „To niemały grzech, orku!”
+
+Beogh szepcze: „Będziesz cierpiał za tą sprawkę.”
+
+Beogh się gniewa: „Oko za oko, ząb za ząb.”
+%%%%
+# an unbelieving hill orc has destroyed an idol
+Beogh idol hill orc
+
+Beogh grzmi: „Giń, heretyku!”
+
+Słyszysz grzmiący głos Beogha: „Cierp, niewierny!”
+
+Beogh ryczy: „Poczuj mą moc, odstępco!”
+%%%%
+# a character of another species has destroyed an idol
+Beogh idol other
+
+Beogh nie jest zachwycony zniszczeniem tego posągu.
+
+Beogh wydaje się być mocno rozgniewany.
+
+To mocno wkurzyło Beogha.
+
+Beogh rzuca klątwę na twój rodzaj.
+
+Beogh przeklina wszyskich nie-orków.
+
+Beogh obiecuje ci wieczną wrogość.
+%%%%
+#################################################
+# The Shining One rants on killing a holy being #
+#################################################
+# an evil worshipper has killed a holy being
+the Shining One holy evil
+
+Świetlisty grzmi: „Zaprzestań tych podłych ataków na boskość!”
+
+Świetlisty woła: „Ta śmierć nie pozostanie bez pomsty!”
+
+Świetlisty woła: „Twe grzechy będą pamiętane aż do końca świata!”
+
+Świetlisty szepcze: „Śiły światła spalą cię na popiół.”
+%%%%
+# a non-good worshipper or atheist has killed a holy being
+the Shining One holy other
+
+Świetlisty mówi: „Tak jak święte życia się kończą, tak skończy się twoje.”
+
+Świetlisty mówi: „Czas oddzielić ziarno od plew.”
+
+Świetlisty mówi: „Pamięć o męczennikach nie zaginie.”
+
+w:1
+Świetlisty rzecze, „Oko za oko, ząb za ząb.”
+%%%%
+##########################################
+# Elyvilon hates you killing her animals #
+##########################################
+Elyvilon holy
+
+Elyvilon syczy: „Ty podła bestio! Jak możesz?!”
+
+Elyvilon mówi ze smutkiem: „Jak to możliwe że takie okrucieństwo w ogóle istnieje.”
+
+Elyvilon szepcze: „Nikt nie powinien krzywdzić innych. Nigdy!”
+%%%%
+recite_closure
+
+„Amen!”
+
+„Chwała Zinowi!”
+
+„I tak napisano.”
+
+„Tako rzecze Zin.”
+
+„Niech czystość będzie z wami.”
+%%%%
+##########################
+# Xom's response to prayer
+##########################
+Xom prayer
+
+Xom zdziela cię @_Xom_zdziela_@!
+
+Xom wesoło popiarduje.
+
+Xom rzecze: Widzę cię!
+
+Nic się nie dzieje. Chyba...
+
+w:1
+Ktoś cię uszczypnął. Ale za tobą nikogo nie ma!
+
+w:1
+Xom mówi: Amen!
+%%%%
+_Xom_zdziela_
+
+poduszką
+
+zdechłą rybą
+
+śmierdzącym jajem
+
+workiem buraków
+
+starym kaloszem
+
+kapciem
+%%%%
+######################################
+# Welcome messages on game restoration
+######################################
+Ashenzari penance
+
+@Ashenzari welcome@
+%%%%
+Ashenzari welcome
+
+Ashenzari rzecze: Weź udział w mej wizji. Weź udział w mym przekleństwie.
+%%%%
+Beogh penance
+
+Beogh rzecze: Ośmiel się okazać litość nie-orkom i każę cię zgładzić.
+%%%%
+Beogh welcome
+
+Beogh rzecze: Utop niewiernych w morzu krwi!
+%%%%
+Beogh newgame
+
+@Beogh welcome@
+%%%%
+Cheibriados penance
+
+Cheibriados rzecze: Nie tak szybko! Zwolnij!
+%%%%
+Cheibriados welcome
+
+Cheibriados mówi: Wyluzuj się.
+%%%%
+Elyvilon penance
+
+Elyvilon prosi: Błagam cię, więcej uwagi przy niesieniu pomocy!
+%%%%
+Elyvilon welcome
+
+Elyvilon mówi: Idź i pomóż cierpiącym!
+%%%%
+Elyvilon newgame
+
+@Elyvilon welcome@
+%%%%
+Fedhas penance
+
+Fedhas protestuje przeciw twemu psuciu środowiska.
+%%%%
+Fedhas welcome
+
+Fedhas rzecze: Nieś życie i śmierć.
+%%%%
+Jiyva penance
+
+@Jiyva welcome@
+%%%%
+Jiyva welcome
+
+Śluz dla boga śluzu!
+%%%%
+Kikubaaqudgha penance
+
+@Kikubaaqudgha welcome@
+%%%%
+Kikubaaqudgha welcome
+
+Kikubaaqudgha rzecze: Szerz ciemność i męczarnie bez końca!
+%%%%
+Lugonu penance
+
+@Lugonu welcome@
+%%%%
+Lugonu welcome
+
+Lugonu rzecze: Szerz rzeź i zepsucie!
+%%%%
+Lugonu newgame
+
+Lugonu mówi: Przejdź przez tą bramę, lub wezmij mnie, by sprowadzić cię na świat!
+%%%%
+Makhleb penance
+
+@Makhleb welcome@
+%%%%
+Makhleb welcome
+
+Krew i dusze dla Makhleba!
+%%%%
+Nemelex Xobeh penance
+
+@Nemelex Xobeh welcome@
+%%%%
+Nemelex Xobeh welcome
+
+Nemelex Xobeh mówi: Wszystko znajdziesz w kartach!
+%%%%
+Okawaru penance
+
+Okawaru gani cię: Nie bądź podłym tchórzem tym razem!
+%%%%
+Okawaru welcome
+
+Okawaru wzywa: Przynieś mi chwałę w walce!
+%%%%
+Sif Muna penance
+
+Sif Muna wścieka się: Więcej uwagi, nieuku!
+%%%%
+Sif Muna welcome
+
+Sif Muna szepcze: Znam wiele sekretów...
+%%%%
+the Shining One penance
+
+Świetlisty rzecze: Możesz jeszcze zmyć swój grzech jako męczennik!
+%%%%
+the Shining One welcome
+
+Świetlisty rzecze: Poprowadź siły światła ku zwycięstwu!
+%%%%
+Trog penance
+
+Trog mamrocze: Ach, to znowu ten marny gryzipiórek...
+%%%%
+Trog welcome
+
+Trog woła: Zabij ich wszystkich!
+%%%%
+Trog newgame
+
+@Trog welcome@
+%%%%
+Vehumet penance
+
+@Vehumet welcome@
+%%%%
+Vehumet welcome
+
+Vehumet woła: Niech wszystko spłonie!
+%%%%
+Xom bored
+
+Xom ziewa.
+
+„Ciekawe co dzieje się gdzie indziej...”
+
+@Xom generic@
+%%%%
+Xom newgame
+
+Xom woła: Nowa zabawka!
+%%%%
+Xom generic
+
+Xom chichocze.
+%%%%
+Yredelemnul penance
+
+Yredelemnul rzecze: Wszyscy umrą! Święte męczeństwo nie jest nic warte!
+%%%%
+Yredelemnul welcome
+
+Yredelemnul rzecze: Nieś czarną pochodnię! Podnieś bezczynnych zmarłych!
+%%%%
+Yredelemnul newgame
+
+@Yredelemnul welcome@
+%%%%
+Zin penance
+
+Zin potępia cię za nieposłuszeństwo prawu.
+
+Zin stanowczo wyjaśnia powagę @_important_subject_@
+%%%%
+Zin welcome
+
+Zin rzecze: Nieś światło, me dziecię.
+%%%%
+Zin newgame
+
+@Zin welcome@
+%%%%
diff --git a/crawl-ref/source/dat/database/quotes.txt b/crawl-ref/source/dat/database/quotes.txt
index 1307dde8ba..0c3592cadd 100644
--- a/crawl-ref/source/dat/database/quotes.txt
+++ b/crawl-ref/source/dat/database/quotes.txt
@@ -4,7 +4,7 @@
####################################################
Tomb
-"In the depths of every heart, there is a tomb and a dungeon, though the lights, the music, and revelry above may cause us to forget their existence, and the buried ones, or prisoners whom they hide. But sometimes, and oftenest at midnight, those dark receptacles are flung wide open. In an hour like this, when the mind has a passive sensibility, but no active strength; when the imagination is a mirror, imparting vividness to all ideas, without the power of selecting or controlling them; then pray that your grieves may slumber, and the brotherhood of remorse not break their chain."
+“In the depths of every heart, there is a tomb and a dungeon, though the lights, the music, and revelry above may cause us to forget their existence, and the buried ones, or prisoners whom they hide. But sometimes, and oftenest at midnight, those dark receptacles are flung wide open. In an hour like this, when the mind has a passive sensibility, but no active strength; when the imagination is a mirror, imparting vividness to all ideas, without the power of selecting or controlling them; then pray that your grieves may slumber, and the brotherhood of remorse not break their chain.”
-Nathaniel Hawthorne
%%%%
####################################################
@@ -12,75 +12,75 @@ Tomb
####################################################
A gas trap
-"Good your grace, an' I had room for such a thundergust within mine ancient
-bowels, 'tis not in reason I coulde discharge ye same and live to thank God
-for yt. He did choose handmaid so humble whereby to shew his power. Nay, 'tis
-not I yt have broughte forth this rich o'ermastering fog, this fragrant
-gloom, so pray you seeke ye further."
- -Mark Twain, "1601", 1880.
+“Good your grace, an’ I had room for such a thundergust within mine ancient
+bowels, ’tis not in reason I coulde discharge ye same and live to thank God
+for yt. He did choose handmaid so humble whereby to shew his power. Nay, ’tis
+not I yt have broughte forth this rich o’ermastering fog, this fragrant
+gloom, so pray you seeke ye further.”
+ -Mark Twain, “1601”, 1880.
%%%%
A gateway to a ziggurat
-"Captain: Take off every 'zig'!!
- Captain: For great justice."
+“Captain: Take off every ‘zig’!!
+ Captain: For great justice.”
-Zero Wing
%%%%
A gateway to Hell
-"Lasciate ogne speranza, voi ch'intrate."
- -Dante Alighieri, _Divina Commedia_, "L'Inferno", Canto III. Circa 1315.
+“Lasciate ogne speranza, voi ch’intrate.”
+ -Dante Alighieri, _Divina Commedia_, “L’Inferno”, Canto III. Circa 1315.
%%%%
A granite statue
-"I met a traveller from an antique land
+“I met a traveller from an antique land
Who said: Two vast and trunkless legs of stone
Stand in the desert. Near them on the sand,
- Half sunk, a shatter'd visage lies, whose frown
+ Half sunk, a shatter’d visage lies, whose frown
And wrinkled lip and sneer of cold command
Tell that its sculptor well those passions read
- Which yet survive, stamp'd on these lifeless things,
- The hand that mock'd them and the heart that fed.
+ Which yet survive, stamp’d on these lifeless things,
+ The hand that mock’d them and the heart that fed.
And on the pedestal these words appear:
- 'My name is Ozymandias, king of kings:
- Look on my works, ye Mighty, and despair!'
+ ‘My name is Ozymandias, king of kings:
+ Look on my works, ye Mighty, and despair!’
Nothing beside remains: round the decay
Of that colossal wreck, boundless and bare,
- The lone and level sands stretch far away."
- -Percy Bysshe Shelley, "Ozymandias". 1818.
+ The lone and level sands stretch far away.”
+ -Percy Bysshe Shelley, “Ozymandias”. 1818.
%%%%
A labyrinth entrance
-"Maze-treaders, whose vision ahead and behind is severely constricted and fragmented, suffer confusion, whereas maze-viewers who see the pattern whole, from above or in a diagram, are dazzled by its complex artistry. What you see depends on where you stand, and thus, at one and the same time, labyrinths are single (there is one physical structure) and double: they simultaneously incorporate order and disorder, clarity and confusion, unity and multiplicity, artistry and chaos."
- -Mark Z. Danielewski, "House of Leaves". 2000.
+“Maze-treaders, whose vision ahead and behind is severely constricted and fragmented, suffer confusion, whereas maze-viewers who see the pattern whole, from above or in a diagram, are dazzled by its complex artistry. What you see depends on where you stand, and thus, at one and the same time, labyrinths are single (there is one physical structure) and double: they simultaneously incorporate order and disorder, clarity and confusion, unity and multiplicity, artistry and chaos.”
+ -Mark Z. Danielewski, “House of Leaves”. 2000.
%%%%
A one-way gate to the infinite horrors of the Abyss
-"And if you gaze for long into an abyss, the abyss gazes also into you."
- -Friedrich Nietzsche, "Beyond Good and Evil"
+“And if you gaze for long into an abyss, the abyss gazes also into you.”
+ -Friedrich Nietzsche, “Beyond Good and Evil”
%%%%
A portal to a secret trove of treasure
-"'Stop thief! Stop thief!' There is a magic in the sound. The tradesman leaves his counter, and the car-man his waggon; the butcher throws down his tray; the baker his basket; the milkman his pail; the errand-boy his parcels; the school-boy his marbles; the paviour his pickaxe; the child his battledore. Away they run, pell-mell, helter-skelter, slap-dash: tearing, yelling, screaming, knocking down the passengers as they turn the corners, rousing up the dogs, and astonishing the fowls: and streets, squares, and courts, re-echo with the sound."
- -Charles Dickens, "Oliver Twist"
+“‘Stop thief! Stop thief!’ There is a magic in the sound. The tradesman leaves his counter, and the car-man his waggon; the butcher throws down his tray; the baker his basket; the milkman his pail; the errand-boy his parcels; the school-boy his marbles; the paviour his pickaxe; the child his battledore. Away they run, pell-mell, helter-skelter, slap-dash: tearing, yelling, screaming, knocking down the passengers as they turn the corners, rousing up the dogs, and astonishing the fowls: and streets, squares, and courts, re-echo with the sound.”
+ -Charles Dickens, “Oliver Twist”
%%%%
A rock wall
-"I know not whether Laws be right,
+“I know not whether Laws be right,
Or whether Laws be wrong;
All that we know who lie in gaol
Is that the wall is strong;
And that each day is like a year,
- A year whose days are long."
- -Oscar Wilde, "Ballad of Reading Gaol"
+ A year whose days are long.”
+ -Oscar Wilde, “Ballad of Reading Gaol”
%%%%
A staircase to the Tomb
-"In the depths of every heart, there is a tomb and a dungeon, though the lights, the music, and revelry above may cause us to forget their existence, and the buried ones, or prisoners whom they hide. But sometimes, and oftenest at midnight, those dark receptacles are flung wide open. In an hour like this, when the mind has a passive sensibility, but no active strength; when the imagination is a mirror, imparting vividness to all ideas, without the power of selecting or controlling them; then pray that your grieves may slumber, and the brotherhood of remorse not break their chain."
+“In the depths of every heart, there is a tomb and a dungeon, though the lights, the music, and revelry above may cause us to forget their existence, and the buried ones, or prisoners whom they hide. But sometimes, and oftenest at midnight, those dark receptacles are flung wide open. In an hour like this, when the mind has a passive sensibility, but no active strength; when the imagination is a mirror, imparting vividness to all ideas, without the power of selecting or controlling them; then pray that your grieves may slumber, and the brotherhood of remorse not break their chain.”
-Nathaniel Hawthorne
%%%%
A tree
-"Only YOU can prevent forest fires!"
+“Only YOU can prevent forest fires!”
-Smokey the Bear
%%%%
####################################################
@@ -88,128 +88,128 @@ A tree
####################################################
Ice Storm
-"Neither Deluge Nor Ice Storm Nor The Black Silence Of The Netherhells Shall Stay These Messengers About Their Sacred Business. Do Not Ask Us About Sabre-Tooth Tigers, Tar Pits, Big Green Things With Teeth Or The Goddess Czol."
- -Anghammarad, "Going Postal", Terry Pratchett.
+“Neither Deluge Nor Ice Storm Nor The Black Silence Of The Netherhells Shall Stay These Messengers About Their Sacred Business. Do Not Ask Us About Sabre-Tooth Tigers, Tar Pits, Big Green Things With Teeth Or The Goddess Czol.”
+ -Anghammarad, “Going Postal”, Terry Pratchett.
%%%%
####################################################
# Items
####################################################
apple
-"MINERVA was the goddess of wisdom, but on one occasion she did a very foolish thing; she entered into competition with Juno and Venus for the prize of beauty. It happened thus: At the nuptials of Peleus and Thetis all the gods were invited with the exception of Eris, or Discord. Enraged at her exclusion, the goddess threw a golden apple among the guests, with the inscription, 'For the fairest.'"
- -Bullfinch's Mythology, Chap. XXVII. a.
+“MINERVA was the goddess of wisdom, but on one occasion she did a very foolish thing; she entered into competition with Juno and Venus for the prize of beauty. It happened thus: At the nuptials of Peleus and Thetis all the gods were invited with the exception of Eris, or Discord. Enraged at her exclusion, the goddess threw a golden apple among the guests, with the inscription, ‘For the fairest.’”
+ -Bullfinch’s Mythology, Chap. XXVII. a.
%%%%
apricot
-"Apricot Ratafia
+“Apricot Ratafia
-This is made two Ways, viz. either by infusing the Apricots cut in Pieces in Brandy for a Day or two, and then passing it thro' the draining Bag, and putting in the usual Ingredients; or else the Apricots may be boil'd in White wine, and by that Means more easily clarify'd adding an equal Quantity of Brandy, and a quarter of a pound of Sugar to every quart, with Cinnamon, Cloves, Mace, and Kernels of the Apricots. After all the Ingredients have infused eight or ten Days the Liquor is to be strain'd again and put into Bottles and so kept."
- -Charles Carter, _The Compleat City and Country Cook: Or, Accomplish'd House-wife_. 1732.
+This is made two Ways, viz. either by infusing the Apricots cut in Pieces in Brandy for a Day or two, and then passing it thro’ the draining Bag, and putting in the usual Ingredients; or else the Apricots may be boil’d in White wine, and by that Means more easily clarify’d adding an equal Quantity of Brandy, and a quarter of a pound of Sugar to every quart, with Cinnamon, Cloves, Mace, and Kernels of the Apricots. After all the Ingredients have infused eight or ten Days the Liquor is to be strain’d again and put into Bottles and so kept.”
+ -Charles Carter, _The Compleat City and Country Cook: Or, Accomplish’d House-wife_. 1732.
%%%%
bread ration
-"It is further reported that in the provinces [Caesar] gave banquets constantly in two dining halls, in one of which his officers or Greek companions, in the other Roman civilians and the more distinguished of the provincials reclined at table. He was so punctilious and strict in the management of his household, in small matters as well as in those of greater importance, that he put his baker in irons for serving him with one kind of bread and his guests with another..."
+“It is further reported that in the provinces [Caesar] gave banquets constantly in two dining halls, in one of which his officers or Greek companions, in the other Roman civilians and the more distinguished of the provincials reclined at table. He was so punctilious and strict in the management of his household, in small matters as well as in those of greater importance, that he put his baker in irons for serving him with one kind of bread and his guests with another...”
-Suetonius, _De Vita Caesarum, Divus Iulius_. 110 CE.
%%%%
choko
-"I ought not to omit naming a vegetable which Mr Yates placed on our table, and to which he directed our attention. It was the Tchu-tchu (Sechium edule) called also by the people _pepinella_. It is a small gourd, very much like vegetable marrow; one seed covers a wall with its ramifications."
- -John Overton Choules, _The Cruise of the Steam Yacht North Star: A Narrative of the Excursion of Mr. Vanderbilt's Party to England, Russia, Denmark, France, Spain, Malta, Turkey, Madeira, Etc_. 1854.
+“I ought not to omit naming a vegetable which Mr Yates placed on our table, and to which he directed our attention. It was the Tchu-tchu (Sechium edule) called also by the people _pepinella_. It is a small gourd, very much like vegetable marrow; one seed covers a wall with its ramifications.”
+ -John Overton Choules, _The Cruise of the Steam Yacht North Star: A Narrative of the Excursion of Mr. Vanderbilt’s Party to England, Russia, Denmark, France, Spain, Malta, Turkey, Madeira, Etc_. 1854.
%%%%
cloak
-"O Bell my wife, why dost thou flyte?
+“O Bell my wife, why dost thou flyte?
Now is now, and then was then:
Seek now all the world throughout,
Thou kens not clowns from gentlemen:
They are clad in black, green, yellow and blue,
So far above their own degree.
- Once in my life I'll take a view;
- For I'll have a new cloak about me."
- -Anonymous, "The Old Cloak". 16th Century.
+ Once in my life I’ll take a view;
+ For I’ll have a new cloak about me.”
+ -Anonymous, “The Old Cloak”. 16th Century.
%%%%
club
-"Speak softly and carry a big stick."
+“Speak softly and carry a big stick.”
-Theodore Roosevelt
%%%%
daeva
-"Between these twain the Daevas also chose not aright, for infatuation came upon them as they took counsel together, so that they chose the Worst Thought. Then they rushed together to Violence, that they might enfeeble the world of men."
+“Between these twain the Daevas also chose not aright, for infatuation came upon them as they took counsel together, so that they chose the Worst Thought. Then they rushed together to Violence, that they might enfeeble the world of men.”
-the Avesta, Ahunavaiti Gatha 30.6
%%%%
dagger
-"He drew his dagger, that was sae sharp,
+“He drew his dagger, that was sae sharp,
That was sae sharp and meet,
And drave it into the nut-browne bride,
That fell deid at his feit.
- 'Now stay for me, dear Annet,' he sed,
- 'Now stay, my dear,' he cry'd;
+ ‘Now stay for me, dear Annet,’ he sed,
+ ‘Now stay, my dear,’ he cry’d;
Then strake the dagger untill his heart,
- And fell deid by her side."
- -English traditional ballad, "Lord Thomas and Fair Annet", circa 1650.
+ And fell deid by her side.”
+ -English traditional ballad, “Lord Thomas and Fair Annet”, circa 1650.
%%%%
gold piece
-"Here it was that the ambassadors of the Samnites, finding him boiling turnips in the chimney corner, offered him a present of gold; but he sent them away with this saying; that he, who was content with such a supper, had no need of gold; and that he thought it more honourable to conquer those who possessed the gold, than to possess the gold itself."
- -Plutarch, "Marcus Cato"
+“Here it was that the ambassadors of the Samnites, finding him boiling turnips in the chimney corner, offered him a present of gold; but he sent them away with this saying; that he, who was content with such a supper, had no need of gold; and that he thought it more honourable to conquer those who possessed the gold, than to possess the gold itself.”
+ -Plutarch, “Marcus Cato”
%%%%
long sword
-"Oh I won't get up, I won't get up,
- I can't get up for my life
+“Oh I won’t get up, I won’t get up,
+ I can’t get up for my life
For you have two long beaten swords
And I have but a pocket knife.
- Well it's true I have two beaten swords,
+ Well it’s true I have two beaten swords,
They cost me deep in the purse
But you will have the better of them
- And I will have the worst."
- -English traditional ballad, "Mattie Groves". Circa 1600.
+ And I will have the worst.”
+ -English traditional ballad, “Mattie Groves”. Circa 1600.
%%%%
lychee
-"The Litchi is the most celebrated native fruit of China. It is nearly round, about an inch and a half in diameter, the shell is tough, becoming brittle, of a chocolate brown colour covered all over with wart-like protuberances. When fresh it is filled with a white almost transparent, sweet, jelly-like pulp in which lies a rather large, shining, brown seed; the pulp is of a delicious sub-acid flavour when fresh. The Chinese dry it when it becomes black like a prune and thus preserve it for use throughout the year; in this state it is frequently to be seen in the London fruit shops."
+“The Litchi is the most celebrated native fruit of China. It is nearly round, about an inch and a half in diameter, the shell is tough, becoming brittle, of a chocolate brown colour covered all over with wart-like protuberances. When fresh it is filled with a white almost transparent, sweet, jelly-like pulp in which lies a rather large, shining, brown seed; the pulp is of a delicious sub-acid flavour when fresh. The Chinese dry it when it becomes black like a prune and thus preserve it for use throughout the year; in this state it is frequently to be seen in the London fruit shops.”
-John Smith, _A Dictionary of Popular Names of the Plants which Furnish the Natural and Acquired Wants of Man, in All Matters of Domestic and General Economy: Their History, Products, & Uses_. 1882.
%%%%
orange
-"Conserve of Orange Peel
+“Conserve of Orange Peel
-HAVING grated the rinds of some Seville oranges as thin as you can, weigh them, and to every pound of orange rind add three pounds of loaf sugar. Pound the orange rind well in a marble mortar, mix the sugar by degrees with them and beat all well together. Put it into gallipots and tie it down so as properly to prevent the air getting to it."
+HAVING grated the rinds of some Seville oranges as thin as you can, weigh them, and to every pound of orange rind add three pounds of loaf sugar. Pound the orange rind well in a marble mortar, mix the sugar by degrees with them and beat all well together. Put it into gallipots and tie it down so as properly to prevent the air getting to it.”
-Francis Collingwood, John Woollams, _The Universal Cook: And City and Country Housekeeper._ 1792.
%%%%
potion
-"Then gave I her, -- so tutor'd by my art, --
+“Then gave I her, -- so tutor’d by my art, --
A sleeping potion; which so took effect
As I intended, for it wrought on her
The form of death: meantime I writ to Romeo
That he should hither come as this dire night,
- To help to take her from her borrow'd grave,
- Being the time the potion's force should cease."
+ To help to take her from her borrow’d grave,
+ Being the time the potion’s force should cease.”
-William Shakespeare, _Romeo and Juliet_
%%%%
rambutan
-"The rambutan (_nephelium lappaceum_) is a beautiful fruit to which I have already alluded, as resembling the mammoth arbutus; and you suppose them at first, when at a little distance from you, a delicious dish of some tropical strawberry. But you find on inquiring into the 'particulars within' the outer coat, that there is concealed beneath the red and hairy covering a semi-transparent pulp of a pleasant acid taste, enveloping a single oval and oblong seed. I know not but I am peculiar in my memory of the beautiful fruits of the straits, but none lingers in my recollection so sweetly in its clustered beauties of the fruit-dish as the bearded and rosy rambutan."
+“The rambutan (_nephelium lappaceum_) is a beautiful fruit to which I have already alluded, as resembling the mammoth arbutus; and you suppose them at first, when at a little distance from you, a delicious dish of some tropical strawberry. But you find on inquiring into the ‘particulars within’ the outer coat, that there is concealed beneath the red and hairy covering a semi-transparent pulp of a pleasant acid taste, enveloping a single oval and oblong seed. I know not but I am peculiar in my memory of the beautiful fruits of the straits, but none lingers in my recollection so sweetly in its clustered beauties of the fruit-dish as the bearded and rosy rambutan.”
-Fitch Waterman Taylor, _A Voyage Round the World And Visits to Various Foreign Countries, in the United States Frigate Columbia_. 1847.
%%%%
slice of pizza
-"When the moon hits your eye like a big pizza pie, that's amore."
- -Jack Brooks, "That's Amore"
+“When the moon hits your eye like a big pizza pie, that’s amore.”
+ -Jack Brooks, “That’s Amore”
%%%%
strawberry
-"A Samurai was out walking when a large tiger began to chase him. The samurai ran for his life, never seeing the cliff under his feet. As he fell, he reached out and caught a vine that hung down. He looked down and saw another tiger circling below; the first tiger waited above. The vine began to give away. The samurai then saw a single strawberry growing on the vine. He reached out and ate the strawberry. How sweet it tasted!"
+“A Samurai was out walking when a large tiger began to chase him. The samurai ran for his life, never seeing the cliff under his feet. As he fell, he reached out and caught a vine that hung down. He looked down and saw another tiger circling below; the first tiger waited above. The vine began to give away. The samurai then saw a single strawberry growing on the vine. He reached out and ate the strawberry. How sweet it tasted!”
-Attributed to various Japanese buddhist monks.
%%%%
sultana
-"A Turkish garden was among the curiosities to which the Jew found access for Bentham. It was a sort of orchard of vines and other trees, without order or apparent arrangement. From that garden Bentham sent specimens of the Sultana raisin to England which he believed to have been the first of that species which had ever reached his country."
+“A Turkish garden was among the curiosities to which the Jew found access for Bentham. It was a sort of orchard of vines and other trees, without order or apparent arrangement. From that garden Bentham sent specimens of the Sultana raisin to England which he believed to have been the first of that species which had ever reached his country.”
-John Bowring, _The Works of Jeremy Bentham_. 1839.
%%%%
####################################################
@@ -217,57 +217,57 @@ sultana
####################################################
__c_suffix
-"When Peleus, some distance away, saw him torn apart by the frightful wound he shouted: 'Accept this tribute to the dead, at least, Crantor, dearest of youths, ' and with his powerful arm, he hurled his ash spear, at full strength, at Demoleon. It ruptured the ribcage, and stuck quivering in the bone. The centaur pulled out the shaft minus its head (he tried with difficulty to reach that also) but the head was caught in his lung. The pain itself strengthened his will: wounded, he reared up at his enemy and beat the hero down with his hooves. Peleus received the resounding blows on helmet and shield, and defending his upper arms, and controlling the weapon he held out, with one blow through the arm he pierced the bi-formed breast.'"
+“When Peleus, some distance away, saw him torn apart by the frightful wound he shouted: ‘Accept this tribute to the dead, at least, Crantor, dearest of youths’, and with his powerful arm, he hurled his ash spear, at full strength, at Demoleon. It ruptured the ribcage, and stuck quivering in the bone. The centaur pulled out the shaft minus its head (he tried with difficulty to reach that also) but the head was caught in his lung. The pain itself strengthened his will: wounded, he reared up at his enemy and beat the hero down with his hooves. Peleus received the resounding blows on helmet and shield, and defending his upper arms, and controlling the weapon he held out, with one blow through the arm he pierced the bi-formed breast.”
-Ovid, _Metamorphoses_, XII 330
%%%%
__r_suffix
-"How now? a rat? Dead, for a ducat, dead!"
+“How now? a rat? Dead, for a ducat, dead!”
-William Shakespeare, Hamlet, Act III, 4
%%%%
__cap-D_suffix
-"On the other hand, Confucius is made to say to his disciples, 'I know how birds can fly, how fishes can swim, and how animals can run. But the runner may be snared, the swimmer may be hooked, and the flyer may be shot by the arrow. But there is the dragon. I cannot tell how he mounts on the wind through the clouds, and rises to heaven. Today I have seen Lao-tsze, and can only compare him to the dragon.'"
+“On the other hand, Confucius is made to say to his disciples, ‘I know how birds can fly, how fishes can swim, and how animals can run. But the runner may be snared, the swimmer may be hooked, and the flyer may be shot by the arrow. But there is the dragon. I cannot tell how he mounts on the wind through the clouds, and rises to heaven. Today I have seen Lao-tsze, and can only compare him to the dragon.’”
-Life of Confucius
-"This Dragon had Two furious Wings
+“This Dragon had Two furious Wings
Each one upon each Shoulder;
With a Sting in his Tail as long as a Flail,
Which made him bolder and bolder.
He had long Claws, and in his Jaws
Four and forty Teeth of Iron;
With a Hide as tough, as any Buff,
- Which did him round environ."
+ Which did him round environ.”
- -"An Excellent Ballad of a most dreadful Combat, fought between Moore of Moore-Hall, and the Dragon of Wantley", retold by Ambrose Philips, _A Collection of Old Ballads. Corrected from the Best and Most Ancient Copies Extant. With Introductions Historical, Critical, Or Humorous_. 1723.
+ -“An Excellent Ballad of a most dreadful Combat, fought between Moore of Moore-Hall, and the Dragon of Wantley”, retold by Ambrose Philips, _A Collection of Old Ballads. Corrected from the Best and Most Ancient Copies Extant. With Introductions Historical, Critical, Or Humorous_. 1723.
%%%%
__cap-K_suffix
-"The Parts Septentrionall are with these Sp'ryts Much haunted.. About the places where they dig for Oare. The Greekes and Germans call them Cobali."
+“The Parts Septentrionall are with these Sp’ryts Much haunted.. About the places where they dig for Oare. The Greekes and Germans call them Cobali.”
-Heywood, Hierarch. ix. 568, circa 1635
%%%%
__cap-O_suffix
-"The little princess, asleep in her cradle, floated on the water, and at last she was cast up on the shore of a beautiful country, where, however, very few people dwelt since the ogre Ravagio and his wife Tourmentine had gone to live there-for they ate up everybody. Ogres are terrible people. When once they have tasted raw human flesh they will hardly eat anything else, and Tourmentine always knew how to make some body come their way, for she was half a fairy."
- -Marie-Catherine Le Jumel de Barneville, Baronne d'Aulnoy, "'Orangier et l'Abeille". 1697.
+“The little princess, asleep in her cradle, floated on the water, and at last she was cast up on the shore of a beautiful country, where, however, very few people dwelt since the ogre Ravagio and his wife Tourmentine had gone to live there-for they ate up everybody. Ogres are terrible people. When once they have tasted raw human flesh they will hardly eat anything else, and Tourmentine always knew how to make some body come their way, for she was half a fairy.”
+ -Marie-Catherine Le Jumel de Barneville, Baronne d’Aulnoy, “’Orangier et l’Abeille”. 1697.
-"NO. Layers. Onions have layers. Ogres have layers. Onions have layers. You get it? We both have layers."
+“NO. Layers. Onions have layers. Ogres have layers. Onions have layers. You get it? We both have layers.”
-Shrek. 2001.
%%%%
__cap-S_suffix
-"The latter lived in the country, and before his house there was an oak, in which there was a lair of snakes. His servants killed the snakes, but Melampus gathered wood and burnt the reptiles, and reared the young ones. And when the young were full grown, they stood beside him at each of his shoulders as he slept, and they purged his ears with their tongues. He started up in a great fright, but understood the voices of the birds flying overhead, and from what he learned from them he foretold to men what should come to pass."
+“The latter lived in the country, and before his house there was an oak, in which there was a lair of snakes. His servants killed the snakes, but Melampus gathered wood and burnt the reptiles, and reared the young ones. And when the young were full grown, they stood beside him at each of his shoulders as he slept, and they purged his ears with their tongues. He started up in a great fright, but understood the voices of the birds flying overhead, and from what he learned from them he foretold to men what should come to pass.”
-Apollodorus (apocryphal), Library and Epitome, 1.9.11. circa 150 BC. Sir James George Frazer, translator.
-"A snake, with mottles rare,
+“A snake, with mottles rare,
Surveyed my chamber floor,
In feature as the worm before,
- But ringed with power."
- -Emily Dickinson, "In Winter In My Room"
+ But ringed with power.”
+ -Emily Dickinson, “In Winter In My Room”
%%%%
__cap-T_suffix
-"Buckshank bold and Elfinstone,
+“Buckshank bold and Elfinstone,
And more than I can mention here,
They caused to be built so stout a ship,
And unto Iceland they would steer.
@@ -275,84 +275,84 @@ __cap-T_suffix
They launched the ship upon the main,
Which bellowed like a wrathful bear;
Down to the bottom the vessel sank,
- A laidly Trold has dragged it there."
+ A laidly Trold has dragged it there.”
-George Borrow, _Lavengro_
%%%%
Aizul
-"I went to Heaven --
- 'Twas a small Town --
+“I went to Heaven --
+ ’Twas a small Town --
Lit -- with a Ruby --
- Lathed -- with Down --"
+ Lathed -- with Down --”
-Emily Dickinson, _I went to Heaven_
%%%%
Antaeus
-"That country was then ruled by Antaeus, son of Poseidon, who used to kill strangers by forcing them to wrestle. Being forced to wrestle with him, Hercules hugged him, lifted him aloft, broke and killed him; for when he touched earth so it was that he waxed stronger, wherefore some said that he was a son of Earth."
+“That country was then ruled by Antaeus, son of Poseidon, who used to kill strangers by forcing them to wrestle. Being forced to wrestle with him, Hercules hugged him, lifted him aloft, broke and killed him; for when he touched earth so it was that he waxed stronger, wherefore some said that he was a son of Earth.”
-Apollodorus (apocryphal), _Library and Epitome_, 2.5.11, circa 150 BC. Sir James George Frazer, translator.
%%%%
Asmodeus
-"For myself, I have other occupations: I make absurd matches; I marry greybeards with minors, masters with servants, girls with small fortunes with tender lovers who have none. It is I who introduced into this world luxury, debauchery, games of chance, and chemistry. I am the author of the first cookery book, the inventor of festivals, of dancing, music, plays, and of the newest fashions; in a word, I am ASMODEUS, surnamed The Devil on Two Sticks."
+“For myself, I have other occupations: I make absurd matches; I marry greybeards with minors, masters with servants, girls with small fortunes with tender lovers who have none. It is I who introduced into this world luxury, debauchery, games of chance, and chemistry. I am the author of the first cookery book, the inventor of festivals, of dancing, music, plays, and of the newest fashions; in a word, I am ASMODEUS, surnamed The Devil on Two Sticks.”
-Alain René Le Sage, _Asmodeus: Or, The Devil on Two Sticks_. 1707.
%%%%
Cacodemon
-"We'll call him Cacodemon, with his black Gib there, his Succuba, his Devil's Seed, his Spawn of Phlegethon, that o' my Consience was bred o' the Spume of Cocytus."
+“We’ll call him Cacodemon, with his black Gib there, his Succuba, his Devil’s Seed, his Spawn of Phlegethon, that o’ my Consience was bred o’ the Spume of Cocytus.”
-John Fletcher, _The Knight of Malta_. 1647.
%%%%
Dispater
-"Hoc idem magis ostendit antiquius Iovis nomen: nam olim Diovis et Diespiter dictus, id est dies pater; a quo dei dicti qui inde, et dius et divum, unde sub divo, Dius Fidius. Itaque inde eius perforatum tectum, ut ea videatur divum, id est caelum. Quidam negant sub tecto per hunc deierare oportere. Aelius Dium Fidium dicebat Diovis filium, ut Graeci Dioskopon Castorem, et putabat hunc esse Sancum ab Sabina lingua et Herculem a Graeca. Idem hic Dis pater dicitur infimus, qui est coniunctus terrae, ubi omnia ut oriuntur ita aboriuntur; quorum quod finis ortuum, Orcus dictus."
+“Hoc idem magis ostendit antiquius Iovis nomen: nam olim Diovis et Diespiter dictus, id est dies pater; a quo dei dicti qui inde, et dius et divum, unde sub divo, Dius Fidius. Itaque inde eius perforatum tectum, ut ea videatur divum, id est caelum. Quidam negant sub tecto per hunc deierare oportere. Aelius Dium Fidium dicebat Diovis filium, ut Graeci Dioskopon Castorem, et putabat hunc esse Sancum ab Sabina lingua et Herculem a Graeca. Idem hic Dis pater dicitur infimus, qui est coniunctus terrae, ubi omnia ut oriuntur ita aboriuntur; quorum quod finis ortuum, Orcus dictus.”
-Marcus Terentius Varro, _De Lingua Latina_, Liber V, circa 40 BC.
%%%%
Dowan
-"Skill and grace, the twin brother and sister, are dancing playfully on your finger tips."
+“Skill and grace, the twin brother and sister, are dancing playfully on your finger tips.”
-Rabindranath Tagore, _Chitra, Act I, Scene IV_
%%%%
Duvessa
-"Twin children: the Girl, she was plain;
+“Twin children: the Girl, she was plain;
The Brother was handsome & vain;
- 'Let him brag of his looks,'
- Father said; 'mind your books!
- The best beauty is bred in the brain.'"
- -Aesop & Walter Crane, _The Baby's Own Aesop: Brother & Sister_
+ ‘Let him brag of his looks,’
+ Father said; ‘mind your books!
+ The best beauty is bred in the brain.’”
+ -Aesop & Walter Crane, _The Baby’s Own Aesop: Brother & Sister_
%%%%
Edmund
-"And my invention thrive, Edmund the base
+“And my invention thrive, Edmund the base
Shall top the legitimate. I grow; I prosper.--
- Now, gods, stand up for bastards!"
+ Now, gods, stand up for bastards!”
-Shakespeare, King Lear.
-"When the forces stood in array Edmund proposed to decide their claims by single combat; but Canute saying that he, a man of small stature, would have little chance against the tall athletic Edmund, proposed, on the contrary, for them to divide the realm as their fathers had done."
+“When the forces stood in array Edmund proposed to decide their claims by single combat; but Canute saying that he, a man of small stature, would have little chance against the tall athletic Edmund, proposed, on the contrary, for them to divide the realm as their fathers had done.”
-Thomas Keightley, _The History of England_. 1839.
%%%%
Geryon
-"Khrysaor, married to Kallirhoe, daughter of glorious Okeanos, was father to the triple-headed Geryon, but Geryon was killed by the great strength of Herakles at sea-circled Erytheis beside his own shambling cattle on that day when Herakles drove those broad-faced cattle toward holy Tiryns, when he crossed the stream of Okeanos and had killed Orthos and the oxherd Eurytion out in the gloomy meadow beyond fabulous Okeanos."
+“Khrysaor, married to Kallirhoe, daughter of glorious Okeanos, was father to the triple-headed Geryon, but Geryon was killed by the great strength of Herakles at sea-circled Erytheis beside his own shambling cattle on that day when Herakles drove those broad-faced cattle toward holy Tiryns, when he crossed the stream of Okeanos and had killed Orthos and the oxherd Eurytion out in the gloomy meadow beyond fabulous Okeanos.”
-Hesiod, _Theogony_, circa 700 BCE.
%%%%
Killer Klown
-"All the world loves a clown."
- -Cole Porter, "Be a Clown". 1948.
+“All the world loves a clown.”
+ -Cole Porter, “Be a Clown”. 1948.
%%%%
Murray
-"Look behind you! A three-headed monkey!"
+“Look behind you! A three-headed monkey!”
-Guybrush Threepwood, _The Secret of Monkey Island_
%%%%
Polyphemus
-"...as soon as he had got through with all his work, he clutched up two more of my men, and began eating them for his morning's meal. Presently, with the utmost ease, he rolled the stone away from the door and drove out his sheep, but he at once put it back again--as easily as though he were merely clapping the lid on to a quiver full of arrows."
+“...as soon as he had got through with all his work, he clutched up two more of my men, and began eating them for his morning’s meal. Presently, with the utmost ease, he rolled the stone away from the door and drove out his sheep, but he at once put it back again--as easily as though he were merely clapping the lid on to a quiver full of arrows.”
-Homer, _The Odyssey_, Book IX
%%%%
Psyche
-"Let Psyche's corpse be clad in mourning weed
+“Let Psyche’s corpse be clad in mourning weed
And set on rock of yonder hill aloft;
Her husband is no wight of human seed,
But serpent dire and fierce, as may be thought,
@@ -361,28 +361,28 @@ Psyche
The Gods themselves and powers that seem so wise
With mighty love be subject to his might.
The rivers black and deadly floods of pain
- And darkness eke as thrall to him remain."
- -Apuleius, _Asinus aureus_, "Cupid and Psyche"
+ And darkness eke as thrall to him remain.”
+ -Apuleius, _Asinus aureus_, “Cupid and Psyche”
circa 160 AD. William Adlington, Translator, 1566.
%%%%
Sigmund
-"But Sigmund turned him about, and he said: 'What aileth thee, son?
- Shall our life-days never be merry, and our labour never be done?'
+“But Sigmund turned him about, and he said: ‘What aileth thee, son?
+ Shall our life-days never be merry, and our labour never be done?’
- But Sinfiotli said: 'I have looked, and lo, there is death in the cup.'
+ But Sinfiotli said: ‘I have looked, and lo, there is death in the cup.’
And the song, and the tinkling of harp-strings to the roof-tree winded up;
And Sigmund was dreamy with wine and the wearing of many a year;
And the noise and the glee of the people as the sound of the wild woods were
And the blossoming boughs of the Branstock were the wild trees waving about;
- So he said: 'Well seen, my fosterling; let the lip then strain it out.'"
+ So he said: ‘Well seen, my fosterling; let the lip then strain it out.’”
-William Morris, _The Story of Sigurd the Volsung and the Fall of the Niblungs. 1891.
%%%%
Tiamat
-"He saith that Tiamat our mother hath conceived a hatred for us,
+“He saith that Tiamat our mother hath conceived a hatred for us,
With all her force she rageth, full of wrath.
All the gods have turned to her,
With those, whom ye created, they go at her side.
@@ -397,107 +397,107 @@ Tiamat
Fierce monster-vipers she clothed with terror,
With splendor she decked them, she made them of lofty stature.
Whoever beheld them, terror overcame him,
- Their bodies reared up and none could withstand their attack."
+ Their bodies reared up and none could withstand their attack.”
-Enuma Elish, Third Tablet. circa 668 BCE.
%%%%
agate snail
-"Snail, snail, slug-slow,
+“Snail, snail, slug-slow,
To me thy four horns show;
If thou dost not show me thy four,
I will throw thee out of the door,
For the crow in the gutter,
- To eat for bread and butter."
+ To eat for bread and butter.”
-Silesian rhyme, _Notes and Queries, Number 69_, 1851.
%%%%
big fish
-"And what are you, reader, but a Loose-Fish and a Fast-Fish, too?"
+“And what are you, reader, but a Loose-Fish and a Fast-Fish, too?”
-Herman Melville, _Moby Dick_. 1851.
%%%%
boggart
-"He thinks every bush a boggart."
+“He thinks every bush a boggart.”
-John Ray, _A Compleat Collection of English Proverbs_. 1768.
-"A BOGGART intruded himself, upon what pretext or by what authority is unknown, into the house of a quiet, inoffensive, and laborious farmer; and, when once it had taken possession it disputed the right of domicile with the legal mortal tenant, in a very unneighbourly and arbitrary manner. In particular, it seemed to have a great aversion to children. As there is no point on which a parent feels more acutely than that of the maltreatment of his offspring, the feelings of the father and more particularly of his good dame, were daily, ay, and nightly, harrowed up by the malice of this malignant and invisible boggart."
+“A BOGGART intruded himself, upon what pretext or by what authority is unknown, into the house of a quiet, inoffensive, and laborious farmer; and, when once it had taken possession it disputed the right of domicile with the legal mortal tenant, in a very unneighbourly and arbitrary manner. In particular, it seemed to have a great aversion to children. As there is no point on which a parent feels more acutely than that of the maltreatment of his offspring, the feelings of the father and more particularly of his good dame, were daily, ay, and nightly, harrowed up by the malice of this malignant and invisible boggart.”
-C.J.T., _Folk-lore and Legends: English_ 1890.
%%%%
bumblebee
-"How doth the little busy Bee
+“How doth the little busy Bee
Improve each shining Hour,
And gather Honey all the day
- From every opening Flower!"
+ From every opening Flower!”
-Isaac Watts. 1715.
%%%%
bush
-"And the angel of the LORD appeared unto him in a flame of fire out of the midst of a bush: and he looked, and, behold, the bush burned with fire, and the bush was not consumed."
+“And the angel of the LORD appeared unto him in a flame of fire out of the midst of a bush: and he looked, and, behold, the bush burned with fire, and the bush was not consumed.”
-KJV Bible, Ex3:2.
%%%%
butterfly
-"Happiness is a butterfly, which when pursued, is always just beyond your grasp, but which, if you will sit down quietly, may alight upon you."
+“Happiness is a butterfly, which when pursued, is always just beyond your grasp, but which, if you will sit down quietly, may alight upon you.”
-Nathaniel Hawthorne
%%%%
catoblepas
-"So passed he over into the island, taking with him the two brothers of Anaxius; where he found the forsaken knight attired in his own livery, as black as sorrow itself could see itself in the blackest glass: his ornaments of the same hue, but formd into the figures of ravens which seemed to gape for carrion: only his reins were snakes, which finely wrapping themselves one within the other, their heads came together to the cheeks and bosses of the bit, where they might seem to bite at the horse, and the horse, as he champed the bit, to bite at them, and that the white foam was engendered by the poisonous fury of the combat. His impresa was a Catoblepta, which so long lies dead as the moon (whereto it hath so natural a sympathy) wants her light. The word signified, that the moon wanted not the light, but the poor beast wanted the moon's light."
+“So passed he over into the island, taking with him the two brothers of Anaxius; where he found the forsaken knight attired in his own livery, as black as sorrow itself could see itself in the blackest glass: his ornaments of the same hue, but formd into the figures of ravens which seemed to gape for carrion: only his reins were snakes, which finely wrapping themselves one within the other, their heads came together to the cheeks and bosses of the bit, where they might seem to bite at the horse, and the horse, as he champed the bit, to bite at them, and that the white foam was engendered by the poisonous fury of the combat. His impresa was a Catoblepta, which so long lies dead as the moon (whereto it hath so natural a sympathy) wants her light. The word signified, that the moon wanted not the light, but the poor beast wanted the moon’s light.”
-Sir Philip Sidney
%%%%
cherub
-"The glory of Yahweh mounted up from the cherub, and stood over the threshold of the house; and the house was filled with the cloud, and the court was full of the brightness of Yahweh’s glory.
- The sound of the wings of the cherubim was heard even to the outer court, as the voice of God Almighty when he speaks."
+“The glory of Yahweh mounted up from the cherub, and stood over the threshold of the house; and the house was filled with the cloud, and the court was full of the brightness of Yahweh’s glory.
+ The sound of the wings of the cherubim was heard even to the outer court, as the voice of God Almighty when he speaks.”
-WEB Bible, Ezk10:4-5
%%%%
clay golem
-"Once upon a time a great Cabbalist lived in Prague called the Rabbi Löw. He made a human figure of clay, and left a small aperture in the lesser brain in which he laid a parchment with the unutterable name of God written on it. The clod immediately arose and was a man; he performed all the duties of a servant for his creator, he fetched water, and hewed wood. All through the Jews quarter he was known as the Golem of the great Rabbi Löw. Every Friday evening the Rabbi took the parchment out of his head, and he was clay until Sunday morning. Once the Rabbi forgot this duty, all were in the Synagogue, the Sabbath hymn was begun, when all the women and children in the assembly started and screamed out, 'the Golem! the Golem is destroying everything!' The Rabbi ordered the precentor to pause at the end of the prayer: it was yet possible to save all, but later nought would avail, the whole world would be destroyed. He hastened home, and saw the Golem already seizing the joists of his house to tear down the building: he sprang forward, took the parchment out, and dead clay again lay at his feet."
+“Once upon a time a great Cabbalist lived in Prague called the Rabbi Löw. He made a human figure of clay, and left a small aperture in the lesser brain in which he laid a parchment with the unutterable name of God written on it. The clod immediately arose and was a man; he performed all the duties of a servant for his creator, he fetched water, and hewed wood. All through the Jews quarter he was known as the Golem of the great Rabbi Löw. Every Friday evening the Rabbi took the parchment out of his head, and he was clay until Sunday morning. Once the Rabbi forgot this duty, all were in the Synagogue, the Sabbath hymn was begun, when all the women and children in the assembly started and screamed out, ‘the Golem! the Golem is destroying everything!’ The Rabbi ordered the precentor to pause at the end of the prayer: it was yet possible to save all, but later nought would avail, the whole world would be destroyed. He hastened home, and saw the Golem already seizing the joists of his house to tear down the building: he sprang forward, took the parchment out, and dead clay again lay at his feet.”
-Berthold Auerbach, _Spinoza_. 1882.
%%%%
efreet
-"When the hoopoe returned to Solomon (he told him the news), and he responded (to Sheba's people): "Are you giving me money? What GOD has given me is far better than what He has given you. You are the ones to rejoice in such gifts." (To the hoopoe, he said,) "Go back to them (and let them know that) we will come to them with forces they cannot imagine. We will evict them, humiliated and debased." He said, "O you elders, which of you can bring me her mansion, before they arrive here as submitters?" One afrit from the jinns said, "I can bring it to you before you stand up. I am powerful enough to do this."
+“When the hoopoe returned to Solomon (he told him the news), and he responded (to Sheba’s people): “Are you giving me money? What GOD has given me is far better than what He has given you. You are the ones to rejoice in such gifts.” (To the hoopoe, he said), “Go back to them (and let them know that) we will come to them with forces they cannot imagine. We will evict them, humiliated and debased." He said, "O you elders, which of you can bring me her mansion, before they arrive here as submitters?" One afrit from the jinns said, “I can bring it to you before you stand up. I am powerful enough to do this.”
-The Quran, Sura 27 Al-Naml
%%%%
ettin
-"But he had not been long in his hiding-hole, before the awful Ettin came in; and no sooner was he in, than he was heard crying:
-'Snouk but and snouk ben,
- I find the smell of an earthly man,
- Be he living, or be he dead,
- His heart this night shall kitchen my bread.'"
+“But he had not been long in his hiding-hole, before the awful Ettin came in; and no sooner was he in, than he was heard crying:
+ ‘Snouk but and snouk ben,
+ I find the smell of an earthly man,
+ Be he living, or be he dead,
+ His heart this night shall kitchen my bread.’”
-Joseph Jacobs, _The Red Ettin_
%%%%
fire crab
-"The planet brought forth scintillating jewelled scuttling crabs, which [they] ate, smashing their shells with iron mallets; tall aspiring trees with breathtaking slenderness and colour which [they] cut down and burned the crab meat with."
- -Douglas Adams, The Hitch-hiker's Guide to the Galaxy
+“The planet brought forth scintillating jewelled scuttling crabs, which [they] ate, smashing their shells with iron mallets; tall aspiring trees with breathtaking slenderness and colour which [they] cut down and burned the crab meat with.”
+ -Douglas Adams, The Hitch-hiker’s Guide to the Galaxy
%%%%
flying skull
-"Alas, poor Yorick! I knew him, Horatio, a fellow of infinite jest, of most excellent fancy. He hath bore me on his back a thousand times, and now how abhorr'd in my imagination it is! My gorge rises at it."
+“Alas, poor Yorick! I knew him, Horatio, a fellow of infinite jest, of most excellent fancy. He hath bore me on his back a thousand times, and now how abhorr’d in my imagination it is! My gorge rises at it.”
-William Shakespeare, _Hamlet_, V, 1. 1600.
%%%%
ghoul
-"In the desert
+“In the desert
I saw a creature, naked, bestial,
Who, squatting upon the ground,
Held his heart in his hands,
And ate of it.
- I said, 'Is it good, friend?'
- 'It is bitter - bitter', he answered,
- 'But I like it
+ I said, ‘Is it good, friend?’
+ ‘It is bitter - bitter’, he answered,
+ ‘But I like it
Because it is bitter,
- And because it is my heart.'"
+ And because it is my heart.’”
-Stephen Crane, _The Black Riders and Other Lines_. 1895.
%%%%
giant frog
-"Hello, my baby
+“Hello, my baby
Hello, my honey
Hello, my ragtime gal
@@ -505,211 +505,211 @@ giant frog
Baby, my hearts on fire
If you refuse me
- Honey, you'll lose me
- Then you'll be left alone
+ Honey, you’ll lose me
+ Then you’ll be left alone
Oh baby, telephone
- And tell me I'm your own."
- -Ida Emerson and Joseph E. Howard, "Hello My Baby!"
+ And tell me I’m your own.”
+ -Ida Emerson and Joseph E. Howard, “Hello My Baby!”
%%%%
gnoll
-"Then he descended softly and beckoned to Nuth. But the gnoles had watched him through knavish holes that they bore in trunks of the trees, and the unearthly silence gave way, as it were with a grace, to the rapid screams of Tonker as they picked him up from behind -- screams that came faster and faster until they were incoherent. And where they took him it is not good to ask, and what they did with him I shall not say."
- -Lord Dunsany, "How Nuth Would Have Practiced His Art Upon the Gnoles". 1912.
+“Then he descended softly and beckoned to Nuth. But the gnoles had watched him through knavish holes that they bore in trunks of the trees, and the unearthly silence gave way, as it were with a grace, to the rapid screams of Tonker as they picked him up from behind -- screams that came faster and faster until they were incoherent. And where they took him it is not good to ask, and what they did with him I shall not say.”
+ -Lord Dunsany, “How Nuth Would Have Practiced His Art Upon the Gnoles”. 1912.
%%%%
goblin
-"Swish, smack! Whip crack!
+“Swish, smack! Whip crack!
Batter and beat! Yammer and bleat!
Work, work! Nor dare to shirk,
While Goblins quaff, and Goblins laugh,
Round and round far underground
- Below, my lad!"
+ Below, my lad!”
-J.R.R. Tolkien, _The Hobbit_
%%%%
golden eye
-"No coveting nor envy burns
+“No coveting nor envy burns
In thy bright golden eye,
That calm and innocently turns
- On all below the sky."
- -Hannah Flagg Gould, _The Youth's Coronal_
+ On all below the sky.”
+ -Hannah Flagg Gould, _The Youth’s Coronal_
%%%%
griffon
-"As when a Gryphon through the wilderness,
- With winged course, o'er hill and moory dale,
+“As when a Gryphon through the wilderness,
+ With winged course, o’er hill and moory dale,
Pursues the Arimaspian who by stealth
Hath from his wakeful custody purloined
- His guarded gold."
+ His guarded gold.”
-Milton, _Paradise Lost_, Book II. 1667.
%%%%
harpy
-"Bird-bodied, girl-faced things they are; abominable their droppings, their hands are talons, their faces haggard with hunger insatiable."
+“Bird-bodied, girl-faced things they are; abominable their droppings, their hands are talons, their faces haggard with hunger insatiable.”
-Virgil, Aeneid 3
-"And Phineus had scarcely taken the first morsel up when, with as little warning as a whirlwind or a lightning flash, they dropped from the clouds proclaiming their desire for food with raucous cries. The young lords saw them coming and raised the alarm. Yet they had hardly done so before the Harpyiai had devoured the whole meal and were on the wing once more, far out at sea. All they left was an intolerable stench."
+“And Phineus had scarcely taken the first morsel up when, with as little warning as a whirlwind or a lightning flash, they dropped from the clouds proclaiming their desire for food with raucous cries. The young lords saw them coming and raised the alarm. Yet they had hardly done so before the Harpyiai had devoured the whole meal and were on the wing once more, far out at sea. All they left was an intolerable stench.”
-Apollonius Rhodius, Argonautica 2. 179 - 434
%%%%
hell knight
-"Ok, let's review. It's up to the fair young maiden to rescue the dragon from the fire breathing knights in shining armor."
+“Ok, let’s review. It’s up to the fair young maiden to rescue the dragon from the fire breathing knights in shining armor.”
-Exiern
%%%%
hobgoblin
-"A foolish consistency is the hobgoblin of little minds."
+“A foolish consistency is the hobgoblin of little minds.”
-Ralph Waldo Emerson
%%%%
hog
-"Fern came slowly down the stairs. Her eyes were red from crying. As she approached her chair, the carton wobbled, and there was a scratching noise. Fern looked at her father. Then she lifted the lid of the carton. There, inside, looking up at her, was the newborn pig. It was a white one. The morning light shone through its ears, turning them pink. "He's yours," said Mr. Arable. "Saved from an untimely death. And may the good Lord forgive me for this foolishness."
- -E.B. White, _Charlotte's Web_
+“Fern came slowly down the stairs. Her eyes were red from crying. As she approached her chair, the carton wobbled, and there was a scratching noise. Fern looked at her father. Then she lifted the lid of the carton. There, inside, looking up at her, was the newborn pig. It was a white one. The morning light shone through its ears, turning them pink. “He’s yours,” said Mr. Arable. “Saved from an untimely death. And may the good Lord forgive me for this foolishness.”
+ -E.B. White, _Charlotte’s Web_
%%%%
hound
-"A traveller, by the faithful hound,
+“A traveller, by the faithful hound,
Half-buried in the snow was found,
Still grasping in his hand of ice
That banner with the strange device,
-Excelsior!"
- -Henry Wadsworth Longfellow, "Excelsior"
+Excelsior!”
+ -Henry Wadsworth Longfellow, “Excelsior”
%%%%
human
-"Do you know
+“Do you know
Do I know
- What's this thing called 'man'?
+ What’s this thing called ‘man’?
God only knows what a man is!
- I only know his price."
- -Bertolt Brecht, "The Measures Taken". 1930.
+ I only know his price.”
+ -Bertolt Brecht, “The Measures Taken”. 1930.
%%%%
imp
-"The Devil, too, sometimes steals human children; it is not infrequent for him to carry away infants within the first six weeks after birth, and to substitute in their place imps."
+“The Devil, too, sometimes steals human children; it is not infrequent for him to carry away infants within the first six weeks after birth, and to substitute in their place imps.”
-Martin Luther
%%%%
jelly
-"Beware of the Blob!
+“Beware of the Blob!
It creeps
And leaps
and glides and slides
Across the floor
Right through the door
And all around the wall,
- A splotch, a blotch..."
- -Burt Bacharach, "Beware of the Blob"
+ A splotch, a blotch...”
+ -Burt Bacharach, “Beware of the Blob”
%%%%
Khufu
-"And then I looked farther, beyond the pallid line of the sands, and I saw a Pyramid of gold, the wonder Khufu had built. As a golden wonder it saluted me, as a golden thing it greeted me, as a golden miracle I shall remember it."
+“And then I looked farther, beyond the pallid line of the sands, and I saw a Pyramid of gold, the wonder Khufu had built. As a golden wonder it saluted me, as a golden thing it greeted me, as a golden miracle I shall remember it.”
-Robert Hichens, _The Spell of Egypt_
%%%%
kraken
-"... Kraken, also called the Crab-fish, which [according to the pilots of Norway] is not that huge, for heads and tails counted, he is no larger than our Öland is wide [i.e. less than 16 km] ... He stays at the sea floor, constantly surrounded by innumerable small fishes, who serve as his food and are fed by him in return: for his meal, if I remember correctly what E. Pontoppidan writes, lasts no longer than three months, and another three are then needed to digest it. His excrements nurture in the following an army of lesser fish, and for this reason, fishermen plumb after his resting place ... Gradually, Kraken ascends to the surface, and when he is at ten to twelve fathoms, the boats had better move out of his vicinity, as he will shortly thereafter burst up, like a floating island, spurting water from his dreadful nostrils and making ring waves around him, which can reach many miles. Could one doubt that this is the Leviathan of Job?"
- -Jacob Wallenberg, "Min son på galejan", 1781.
+“... Kraken, also called the Crab-fish, which [according to the pilots of Norway] is not that huge, for heads and tails counted, he is no larger than our Öland is wide [i.e. less than 16 km] ... He stays at the sea floor, constantly surrounded by innumerable small fishes, who serve as his food and are fed by him in return: for his meal, if I remember correctly what E. Pontoppidan writes, lasts no longer than three months, and another three are then needed to digest it. His excrements nurture in the following an army of lesser fish, and for this reason, fishermen plumb after his resting place ... Gradually, Kraken ascends to the surface, and when he is at ten to twelve fathoms, the boats had better move out of his vicinity, as he will shortly thereafter burst up, like a floating island, spurting water from his dreadful nostrils and making ring waves around him, which can reach many miles. Could one doubt that this is the Leviathan of Job?”
+ -Jacob Wallenberg, “Min son på galejan”, 1781.
%%%%
Mara
-"This night the Lord of Illusion passed among you, Mara, mighty among dreamers, mighty for ill. He did come upon another who may work with the stuff of dreams in a different way. He did meet with Dharma, who may expel a dreamer from his dream. They did struggle, and the Lord Mara is no more. Why did they struggle, deathgod against illusionist? You say their ways are incomprehensible, being the ways of gods. This is not the answer."
- -Roger Zelazny, "Lord of Light", 1967
+“This night the Lord of Illusion passed among you, Mara, mighty among dreamers, mighty for ill. He did come upon another who may work with the stuff of dreams in a different way. He did meet with Dharma, who may expel a dreamer from his dream. They did struggle, and the Lord Mara is no more. Why did they struggle, deathgod against illusionist? You say their ways are incomprehensible, being the ways of gods. This is not the answer.”
+ -Roger Zelazny, “Lord of Light”, 1967
%%%%
Menkaure
-"Ye men of Egypt, ye have heard your king!
+“Ye men of Egypt, ye have heard your king!
I go, and I return not. But the will
Of the great Gods is plain; and ye must bring
Ill deeds, ill passions, zealous to fulfil
Their pleasure, to their feet; and reap their praise,
- The praise of Gods, rich boon! and length of days."
+ The praise of Gods, rich boon! and length of days.”
-Matthew Arnold, _Mycerinus_
%%%%
manticore
-"Ctesias writeth, that in Aethiopia likewise there is a beast which he calleth Mantichora, having three rankes of teeth, which when they meet togither are let in one within another like the teeth of combes: with the face and eares of a man, with red eyes; of colour sanguine, bodied like a lyon, and having a taile armed with a sting like a scorpion: his voice resembleth the noise of a flute and trumpet sounded together: very swift he is, and mans flesh of all others hee most desireth."
+“Ctesias writeth, that in Aethiopia likewise there is a beast which he calleth Mantichora, having three rankes of teeth, which when they meet togither are let in one within another like the teeth of combes: with the face and eares of a man, with red eyes; of colour sanguine, bodied like a lyon, and having a taile armed with a sting like a scorpion: his voice resembleth the noise of a flute and trumpet sounded together: very swift he is, and mans flesh of all others hee most desireth.”
-Pliny the Elder, _Natural History_, Book 8, Chapter XXI
%%%%
mermaid
-"To the Sirens first shalt thou come, who beguile all men whosoever comes to them. Whoso in ignorance draws near to them and hears the Sirens' voice, he nevermore returns, that his wife and little children may stand at his side rejoicing, but the Sirens beguile him with their clear-toned song, as they sit in a meadow, and about them is a great heap of bones of mouldering men, and round the bones the skin is shrivelling."
+“To the Sirens first shalt thou come, who beguile all men whosoever comes to them. Whoso in ignorance draws near to them and hears the Sirens’ voice, he nevermore returns, that his wife and little children may stand at his side rejoicing, but the Sirens beguile him with their clear-toned song, as they sit in a meadow, and about them is a great heap of bones of mouldering men, and round the bones the skin is shrivelling.”
-Homer, _The Odyssey_, Book XII
%%%%
mummy
-"I see Egypt and the Egyptians -- I see the pyramids and obelisks;
- I look on chisel'd histories, songs, philosophies, cut in slabs
+“I see Egypt and the Egyptians -- I see the pyramids and obelisks;
+ I look on chisel’d histories, songs, philosophies, cut in slabs
of sand-stone, or on granite-blocks;
- I see at Memphis mummy-pits, containing mummies, embalm'd, swathed
+ I see at Memphis mummy-pits, containing mummies, embalm’d, swathed
in linen cloth, lying there many centuries;
- I look on the fall'n Theban, the large-ball'd eyes, the side-drooping
- neck, the hands folded across the breast."
- -Walt Whitman, "Salut au Monde"
+ I look on the fall’n Theban, the large-ball’d eyes, the side-drooping
+ neck, the hands folded across the breast.”
+ -Walt Whitman, “Salut au Monde”
%%%%
ophan
-"As I looked at the living creatures, I saw a wheel on the ground beside
+“As I looked at the living creatures, I saw a wheel on the ground beside
each creature with its four faces. This was the appearance and structure
of the wheels: They sparkled like chrysolite, and all four looked alike.
Each appeared to be made like a wheel intersecting a wheel. As they
moved, they would go in any one of the four directions the creatures faced;
the wheels did not turn about as the creatures went. Their rims were
- high and awesome, and all four rims were full of eyes all around."
+ high and awesome, and all four rims were full of eyes all around.”
-Ezekiel 1:15-18 (New International Version)
%%%%
phantom
-"Who wondrous things concerning our welfare, And straunge phantomes doth lett us ofte foresee."
+“Who wondrous things concerning our welfare, And straunge phantomes doth lett us ofte foresee.”
-Spenser, _The Faerie Queene_ II. xii. 47
%%%%
pillar of salt
-"Then the LORD rained brimstone and fire on Sodom and Gomorrah, from the LORD out of the heavens. So He overthrew those cities, all the plain, all the inhabitants of the cities, and what grew on the ground. But his wife looked back behind him, and she became a pillar of salt."
+“Then the LORD rained brimstone and fire on Sodom and Gomorrah, from the LORD out of the heavens. So He overthrew those cities, all the plain, all the inhabitants of the cities, and what grew on the ground. But his wife looked back behind him, and she became a pillar of salt.”
-Genesis 19:24-26 (New King James Version)
%%%%
player ghost
-"Know thyself."
+“Know thyself.”
-Inscription in the pronaos of the Temple of Apollo at Delphi
%%%%
Prince Ribbit
-"Princess! youngest princess!
+“Princess! youngest princess!
Open the door for me!
Dost thou not know what thou saidst to me
Yesterday by the cool waters of the fountain?
Princess, youngest princess!
- Open the door for me!"
+ Open the door for me!”
-Brothers Grimm (Margaret Hunt), _The Frog King, or Iron Henry_
%%%%
program bug
-"If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization."
- -Gerald Weinberg, Weinberg's Second Law
+“If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.”
+ -Gerald Weinberg, Weinberg’s Second Law
%%%%
rakshasa
-"He is brilliant, yet utterly corrupt. Like rotten mackerel by moonlight, he both shines and stinks."
+“He is brilliant, yet utterly corrupt. Like rotten mackerel by moonlight, he both shines and stinks.”
-John Randolph
%%%%
raven
-"The Hatter opened his eyes very wide on hearing this; but all he said was 'Why is a raven like a writing-desk?'"
- -Lewis Carroll, Alice's Adventures in Wonderland
+“The Hatter opened his eyes very wide on hearing this; but all he said was ‘Why is a raven like a writing-desk?’”
+ -Lewis Carroll, Alice’s Adventures in Wonderland
%%%%
seraph
-"In the year that king Uzziah died I saw also the LORD sitting upon a throne, high and lifted up, and his train filled the temple.
+“In the year that king Uzziah died I saw also the LORD sitting upon a throne, high and lifted up, and his train filled the temple.
Above it stood the seraphims: each one had six wings; with twain he covered his face, and with twain he covered his feet, and with twain he did fly.
- And one cried unto another, and said, Holy, holy, holy, is the LORD of hosts: the whole earth is full of his glory."
+ And one cried unto another, and said, Holy, holy, holy, is the LORD of hosts: the whole earth is full of his glory.”
-KJV Bible, Isaiah6:1-3
%%%%
shadow
-"Between the idea
+“Between the idea
And the reality
Between the motion
And the act
@@ -721,44 +721,44 @@ shadow
Between the emotion
And the response
Falls the Shadow
- Life is very long"
- -T.S. Eliot, "The Hollow Men"
+ Life is very long”
+ -T.S. Eliot, “The Hollow Men”
%%%%
small skeleton
-"When you hear sweet syncopation
+“When you hear sweet syncopation
And the music softly moans
- T'ain't no sin to take off your skin
+ T’ain’t no sin to take off your skin
And dance around in your bones.
When it gets too hot for comfort
And you can’t get ice cream cones
- T'ain't no sin to take off your skin
- And dance around in your bones."
- -William S. Burroughs and Tom Waits, "T'ain't no sin"
+ T’ain’t no sin to take off your skin
+ And dance around in your bones.”
+ -William S. Burroughs and Tom Waits, “T’ain’t no sin”
%%%%
toenail golem
-"Gentle socks pamper them by day, and shoes cobbled of leather fortify them,
+“Gentle socks pamper them by day, and shoes cobbled of leather fortify them,
but my toes hardly notice. All they’re interested in is turning out
toenails—semitransparent, flexible sheets of a hornlike material, as
- defense against—whom?"
+ defense against—whom?”
-Jorge Luis Borges
%%%%
ugly thing
-"Beauty is no quality in things themselves: It exists merely in the mind which
+“Beauty is no quality in things themselves: It exists merely in the mind which
contemplates them; and each mind perceives a different beauty. One person may
even perceive deformity, where another is sensible of beauty; and every
individual ought to acquiesce in his own sentiment, without pretending to
- regulate those of others."
+ regulate those of others.”
-David Hume
%%%%
worm
-"While the angels, all pallid and wan,
+“While the angels, all pallid and wan,
Uprising, unveiling, affirm
- That the play is the tragedy, "Man,"
- And its hero, the Conqueror Worm."
+ That the play is the tragedy, ‘Man’,
+ And its hero, the Conqueror Worm.”
-Edgar Allan Poe
%%%%
####################################################
@@ -766,21 +766,21 @@ worm
####################################################
Cigotuvi's Monster
-"I beheld the wretch - the miserable monster whom I had
+“I beheld the wretch - the miserable monster whom I had
created. He held up the curtain of the bed; and his eyes, if
eyes they may be called, were fixed on me. His jaws opened,
and he muttered some inarticulate sounds, while a grin
- wrinkled his cheeks."
- -Mary Shelley, "Frankenstein"
+ wrinkled his cheeks.”
+ -Mary Shelley, “Frankenstein”
%%%%
strange machine
-"The machine had stood there a long time. It was several
+“The machine had stood there a long time. It was several
hundred feet long and could run on a thimbleful of earth or
- water. It had been working seven and a half million years."
+ water. It had been working seven and a half million years.”
-Sweet Their Blood and Sticky, Albert Teichner
%%%%
mad acolyte of Lugonu
-"And when you look long into an abyss, the abyss also looks into you."
- -Friedrich Nietzche, "Beyond Good and Evil", 1886
+“And when you look long into an abyss, the abyss also looks into you.”
+ -Friedrich Nietzche, “Beyond Good and Evil”, 1886
diff --git a/crawl-ref/source/dat/database/randname.txt b/crawl-ref/source/dat/database/randname.txt
index c03b78db8e..4c3aaf939c 100644
--- a/crawl-ref/source/dat/database/randname.txt
+++ b/crawl-ref/source/dat/database/randname.txt
@@ -891,6 +891,11 @@ smelly
w:3
bronze
+w:2
+@_gemstone_@-studded
+
+@_gemstone_@-encrusted
+
w:200
@armour appearance@
%%%%
@@ -911,6 +916,50 @@ distressingly furry
w:160
@general appearance@
%%%%
+_gemstone_
+
+diamond
+
+ruby
+
+jacinth
+
+sapphire
+
+black opal
+
+emerald
+
+turquoise
+
+citrine
+
+aquamarine
+
+amber
+
+topaz
+
+jet
+
+opal
+
+chrysoberyl
+
+garnet
+
+amethyst
+
+jasper
+
+fluorite
+
+obsidian
+
+agate
+
+jade
+%%%%
######################################################
# Jewellery appearance
######################################################
diff --git a/crawl-ref/source/dat/database/wpnnoise.txt b/crawl-ref/source/dat/database/wpnnoise.txt
index 6c18278421..f210955384 100644
--- a/crawl-ref/source/dat/database/wpnnoise.txt
+++ b/crawl-ref/source/dat/database/wpnnoise.txt
@@ -1022,7 +1022,7 @@ sings
hums
%%%%
-sings_or_whistles
+_sings_or_whistles_
sings
diff --git a/crawl-ref/source/dat/des/branches/elf.des b/crawl-ref/source/dat/des/branches/elf.des
index 8380665348..84fe1d856b 100644
--- a/crawl-ref/source/dat/des/branches/elf.des
+++ b/crawl-ref/source/dat/des/branches/elf.des
@@ -732,6 +732,106 @@ MAP
xxxx
ENDMAP
+NAME: guppyfry_elf_castle
+DEPTH: Elf:2-4
+TAGS: mini_float
+MONS: deep elf soldier / deep elf mage / deep elf knight
+MONS: deep elf blademaster / deep elf death mage / deep elf sorcerer
+MONS: plant
+SUBST: - = .%*3$
+SUBST: ? = .12$
+MAP
+..............
+.xxmxx..xxmxx.
+.x1-1x..x1*1x.
+.x.?.x..x.2.x.
+.xx.xx..xx.xx.
+.x...x..x...x.
+.x...x..x...x.
+.xxx+x++x+xxx.
+.x.2......?.x.
+.x.*1....1-.x.
+.xxmxx++xxmxx.
+..............
+ENDMAP
+
+NAME: guppyfry_elf_garden
+DEPTH: Elf:2-4
+TAGS: mini_float
+MONS: deep elf soldier / deep elf mage / deep elf priest
+MONS: deep elf blademaster / deep elf master archer / deep elf sorcerer
+MONS: plant
+SUBST: - = wwWW333ttt..%
+MAP
+................
+................
+..mmmmT..Tmmmm..
+..m----..----m..
+..m----..----m..
+..m----..----m..
+..3---t..t---3..
+.......21.......
+.......11.......
+..3---t..t---3..
+..m----..----m..
+..m----..----m..
+..m----..----m..
+..mmmmT..Tmmmm..
+................
+................
+ENDMAP
+
+NAME: guppyfry_elf_altar
+DEPTH: Elf:2-4
+MONS: deep elf knight / deep elf priest
+MONS: deep elf high priest
+SUBST: F = G:6 F:1
+KMONS: F = orange crystal statue / silver statue / ice statue
+SUBST: ? = .1$%*
+MAP
+xxxxxxxxxxx
+xC?1.m....+
+x??1Fm....+
+x112.m....x
+x.F..F..xxx
+x.........x
+x..F..F...x
+x.........x
+x...F..F..x
+x.........x
+x...T..T..x
+xxxxx++xxxx
+ENDMAP
+
+NAME: guppyfry_elf_lava
+DEPTH: Elf:2-4
+TAGS: mini_float
+MONS: deep elf conjurer / deep elf mage / deep elf summoner
+MONS: deep elf annihilator / deep elf death mage / deep elf demonologist
+KFEAT: v = general shop type:Elven suffix:Fire count:7 ; \
+ w:10 ring of fire | w:5 scroll of immolation | w:10 ring of protection from fire | \
+ w:4 any weapon ego:flaming | w:4 bow ego:flame | w:12 arrow ego:flame | \
+ w:7 wand of flame | w:5 wand of fire | w:3 wand of fireball | \
+ w:4 bottled efreet | w:4 staff of fire | w:17 randbook disc:fire | \
+ w:6 robe ego:fire_resistance | w:9 any armour ego:fire_resistance
+SUBST: ? = .l1
+SUBST: - = .l
+MAP
+.............
+.xxxx-..-xxxx.
+.xllll-.llllx.
+.xllll.-llllx.
+.xllll-.llllx.
+.-lll?..vlll-.
+...-..12...-..
+..-.-.11..-.-.
+.-lll?..?lll-.
+.xllll.-llllx.
+.xllll-.llllx.
+.xllll.-llllx.
+.xxxx...-xxxx.
+..............
+ENDMAP
##############################################################################
##############################################################################
diff --git a/crawl-ref/source/dat/des/branches/hells.des b/crawl-ref/source/dat/des/branches/hells.des
index 2bdb0e2c31..bd67c95d04 100644
--- a/crawl-ref/source/dat/des/branches/hells.des
+++ b/crawl-ref/source/dat/des/branches/hells.des
@@ -90,7 +90,7 @@ end
# This replaces the hardcoded placement of a hell entrance on D:21-27.
NAME: hell_entry
-TAGS: extra allow_dup luniq
+TAGS: extra allow_dup luniq can_overwrite
DEPTH: D:21-27
CHANCE: 100%
KFEAT: O = enter_hell
@@ -866,13 +866,13 @@ ORIENT: north
TAGS: dis_divider no_vmirror no_rotate
KMONS: 1 = hell sentinel
KMONS: 2 = iron dragon
-KFEAT: 12 = deep_water
+KFEAT: 2 = deep_water
KMASK: w = no_monster_gen
MAP
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv++++vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-vvvvvvvvvvvvvvvvvvvvvvvvvv................vvvvvvvvvvvvvvvvvvvvvvvvvv
+vvvvvvvvvvvvvvvvvvvvvvvvvv1..............1vvvvvvvvvvvvvvvvvvvvvvvvvv
vvvvwwwwwwwwwwwwwwwwwwwwww..wwwwwwwwwwww..wwwwwwwwwwwwwwwwwwwwwwvvvv
-vvvvwwwwwwwwwwwwww2wwwwwww..wwwww11wwwww..wwwwwww2wwwwwwwwwwwwwwvvvv
+vvvvwwwwwwwwwwwwww2wwwwwww..wwwwwwwwwwww..wwwwwww2wwwwwwwwwwwwwwvvvv
vvvvvvvvvvvvvvvvvvvvvvvvvv..vvvvvvvvvvvv..vvvvvvvvvvvvvvvvvvvvvvvvvv
vvvvvvvvvvvvvvvvvvvvvvvvvv++vvvvvvvvvvvv++vvvvvvvvvvvvvvvvvvvvvvvvvv
vvvvvvvv....................................................vvvvvvvv
@@ -1576,10 +1576,18 @@ ENDMAP
# Ereshkigal (Tartarus)
##############################################################################
-NAME: tar_old
-ORIENT: encompass
-MONS: patrolling Ereshkigal, necrophage, wraith, shadow, small zombie
-MONS: small skeleton, Shadow Fiend
+NAME: tar_old
+ORIENT: encompass
+MONS: patrolling Ereshkigal, reaper, shadow demon, shadow
+MONS: lich / ancient lich, shadow dragon / death drake w:1, shadow fiend
+KMONS: 8 = ghoul
+KMONS: 9 = vampire mage / vampire knight
+KMONS: 0 = soul eater
+KMONS: Z = large skeleton / large zombie / small skeleton / small zombie
+KFEAT: A = secret_door
+MARKER: A = lua:restrict_door()
+SUBST: ? = ?..., ? = 2., 0 = 002
+SHUFFLE: 3569
: serpent_of_hell_setup(_G)
: tar_setup(_G)
MAP
@@ -1590,49 +1598,49 @@ xxxx..............................................................xxxx
xxxx.................cccc..........ccc............................xxxx
xxxx.............ccccc..cccc.....ccc.cccc.........................xxxx
xxxx...........ccc.........ccccccc.....cc.........................xxxx
-xxxx.........ccc.......2............V..cc.........................xxxx
+xxxx.........ccc........6...........V..cc.........................xxxx
xxxx........cc4........................cc...........xxxxxxxx......xxxx
-xxxx........cc44xxx==xxx......D........cc..........xx......xx.....xxxx
-xxxx........ccxxx......xxx.......ccc++ccc.........xx........xx....xxxx
+xxxx........cc44xxx++xxx......D........cc..........xx......xx.....xxxx
+xxxx........ccxxx......xxx.......ccc++ccc....6....xx........xx....xxxx
xxxx........cxx..........xxx.....ccc44ccc.........x..........x....xxxx
-xxxx........cx............xx....cccc44cc.........xx..........xx...xxxx
-xxxx.......ccx.G........G.xxx7ccc..c44c..........x.....|......x...xxxx
-xxxx.......cxx............xxxcc..................x......7.....x...xxxx
-xxxx......ccx..............xxc...................xx..........xx...xxxx
+xxxx........cx............xx....cccc44cc.........xx.9......7.xx...xxxx
+xxxx.......ccx.G........G.xxx7ccc..c44c..........x....||||....x...xxxx
+xxxx.......cxx............xxxcc..................x....||||....x...xxxx
+xxxx......ccx..............xxc...................xx.9......9.xx...xxxx
xxxx......ccx..G........G..xxc..x.........x.......x..........x....xxxx
-xxxx......ccx..............xcc....................xx........xx....xxxx
-xxxx.......cxx............xxc......................xx......xx.....xxxx
-xxxx.......ccx.F........F.xcc.......................xxxxxxxx......xxxx
+xxxx......ccx..............xcc......??............xx........xx....xxxx
+xxxx.......cxx............xxc......2222............xx......xx.....xxxx
+xxxx.......ccx.G........G.xcc.......??..............xxxxxxxx......xxxx
xxxx........cx............xc......................................xxxx
xxxx........cxx....17....xxc....x.........x.......................xxxx
xxxx........ccxxx......xxxcc......................................xxxx
-xxxx........cccc=xxxxxx=cccc......................................xxxx
-xxxx........cc||cccccccc||cc......................................xxxx
-xxxx.........cc||||O|||||cc.......................................xxxx
+xxxx........ccccAxxxxxxAcccc.................................3....xxxx
+xxxx........cc$$cccccccc$$cc......................................xxxx
+xxxx.........cc$$$$O$$$$$cc.......................................xxxx
xxxx..........cccccccccccc......x.........x............V..........xxxx
xxxx..............................................................xxxx
-xxxx...........................................xxxxxxxxxxxxxxxx...xxxx
-xxxx...........................................xxxxxxxxxxxxxxxx...xxxx
-xxxx...........................................xx$$$$xxx|||||xx...xxxx
-xxxx.......V........V...........x.........x....xx$$$$xxx|||||xx...xxxx
-xxxx...........................................xxxxxxxxxxxxxxxx...xxxx
-xxxx...........................................xxxxxxxxxxxxxxxx...xxxx
-xxxx...........................................xx44444xx22222xx...xxxx
-xxxx.......xxxxxxxxx+xxxxxxxxx.................xx44444xx22222xx...xxxx
-xxxx.......x3.2..........3...x..x.........x..xxxxxxxxxxxxxxxxxx...xxxx
-xxxx.......x.x.x.x.x.x.x.x.x.x.................xxxxxxxxxxxxxxxx...xxxx
-xxxx.......x...2.3..4..5..4..x......................=.......xxx...xxxx
-xxxx.......xx.x.x.x.x.x.x.x.xx......................=.......xxx...xxxx
-xxxx.......x..65..3..6.6...5.x.................xxxxxxxxxxxxxxxx...xxxx
-xxxx.......x.x.x.x.x.x.x.x.x.x..x.........x..xxxxxxxxxxxxxxxxxx...xxxx
-xxxx.......x...4...3.....4...x.................xx.....xx555555x...xxxx
-xxxx.......xx=xxxxx.x.xxxxxxxx.................xx.....xx555555x...xxxx
-xxxx.......x$$$$$$x.25.x$$$||x.................xxxxxxxxxxxxxxxx...xxxx
-xxxx.......x$x$$x$xx.x.x$x$x|x.................xxxxxxxxxxxxxxxx...xxxx
-xxxx.......x||||||x.556=$$$||x..x.........x....xx$$xx56565xx$|x...xxxx
-xxxx.......xxxxxxxxxxxxxxxxxxx.................xx$$xx65656xx|7x...xxxx
-xxxx...........................................xxxxxxxxxxxxxxxx...xxxx
-xxxx...........................................xxxxxxxxxxxxxxxx...xxxx
+xxxx...........................................cccccccccccccccc...xxxx
+xxxx...........................................cccccccccccccccc...xxxx
+xxxx...........................................cc$$$$$xx|||||cc...xxxx
+xxxx.......3........V...........x....6....x....cc$$$$$xx|||||cc...xxxx
+xxxx...........................................ccxxcccccccccccc...xxxx
+xxxx...........................................ccxxcccccccccccc...xxxx
+xxxx...........................................cc44744xx00000cc...xxxx
+xxxx.......ccccccccc+ccccccccc.................cc44444xx88888cc...xxxx
+xxxx.......c.................c..x.........x..ccccccccccccxxxxcc...xxxx
+xxxx.......c.x.x.x.x.x.x.x.x.c.................ccccccccccxxxxcc...xxxx
+xxxx.......c.................c......................=........cc...xxxx
+xxxx.......cx5x.x.x.x.x.x.x5xc......................=........cc...xxxx
+xxxx.......c.................c.................ccccccccccxxxxcc...xxxx
+xxxx.......c.x.x.x.x5x.x.x.x.c..x.........x..ccccccccccccxxxxcc...xxxx
+xxxx.......c.................c.................ccZZZZZxx88888cc...xxxx
+xxxx.......cxxxxxxx.x.xxxxxxxc.................ccZZZZZxx00000cc...xxxx
+xxxx.......c$$$$$$x....x$$$||c.................ccxxcccccccccccc...xxxx
+xxxx.......c$x$$x$xx.x.x$x$x|c.................ccxxcccccccccccc...xxxx
+xxxx.......c||||||+....+$$$||c..x....3....x....cc||xx444xx|||cc...xxxx
+xxxx.......ccccccccccccccccccc.................cc||xx444xx|7|cc...xxxx
+xxxx...........................................cccccccccccccccc...xxxx
+xxxx...........................................cccccccccccccccc...xxxx
xxxx..............................................................xxxx
xxxx..............................................................xxxx
xxxx........(...........................................[.........xxxx
@@ -1650,30 +1658,32 @@ ENDMAP
# Ereshkigal (Tartarus) by Mu
##############################################################################
-NAME: tar_mu
-ORIENT: encompass
-MONS: patrolling Ereshkigal, shadow fiend, reaper, soul eater, shadow demon
-MONS: shadow dragon, shadow wraith
-KMONS: 8 = shadow imp
+NAME: tar_mu
+ORIENT: encompass
+SUBVAULT: Z : eresh_room
+# Ereshkigal is placed in the subvault.
+MONS: random, shadow fiend, reaper, soul eater, shadow demon
+MONS: shadow dragon, shadow wraith
+KMONS: 8 = shadow imp
: serpent_of_hell_setup(_G)
- ## Randomising the secret doors to get into the pyramid.
- ## There may be secret doors that lead nowhere.
-SHUFFLE: FfGgHh
-SUBST: F = =
-SUBST: f : fff=c, f = =c
-SUBST: G : Gcc, G = =cc
-SUBST: g : gcccc, g = =cc
-SUBST: H = c
-SUBST: h = c
- ## position of the loot chamber varies
-SHUFFLE: AB
-SUBST: A = %
-SUBST: B = x
-NSUBST: " = 1:= / *:x
-KFEAT: % = .
-KMONS: % = soul eater / shadow wraith / nothing
-KITEM: % = | / $
-SUBST: 4 = 3333444455566778
+# Randomising the secret doors to get into the pyramid.
+# There may be secret doors that lead nowhere.
+SHUFFLE: FfGgHh
+SUBST: F = =
+SUBST: f : fff=c, f = =c
+SUBST: G : Gcc, G = =cc
+SUBST: g : gcccc, g = =cc
+SUBST: H = c
+SUBST: h = c
+# position of the loot chamber varies
+SHUFFLE: AB
+SUBST: A = %
+SUBST: B = x
+NSUBST: " = 1:= / *:x
+KFEAT: % = .
+KMONS: % = soul eater w:20 / shadow wraith w:15 / reaper w:5 / nothing w:20
+KITEM: % = | / $
+SUBST: 4 = 3333444455566778
: tar_setup(_G)
MAP
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
@@ -1681,32 +1691,32 @@ xxxx..............................................................xxxx
xxxx..............................................................xxxx
xxxx..cccccccccccccccccccccccccccccc..............................xxxx
xxxx..cccccccccccccccccccccccccccccc..............................xxxx
-xxxx..cc..c.......................cc..............................xxxx
+xxxx..cc..c...........4...........cc..............................xxxx
xxxx..cc..F.......................cc..............................xxxx
xxxx..cc..ccGcccccccccccccccccccGFcc..............................xxxx
xxxx..cc..H.................f..c..cc..............ccccccc.........xxxx
-xxxx..cc..f.................h..H..cc............ccccccccccc.......xxxx
+xxxx..cc..f.........5.......h..H..cc............ccccccccccc.......xxxx
xxxx..cc..chgccccHccccccccGgc..c..cc...........ccccc$$$ccccc......xxxx
xxxx..cc..c..F.G............c..c..cc..........cccc$$$$$$$cccc.....xxxx
xxxx..cc..f..c.ccgcccccccccHc..c..cc..........ccc$$$$$$$$$ccc.....xxxx
-xxxx..cc..c..c.c..........c.c..c..cc.........ccc$$$$$$$$$$$ccc....xxxx
-xxxx..cc..c..c.h...xnnx...f.c..c..cc.........ccc.2.$$$$$.2.ccc....xxxx
-xxxx..cc..c..c.c...x$$x...c.c..c..cc........ccc....xxxxx....ccc...xxxx
-xxxx..cc..c..c.c...x||x...c.c..h..cc........ccc..xxxxxxxxx..ccc...xxxx
-xxxx..cc..c..h.c.xxx..xxx.c.c..c..cc........cc..xxxxxxxxxxx..cc...xxxx
-xxxx..cc..c..c.c.nO..2.1n.c.c..c..cc........cc=cxxxxxxxxxxxc=cc...xxxx
-xxxx..cc..c..c.c.xxx..xxx.c.c..cD.cc........cc.c...........c.cc...xxxx
-xxxx..cc..c..c.c...x||x...c.c..c..cc........cc.c.xxxxxxxxx.c.cc...xxxx
-xxxx..cc..c..c.c...x$$x...c.c..c..cc........cc.c=xxxxxxxxc=c.cc...xxxx
-xxxx..cc..c..G.c...xnnx...c.c..g..cc........cc.c.xx.444.xc.c.cc...xxxx
-xxxx..cc..c..c.c..........c.c..c..cc........cc.c.cx.444.xc.c.cc...xxxx
+xxxx..cc..c..c.cZZZZZZZZZZc.c..c..cc.........ccc$$$$$$$$$$$ccc....xxxx
+xxxx..cc..c..c.hZZZZZZZZZZf.c..c..cc.........ccc.2.$$$$$.2.ccc....xxxx
+xxxx..cc..c..c.cZZZZZZZZZZc.c..c..cc........ccc....xxxxx....ccc...xxxx
+xxxx..cc..c..c.cZZZZZZZZZZc.c..h..cc........ccc..xxxxxxxxx..ccc...xxxx
+xxxx..cc..c..h.cZZZZZZZZZZc.c..c..cc........cc..xxxxxxxxxxx..cc...xxxx
+xxxx..cc.4c..c.cZZZZZZZZZZc.c5.c..cc........cc=cxxxxxxxxxxxc=cc...xxxx
+xxxx..cc..c.5c.cZZZZZZZZZZc.c..cD2cc........cc.c...........c.cc...xxxx
+xxxx..cc..c..c.cZZZZZZZZZZc.c..c..cc........cc.c.xxxxxxxxx.c.cc...xxxx
+xxxx..cc..c..c.cZZZZZZZZZZc.c..c..cc........cc.c=xxxxxxxxc=c.cc...xxxx
+xxxx..cc..c..G.cZZZZZZZZZZc.c..g..cc........cc.c.xx.444.xc.c.cc...xxxx
+xxxx..cc..c..c.cZZZZZZZZZZc.c..c..cc........cc.c.cx.444.xc.c.cc...xxxx
xxxx..cc..c..cFccHccccGcFcc.H..f..cc........cc.c.cxxxxxxxc.c.cc...xxxx
xxxx..cc..c..G............c.c..c..cc........cc.c.cccxxxccc.c.cc...xxxx
xxxx..cc..c..cccccccccccHccfcgcc..cc........cc.c...cxxxc...c.cc...xxxx
-xxxx..cc..F..c.................c..cc........cc.c.cccxxxccc.c.cc...xxxx
+xxxx..cc..F..c......5..........c..cc........cc.c.cccxxxccc.c.cc...xxxx
xxxx..cc..c..g.................c..cc........cc.c.cx|2.2|xc.c.cc...xxxx
xxxx..cccHcfcccHcccccccccccccfcc==cc........cc.c.cx|$$$|xc.c.cc...xxxx
-xxxx..cc.......................c..cc........cc.c.ccccxcccc.c.cc...xxxx
+xxxx..cc............4..........c..cc........cc.c.ccccxcccc.c.cc...xxxx
xxxx..cc.......................c..cc........cc.c....cxc....c.cc...xxxx
xxxx..cccccccccccccccccccccccccc++cc........cc.c.ccccxcccc.c.cc...xxxx
xxxx..cccccccccccccccccccccccccc++cc........cc.c.cxx|||xxc.c.cc...xxxx
@@ -1739,6 +1749,90 @@ xxxx...............................(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ENDMAP
+NAME: eresh_room_1
+TAGS: eresh_room no_rotate
+WEIGHT: 30
+MONS: patrolling Ereshkigal, shadow fiend
+MARKER: = = lua:restrict_door()
+: tar_setup(_G)
+MAP
+..........
+...c==c...
+...c..c...
+...c..c...
+.ccc..ccc.
+.cO.12..c.
+.ccc..ccc.
+...c||c...
+...c||c...
+...cccc...
+..........
+ENDMAP
+
+NAME: eresh_room_2
+TAGS: eresh_room no_rotate
+WEIGHT: 10
+MONS: patrolling Ereshkigal, shadow fiend
+MARKER: = = lua:restrict_door()
+SHUFFLE: |O
+: tar_setup(_G)
+MAP
+..........
+.G......G.
+..........
+c........c
+cc......cc
+|=..21..=O
+cc......cc
+c........c
+..........
+.G......G.
+..........
+ENDMAP
+
+NAME: eresh_room_3
+TAGS: eresh_room no_rotate
+WEIGHT: 10
+MONS: patrolling Ereshkigal, shadow fiend
+MARKER: = = lua:restrict_door()
+: tar_setup(_G)
+MAP
+..........
+..........
+..cc++cc..
+.cc....cc.
+.c......c.
+.cG....Gc.
+.c..12..c.
+.c=cccc=c.
+.cc|O||cc.
+..cccccc..
+..........
+ENDMAP
+
+NAME: eresh_room_4
+TAGS: eresh_room no_rotate
+WEIGHT: 5
+MONS: patrolling Ereshkigal, shadow fiend
+NSUBST: m = 1:==+ / *:nnnnm
+SHUFFLE: 12 / AB
+SUBST: A=., B=.
+MARKER: m = lua:restrict_door()
+: tar_setup(_G)
+MAP
+..........
+.G......G.
+....A.....
+...mmmm...
+...m||m...
+..1mO|m2..
+...m||m...
+...mmmm...
+.....B....
+.G......G.
+..........
+ENDMAP
+
##############################################################################
# Ereshkigal (Tartarus) by minmay
##############################################################################
@@ -1746,9 +1840,14 @@ ENDMAP
NAME: tar_minmay_river
ORIENT: encompass
MONS: patrolling Ereshkigal, reaper, shadow demon, shadow fiend, soul eater
-FTILE: "5 = floor_green_bones
-SUBST: " = .:298 *:1 5:1
+FTILE: "5!?^ = floor_green_bones
+SUBST: 5 = 5:10 3:1
+NSUBST: " = 2:4 / 4:3
+NSUBST: 2 = 3:4 / *:2
NSUBST: w = 3=Ew / 20=Fw / *:w
+NSUBST: ! = 2:. / *:c
+NSUBST: ? = 2:. / *:c
+NSUBST: ^ = 2:. / *:c
KMONS: E = kraken spectre
KMONS: F = shark spectre / big fish spectre / electric eel spectre
KFEAT: EFw = deep_water
@@ -1774,14 +1873,14 @@ XXXXXXc.c..c.cc.cc....cc.cc.c....c.cc...D..cc.c....c.cc.cc....cc.cc.c..c.cXXXXXX
XXXXXXc.c.cc.c..c..cc.+2..c.c....c.c........c.c....c.c..2+.cc..c..c.cc.c.cXXXXXX
XXXXXXc.c.cc.c..c..cc.ccc.c.c....c.c........c.c....c.c.ccc.cc..c..c.cc.c.cXXXXXX
XXXXXXc.c..c.cc.cc......c.c.c....c3c........c3c....c.c.c......cc.cc.c..c.cXXXXXX
-XXXXXXc.cc.c..c..cc+c...c...c2cc.ccccc++++ccccc.cc2c...c...c+cc..c..c.cc.cXXXXXX
+XXXXXXc.cc.c..c..cc+c...c...c2cc2ccccc++++ccccc2cc2c...c...c+cc..c..c.cc.cXXXXXX
XXXXXXc..c.cc.cc..c2c...ccc.c+c...cc........cc...c+c.ccc...c2c..cc.cc.c..cXXXXXX
XXXXXXcc.c..c..cc...cccc33c...c...c..........c...c...c33cccc...cc..c..c.ccXXXXXX
XXXXXXcc.cc.cc..ccc....c33cccccc..c..c....c..c..cccccc33c....ccc..cc.cc.ccXXXXXX
-XXXXXXcc..c..cc...cccc.ccc|||c2c.....c....c.....c2c|||ccc.cccc...cc..c..ccXXXXXX
+XXXXXXcc..c..cc...cccc.ccc|||c.c.....c....c.....c.c|||ccc.cccc...cc..c..ccXXXXXX
XXXXXXccc.cc..ccc........c||cc.cc...cc....cc...cc.cc||c........ccc..cc.cccXXXXXX
-XXXXXXc2c..cc...cccccccc.c|cc...cc2cccc33cccc2cc...cc|c.cccccccc...cc..c2cXXXXXX
-XXXXXXc.cc..ccc.......2+.ccc.....cccc2cccc2cccc.....ccc.+2.......ccc..cc.cXXXXXX
+XXXXXXc.c..cc...cccccccc.c|cc...cc2cccc33cccc2cc...cc|c.cccccccc...cc..c.cXXXXXX
+XXXXXXc.cc..ccc..2....2+.ccc.....cccc2cccc2cccc.....ccc.+2....2..ccc..cc.cXXXXXX
XXXXXXc..cc...cccc....cccc............................cccc....cccc...cc..cXXXXXX
XXXXXX..............WWWWWWWWWWWWWWWWWWWWWWW...............................XXXXXX
XXXXXX..WWWWWWWWWWWWWWwwwwwwwwwwwwwwWwwwwwWWWWWWWW........................XXXXXX
@@ -1792,27 +1891,27 @@ XXXXXXwwwwWwwwwwwwwwwwWwwwwwwwwwwwwWwwwwwwwwwwwWwwwwwwwwwwWwwwwwwwwwwWwwwwXXXXXX
XXXXXXwwwwwWwwwwwwwwwwWwwwwwwwwwwwWwwwwwwwwwwwWwwwwwwwwwwwWwwwwwwwwwwWwwwwXXXXXX
XXXXXXwwwwwWwwwwwwwWWWWWWWWWWWWWWWWWWWwwwwwwwwWwwwwwwwwwwwWwwwwwwwwwwWwwwwXXXXXX
XXXXXXwwwWWWWWWWWWWWcc""""""""""cccccWWWWWWwwwWwwwwwwwwwwWwwwwwwwwwwwWwwwwXXXXXX
-XXXXXXWWWW""""""""ccc"""ccccccc""c""c"""""WWWWWWWWwwwwwwwWwwwwwwwwwwWwwwwwXXXXXX
+XXXXXXWWWW"""^^^^^ccc^^^ccccccc^^c""c"""""WWWWWWWWwwwwwwwWwwwwwwwwwwWwwwwwXXXXXX
XXXXXX"""""""c""""""c""""c5"c""""c""c""""""""""""WWWWWWWWWWWwwwwwwwwWwwwwwXXXXXX
-XXXXXXc"""cccc""c""""""""c""c""""c"""""c"""cccc"""""""""c""WWWWWWWWWWWWWwwXXXXXX
-XXXXXXc""""c""""c""c"""ccc"""""""cc""""c""""""cccccc""""cccc"""""""""""WWWXXXXXX
-XXXXXXc""ccc""""c""c"""""c""""c""c"""c"c"""c"5c""""""""""""c""""c"""c"""""XXXXXX
-XXXXXXc""""c""""c""c"""""""cccc""c5""c"c"""cccc"""""c""""c"c""""c"""c"c""cXXXXXX
+XXXXXXc^^^cccc""c""""""""c""c""""c"""""c^^^cccc"""""""""c""WWWWWWWWWWWWWwwXXXXXX
+XXXXXXc""""c""""c""c"""ccc"""""""cc""""c""""""cccccc^^^^cccc"""""""""""WWWXXXXXX
+XXXXXXc""ccc""""c""c"""""c""""c""c"""c"c"""c"5c""""""""""""c^^^^c^^^c"""""XXXXXX
+XXXXXXc""""c""""c""c"""""""cccc""c5""c"c"""cccc"""""c""""c""""""c"""c"c""cXXXXXX
XXXXXXcc""""""ccccccccc""""c""c""cccccccc"""c"c"""c"c""ccccc""""c""cccccccXXXXXX
-XXXXXXc""""""""c"""c"5cc""""""c""c""""""""""c"""""c"c"""c5""""""cccc5""c"cXXXXXX
-XXXXXX""""c""""c""""""c"""""""c"""""""c"""""""""cccccc""c""""c"""""c"""""cXXXXXX
+XXXXXXc""""""""c"""c"5cc""""""c""c""""""""""c"""""c"c"""c5""""""""cc5""c"cXXXXXX
+XXXXXX""""c""""c""""""c"""""""c"""""""c"""""""""cccccc??c""""c"""""c"""""cXXXXXX
XXXXXX""ccc""""c""""""c""cccccc"""""""c""""""c"""""c""""ccccccc"""cc"""""cXXXXXX
-XXXXXX""""c""""""""cccc"""""c"""""""ccc""""""c""""cc""""c"5c"""""""cccc""cXXXXXX
-XXXXXX""""ccccc"""""""c"""""c"""""""""c""""""c"""""c""c""""c"""""""""c"""cXXXXXX
-XXXXXX"""""5c""""c""""c""""cc"""""c""5c"""cc"ccccc""""c""""c""c""""""c""""XXXXXX
-XXXXXX""ccccc""""c""""""""""c"""cccccccc"""c"""c""""""c""ccc""ccc""""c""""XXXXXX
-XXXXXX""""""c""""c""""""""""c"""""c""""""""c""5ccccc""c""""c""c"""""""""""XXXXXX
+XXXXXX""""c"""??"""cccc"""""c"""""""ccc""""""c""""cc""""c"5c"""""""cccc""cXXXXXX
+XXXXXX""""ccccc"""""""c"""""c"""""""""c""""""c"""??c""c""""c"""""""""c"""cXXXXXX
+XXXXXX"""""5c""""c""""c????cc"""""c""5c"""cc"ccccc""""c""""c""c""""""c""""XXXXXX
+XXXXXX??ccccc""""c""""""""""c???cccccccc???c"""c""""""c""ccc""ccc????c""""XXXXXX
+XXXXXX""""""c""""c""""""""""c"""""c""""""""c""5ccccc""c""""c??c"""""""""""XXXXXX
XXXXXXc""""""""""c"c"""""""""""cccc""""""""ccccc""""""c"""""""c""c"""cccc"XXXXXX
XXXXXXc"""""""""ccccccccccc"""""""c""""""""""""c""""""c"""""ccccccc""c5"""XXXXXX
XXXXXXcccc""""ccc"""5c""""""""""""c""""""""""""c"""ccccc"""cc""""""""cc"""XXXXXX
XXXXXXc5""""""""c""""c""""""""c"""""""""ccc""""c"""c""5cc"""""cc"""""c""ccXXXXXX
-XXXXXXc""""""""""""""cccc"""""c"""""ccccc""""""""""c"""c"""""""cccc""""""cXXXXXX
-XXXXXXccc"""""""""cccc""""""c"c""""""c""cccccc"""""c"""ccc"""ccc"""""""""cXXXXXX
+XXXXXXc""""""""""""""cccc!!!!"c!!!!!ccccc""""""""""c"""c"""""""cccc!!!!!!cXXXXXX
+XXXXXXccc!!!!!!!!!cccc""""""c"c""""""c""cccccc!!!""c"""ccc!!!ccc"""""""""cXXXXXX
XXXXXX"""""""c""""c"c"""""""cccc"""""c""c5""""""cccc"ccc"""""""c""""c""cccXXXXXX
XXXXXX""""""cc""""c"c""""""""""c""""""""c""""""""""c"""""""""""c""cccc"""cXXXXXX
XXXXXX"""""""c""""c""""""""c""5cccc""""ccc""""""""cc"""""""c"cccccc"c""""cXXXXXX
diff --git a/crawl-ref/source/dat/des/branches/lair.des b/crawl-ref/source/dat/des/branches/lair.des
index e42a4ece32..7f8f15ecc0 100644
--- a/crawl-ref/source/dat/des/branches/lair.des
+++ b/crawl-ref/source/dat/des/branches/lair.des
@@ -1278,6 +1278,50 @@ aaaw..ww
ENDMAP
###############################################################################
+# Two stream minivaults
+NAME: guppyfry_lair_drakes
+DEPTH: Lair:3-7
+TAGS: mini_float uniq_mini_stream
+MONS: fire drake / swamp drake / mottled dragon
+MONS: steam dragon
+MONS: plant
+SUBST: - = wwWW..%
+SHUFFLE: .t
+MAP
+.3WW-3.....
+.ttWW-ttt..
+.3ttW-tt.t.
+.ttWWtt...t
+tt1Wttt2.tt
+.ttWW-t3.t.
+..ttWW--1t.
+.tt1-WWttt.
+..tt--Wtt3.
+.tt3.tWWttW
+.ttt.ttWWW-
+....3.3-W-.
+ENDMAP
+
+NAME: guppyfry_mini_stream
+DEPTH: Lair
+TAGS: mini_float uniq_mini_stream
+SUBST: - = wW.%
+MAP
+..WW.......
+.ttWW.ttt..
+..ttW.tt.t.
+.ttWWtt...t
+tt0Wttt0.tt
+.ttWW.t..t.
+..ttWW-.0t.
+.tt0-WWttt.
+..tt.-Wtt..
+.tt..tWWtt.
+.ttt.ttWWtt
+........W..
+ENDMAP
+
+###############################################################################
# Lair endings
###############################################################################
diff --git a/crawl-ref/source/dat/des/branches/orc.des b/crawl-ref/source/dat/des/branches/orc.des
index 3b197a1603..31624bcefc 100644
--- a/crawl-ref/source/dat/des/branches/orc.des
+++ b/crawl-ref/source/dat/des/branches/orc.des
@@ -877,6 +877,63 @@ llllx..xllll
ENDMAP
##################################################
+# The orcs dug into a natural cave and used the bats as a shooting gallery.
+NAME: mines_bat_river
+TAGS: no_item_gen no_monster_gen no_pool_fixup
+DEPTH: Orc
+MONS: bat
+MONS: generate_awake orc ; bow ego:flame | bow ego:frost | bow ego:vorpal . arrow q:10
+NSUBST: . = 2:2 / 2:c
+NSUBST: c = *: 2 .
+KITEM: d = arrow q:1
+NSUBST: b = 3:1 / 10:d / 4:e / *: .:20 1:1 d:2 e:2
+: dgn.delayed_decay(_G, 'e', 'bat corpse')
+SHUFFLE: ABC
+SUBST: A = @
+SUBST: B = x
+SUBST: C = x
+MAP
+ xxx
+ xxxxxxx
+ xxxww.xx
+ xxbww..AA
+ xxbbww...Ax
+ xxbbbbwwW..x
+ xbbbbbbwwW.x
+xxbbbbbbbwW.xx
+xbbbbbbbbww..x
+xxbxbbbbWWww.B
+ xxbbbbbW.WW.B
+ xxxbbbwwWW..x
+ xxxxwwWW..xx
+ xxxwW..CC
+ xxxxxxxC
+ xxxxxxx
+ENDMAP
+
+##################################################
+# The orcs piled up some loose rubble.
+NAME: rock_pile
+TAGS: no_item_gen no_monster_gen mini_float
+DEPTH: Orc
+MONS: orc ; sling . stone q:30, boulder beetle
+KITEM: d = w:3 stone / w:1 large rock q:1
+SUBST: a = .:4 b
+NSUBST: b = 1:2 / 5:1 / *:d
+SUBST: 1 = 1 .
+MAP
+ . .
+ ....
+ ..axaxa..
+ .xabbbax..
+..aabbaxa...
+ .xaaaax..
+ .aaxa....
+ . . ..
+ ...
+ENDMAP
+
+##################################################
NAME: st_orc_town
TAGS: no_rotate no_item_gen
PLACE: Orc:4
diff --git a/crawl-ref/source/dat/des/branches/snake.des b/crawl-ref/source/dat/des/branches/snake.des
index dc345c5523..8dda9b7949 100644
--- a/crawl-ref/source/dat/des/branches/snake.des
+++ b/crawl-ref/source/dat/des/branches/snake.des
@@ -186,6 +186,243 @@ MAP
.......
ENDMAP
+NAME: nicolae_snake_lava_pool
+DEPTH: Snake
+TAGS: mini_float
+SUBST: L = l1
+SUBST: 1 = 1.
+MONS: adder / ball python / black mamba / anaconda w:5 / \
+ water moccasin / nothing w:40
+KMONS: l = lava snake / nothing w:50
+KFEAT: l = lava
+MAP
+ .......
+ ...........
+ .............
+ .....111.....
+.....1LLL1.....
+....1LlllL1....
+...1LlllllL1...
+...1LlllllL1...
+...1LlllllL1...
+....1LlllL1....
+.....1LLL1.....
+ .....111.....
+ .............
+ ...........
+ .......
+ENDMAP
+
+NAME: nicolae_snake_springs
+DEPTH: Snake
+TAGS: mini_float
+SUBST: W = w1
+SUBST: 1 = 1.
+MONS: adder / ball python / black mamba / anaconda w:5 / \
+ water moccasin w:15
+KMONS: w = sea snake / nothing w:90
+KFEAT: w = deep_water
+MAP
+ .......
+ ...........
+ .............
+ .....111.....
+.....1WWW1.....
+....1WwwwW1....
+...1WwwwwwW1...
+...1WwwwwwW1...
+...1WwwwwwW1...
+....1WwwwW1....
+.....1WWW1.....
+ .....111.....
+ .............
+ ...........
+ .......
+ENDMAP
+
+NAME: nicolae_sea_snake_s
+MONS: naga mage, naga
+ORIENT: float
+DEPTH: Snake:2-4
+TAGS: no_monster_gen
+SHUFFLE: {[(
+SHUFFLE: (<
+KFEAT: q = w
+KMONS: q = w:15 sea snake / w:5 nothing
+MAP
+xxxwwwwwwwxxxxxx
+@..wwwqwww.....xx
+@...wwwww.......xx
+@....wqw.........x
+x..2.www....x....x
+xx...wqw...xxx...x
+ x...www...xxx...x
+ x.2.wqw...xxx...x
+ x...www...xxx...x
+ x...wqw...xxx...x
+ x.2.www...xxx...x
+ x....w....xxx...x
+ x.........xxx{.[x
+ xx...1...xxxx...x
+ xx.....xx xx(xx
+ xxxxxxx xxx
+ENDMAP
+
+NAME: nicolae_snake_horde_hoard
+DEPTH: Snake
+KITEM: s = $ / nothing w:25 / * w:1
+KMONS: s = adder w:5 / ball python w:5 / black mamba / anaconda / \
+ water moccasin / sea snake w:1 / nothing w:20
+MARKER: + = lua:restrict_door()
+MAP
+ xxxxxxx
+xxsssssxxxxxx
+xssssssss+..@
+xssssssss+.0@
+xssssssss+..@
+xxsssssxxxxxx
+ xxxxxxx
+ENDMAP
+
+NAME: nicolae_cobra_stairs
+DEPTH: Snake:3-4
+ORIENT: float
+TAGS: no_pool_fixup patrolling
+SHUFFLE: }])
+SUBST: ) = >>)
+MONS: guardian serpent, greater naga, naga mage, naga warrior
+MAP
+ xxxxxxxx
+ xxx......xx
+ xxx..4.www.2xx
+xxxx.9....w3w...x
+@.....wwwwwWw...xx
+@..0.ww.....1...}x
+@..0.W.4.4.3.2..]x
+@..0.ww.....1...)x
+@.....wwwwwWw...xx
+xxxx.9....w3w...x
+ xxx..4.www.2xx
+ xxx......xx
+ xxxxxxxx
+ENDMAP
+
+NAME: nicolae_snake_hallway
+DEPTH: Snake
+ORIENT: float
+SUBST: A : @xx
+SUBST: B : @xx
+SUBST: C : @xx
+SUBST: T : TTTVVUY
+MONS: naga, naga warrior
+MONS: naga mage w:25 / greater naga w:5
+MAP
+ xxxxxx
+ xxx.G.GxxxxxAAxx
+xxx xxx.G..1..Gxx.1..xxx
+@Gxxx xxx.G....1....G...T..xx
+@..Gxxxx.G.2...G.G.....3...1.C
+@..1.G.G.3.2.Gxxxx.G...3...1.C
+@G.1...2.3.Gxxx xxx.G...T..xx
+xx.G...2.Gxxx xxx.1..xxx
+ xxx.G.Gxxx xxBBxx
+ xxxxxx
+ENDMAP
+
+# The disgraced guardian serpent Aizul has been
+# demoted to watching the stairs.
+NAME: nicolae_aizul_guard
+DEPTH: Snake:2-4
+TAGS: no_rotate no_hmirror no_vmirror
+ORIENT: float
+SHUFFLE: ]})>
+SUBST: ) = )>
+: if you.absdepth() > 14 then
+KMONS: A = patrolling Aizul, patrolling greater naga
+KMONS: B = guardian serpent / greater naga
+: else
+KMONS: A = patrolling Aizul, patrolling guardian serpent
+KMONS: B = naga mage / guardian serpent
+: end
+NSUBST: B = A / B
+MAP
+ xxx.@.xxx
+xx.B...B.xx
+x.........x
+xB.......Bx
+....].>....
+@.........@
+....).}....
+xB.......Bx
+x.........x
+xx.B...B.xx
+ xxx.@.xxx
+ENDMAP
+
+NAME: nicolae_snake_shapes
+TAGS: no_pool_fixup mini_float
+DEPTH: Snake
+NSUBST: 0 = 2:9 / 1:8 / *:0
+SUBST: x : xcvmlwWb
+MAP
+ .....
+ ...........
+ ......xxx......
+ .......0x.......
+...xxx..xx..xxx...
+....0x..x0...0x...
+....xx..xxx..xx....
+ ...x0...0x..x0....
+ ...xxx..xx..xxx...
+ .......x0.......
+ ......xxx......
+ ...........
+ .....
+ENDMAP
+
+NAME: nicolae_coiled_stairwell_down
+DEPTH: Snake:1-4
+TAGS: uniq_coiled_stairwell
+SUBST: } = }])>
+MAP
+ xxxxxxx
+ xx.....xx
+xx.xxxxx.xx
+x.xx...xx.x
+x.x.xxx.x.x
+x.x.x}x.x.x
+x.xx..x.x.x
+xx.xxxx.x.x
+ xx....xx.x
+ xxxxxx.xx
+ x...xx
+ xx.xxx
+ x.0.x
+ x...x
+ xx@xx
+ENDMAP
+
+NAME: nicolae_coiled_stairwell_up
+DEPTH: Snake:2-5
+TAGS: uniq_coiled_stairwell
+SUBST: { = {[(<
+MAP
+ xxxxxxx
+ xx.....xx
+xx.xxxxx.xx
+x.xx...xx.x
+x.x.xxx.x.x
+x.x.x{x.x.x
+x.xx..x.x.x
+xx.xxxx.x.x
+ xx....xx.x
+ xxxxxx.xx
+ x...xx
+ xx.xxx
+ x.0.x
+ x...x
+ xx@xx
+ENDMAP
################################################################################
# Snake endings
diff --git a/crawl-ref/source/dat/des/branches/spider.des b/crawl-ref/source/dat/des/branches/spider.des
index 1bef9a0fdd..e7a0429e2c 100644
--- a/crawl-ref/source/dat/des/branches/spider.des
+++ b/crawl-ref/source/dat/des/branches/spider.des
@@ -259,7 +259,7 @@ ENDMAP
NAME: spiders_nest_the_unseen
TAGS: no_item_gen no_monster_gen mini_float
-DEPTH: Spider
+DEPTH: Spider:3-5
MONS: trapdoor spider, patrolling ghost moth
SUBST: | = %%d, * = ..%%d
ITEM: piece of ambrosia
@@ -284,7 +284,7 @@ ENDMAP
NAME: spiders_nest_ghost_moth_duel
TAGS: no_item_gen no_monster_gen mini_float
-DEPTH: Spider
+DEPTH: Spider:3-5
MONS: ghost moth, tarantella
ITEM: piece of ambrosia
MAP
@@ -522,11 +522,10 @@ ENDMAP
NAME: guppyfry_wasp_nest
TAGS: no_monster_gen no_trap_gen
DEPTH: Spider
-ORIENT: float
MONS: yellow wasp / red wasp / nothing
SUBST: - = wW.%
MAP
-WWxxxxxxxxxxxxxxWW
+@WxxxxxxxxxxxxxxW@
xWW....WWWW....WWx
xxWW--WW--WW--WWxx
xxWWWW1111WWWWxx
@@ -711,6 +710,194 @@ xW...WW...Wx
W....WW....W
ENDMAP
+NAME: nicolae_trapdoor_corridor
+DEPTH: Spider:1-3
+MONS: trapdoor spider
+SUBST: z = ....***
+NSUBST: ! = 1:^ / *:.
+NSUBST: ' = 1:^ / *:.
+KFEAT: * = shaft trap w:40 / web / floor
+KFEAT: ^ = known shaft trap
+MAP
+xxxxxxxxxxxxx
+@!.1.xxzzzzxxx
+@!.1.zzz1zzz.xxx
+xxx.zzzxxzz.1.'@
+ xxzzzzzzxx1.'@
+ xxzz1zzxxxxxx
+ xxzzzxx
+ xxxxx
+ENDMAP
+
+NAME: nicolae_orb_island
+DEPTH: Spider:2-5
+TAGS: no_pool_fixup mini_float
+MONS: generate_awake orb spider
+KPROP: 1'z = no_rtele_into
+KMASK: w = no_monster_gen
+SUBST: z = x
+MAP
+ ..
+ ......
+ ....x.....
+ ..........w...
+ ....x.www........
+ ...x..wwwwwww.....
+ ...w...w1''1www....
+ .......w'z''www.x...
+...w...ww'''zzww.....
+....wwww1'''1wwww.....
+ .....ww'zz''ww'ww...
+ ...x.ww''''www'x..w.
+ ..w.wwww'1wwwwx....
+ ....xwwwwwww.......
+ ........ww.w.....
+ w..............
+ ...xx.......
+ ........w
+ .....
+ENDMAP
+
+NAME: nicolae_orb_outpost
+DEPTH: Spider:2-5
+WEIGHT: 3
+TAGS: no_pool_fixup no_monster_gen mini_float
+MONS: generate_awake orb spider
+KPROP: 1' = no_rtele_into
+MAP
+ .....
+ .........
+ ...........
+ ...........
+....wwwww....
+....w1'1w....
+....w'''w....
+....w1'1w....
+....wwwww....
+ ...........
+ ...........
+ .........
+ .....
+ENDMAP
+
+NAME: nicolae_orb_stairs
+TAGS: no_pool_fixup no_monster_gen
+DEPTH: Spider:2-5
+MONS: orb spider / nothing w:8
+SUBST: s = x.
+SUBST: w = www^
+SUBST: . = ...^
+KFEAT: ^ = web / floor
+SHUFFLE: [{(
+MAP
+ ssss@@@ssss
+sssxs^^^sxsss
+ssx...1...xss
+sx.1.www.1.xs
+ss..^...^..ss
+@^.w.....w.^@
+@^1w..[..w1^@
+@^.w.....w.^@
+ss..^...^..ss
+sx.1.www.1.xs
+ssx...1...xss
+sssxs^^^sxsss
+ ssss@@@ssss
+ENDMAP
+
+NAME: nicolae_spider_nook
+DEPTH: Spider
+TAGS: no_monster_gen
+MONS: wolf spider / redback / trapdoor spider / jumping spider / spider
+KITEM: d = | w:5 / * w:20 / $
+KMONS: d = orb spider
+MAP
+ xx+xx
+ xx.x.xx
+ xx1x1x1xx
+xx.x.x.x.xx
+x1x1x1x1x1x
+xx.x.x.x.xx
+ xx1x1x1xx
+ xxdxdxx
+ xx*xx
+ xxx
+ENDMAP
+
+# Demonic crawler nest, maybe with a demonic farmer
+NAME: nicolae_crawler_farm
+DEPTH: Spider
+TAGS: no_monster_gen patrolling no_trap_gen mini_float
+MONS: crimson imp w:50 / white imp w:25 / shadow imp w:15 / \
+ iron imp w:10 / nothing w:50
+MONS: demonic crawler
+KPROP: d' = no_rtele_into
+SUBST: d = c
+NSUBST: c = 6:2 / *:.
+MAP
+ xxxxx
+ xxxxxxxxx
+ xxdl..ldxx
+ xlll.cl'dx
+ xxlc...ldxx
+ xx..l1.lxxx
+ xxc.ll.xxxx
+ xxl...cxxx..
+ xxcl..lxx...
+ xxxc....l...
+ xxxxl......
+ xxxxlllx
+ xxxxx
+ENDMAP
+
+NAME: nicolae_spider_shape
+DEPTH: Spider
+TAGS: mini_float
+MAP
+ ...........
+ .xxx...xxx.
+.....x0x.....
+.xxx0xxx0xxx.
+...0xxxxx....
+....xxxxx0...
+.xxx0xxx0xxx.
+.....x0x.....
+ .xxx...xxx.
+ ...........
+ENDMAP
+
+NAME: nicolae_arachne_temple
+DEPTH: Spider:2-5
+TAGS: no_item_gen no_monster_gen no_trap_gen mini_float
+MONS: spider, tarantella, wolf spider, redback, jumping spider
+FTILE: -2 = FLOOR_SANDSTONE
+FTILE: 'A435 = FLOOR_LIMESTONE
+COLOUR: -2 = brown
+COLOUR: 'A435 = yellow
+KFEAT: -' = web / floor w:40
+KMONS: A = Arachne, orb spider
+MAP
+ .1.
+ cc'cc
+ 1.cc5'''5cc..
+ .'c''--'--''c'1
+ .c'--2-3-2--'c.
+ c'-'-'''''-'-'c
+ c'--'--'--'--'c
+ c5-2'-'-'-'-'2-5c
+ .c'--'--4'4--'--'c.
+ 1'''3''''A''''3'''1
+ .c'--'--4'4--'--'c.
+ c5-2'-'-'-'-'2-5c
+ c'--'--'--'--'c
+ c'-'-'''''-'-'c
+ .c'--2-3-2--'c.
+ 1'c''--'--''c'.
+ ..cc5'''5cc.1
+ cc'cc
+ .1.
+ENDMAP
+
##############################################################################
# Rune vaults
##############################################################################
@@ -724,11 +911,12 @@ MONS: wolf spider / redback / tarantella / jumping spider / w:20 nothing
MONS: trapdoor spider / nothing
MONS: ghost moth
MONS: orb spider
+KMONS: 8 = moth of wrath / ghost moth
NSUBST: 6 = 1:6 / 1:46 / *:4
COLOUR: c = white
-COLOUR: 1O+' = lightgrey
-FTILE: 1cO+' = floor_pebble_lightgray
-NSUBST: ' = 3:3 / 4:2 / *:'
+COLOUR: 18O+' = lightgrey
+FTILE: 18cO+' = floor_pebble_lightgray
+NSUBST: ' = 3:3 / 4:2 / 4=32'' / *:'
TILE: c = wall_vines
SUBST: x = c
SUBST: X = x
@@ -738,6 +926,8 @@ SUBST: W = WW.
SUBST: W = W..
: end
KFEAT: Ww = shallow_water
+SUBST: = : .+
+SUBST: 9 : 7.
MAP
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX
@@ -748,7 +938,7 @@ xxxxxxxxxx44wwwW..WxxW.xx.57.WWxxxxxxxxxxxxxxxX
xxxxxxxxxxx4xxW..Wxxx.WxxWWxW..WxwwwxxxxxxxxxxX
xxxxxxxxxxxxxW.5WxxxxW..xxxxxW..Wwwwww46xxxxxxX
xxxxxxxxxxxxxW..Wxcccc..ccccxW.5.Wxxw444xxxxxxX
-xxxxxxxxxxxxxW.Wxxc1'c++c'1cxxWW..Wxxxx4xxxxxxX
+xxxxxxxxxxxxxW.Wxxc1'c++c'8cxxWW..Wxxxx4xxxxxxX
xxxxxxxxxxxxW.Wxxxc'''cc'''cxxxxW.WxxxxxxxxxxxX
xxxxxxxxxxxW5Wxxxxc''''''''ccccxxW.WWxxxxxxxxxX
xxxxxxxxxxxW.Wx44xc''''''''+'OcxxWW5.WxxxxxxxxX
@@ -761,8 +951,56 @@ xxxxxxxxW..WxxxW.5WxxW.4.WxxW5WxxxxxW...WxxxxxX
xxxxxxxxxW..WxW..WxxxxW..WxxW..WxxW..WWWxxxxxxX
xxxxxxxxxxW.5.W..WxxxxxW...WxxW..W..WWxxxxxxXXX
xxxxxxxxxxxWW...Wxxxxxxx...xxxxWW5WWxxxxxXXXX
-xxxxxxxxxxxxxWWWxxxxxxxx...xxxxxxWxxxxxXXX
+xxxxxxxxxxxxxWWWxxxxxxxx===xxxxxxWxxxxxXXX
xxxxxxxxxxxxxxxxxxxxxxxx+++xxxxxxxxxxxXX
-XXXXXXXXXXXXXXXXXXXXX.........XXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXX99.....99XXXXXXXXX
XXXXXXXXXXXXXXXXXX@@@@@@@@@@@@@@@XXXXXX
ENDMAP
+
+NAME: guppyfry_spider_rune
+PLACE: Spider:5
+TAGS: no_pool_fixup
+ORIENT: southwest
+KITEM: O = gossamer rune of zot
+KMONS: O = ghost moth
+KITEM: * = piece of ambrosia q:3
+KMONS: * = emperor scorpion
+MONS: moth of wrath / ghost moth, ghost moth
+MONS: yellow wasp / red wasp / w:5 nothing
+MONS: w:2 demonic crawler / w:3 emperor scorpion / w:1 nothing
+MONS: tarantella / w:20 wolf spider / jumping spider / w:5 demonic crawler / \
+ w:5 brain worm / w:7 nothing
+MONS: trapdoor spider / nothing
+MONS: w:9 orb spider / w:1 nothing
+KFEAT: ^ = web
+SUBST: - = ....WWW^
+SUBST: = = +.
+SHUFFLE: O12*
+MAP
+xxxxxxxxxxxxxxxxxxx@@@@@@@@@@xxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxx......xxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxx....xxxxxxxxxxxxxxxxx
+xxxxxxxxxxccccccccccccc==cccccccccccccxxxxxx
+xxxxxxxxxxcccccccccccc-.--ccccccccccccxxxxxxx
+xxxxxxxxxxc6Wccccccccc.x.-cccccccccW6cxxxxxxxx
+xxxxxxxxxxc6...++.ccccx.-xccccc++...6cxxxxxxxx
+xxxxxxxxxxcW--.ccc45Oc6--6c154.cc.--Wcxxxxxxxx
+xxxxxxxxxxcc.--ccc55ccx.-xcc55ccc--.ccxxxxxxxx
+xxxxxxxxxxcccW--cccwcc.---ccwccc--Wcccxxxxxxxx
+xxxxxxxxxxcccc.--cc7ccx.-xcc7cc--.ccccxxxxxxxx
+xxxxxxxxxxccccxW--cwcc--.-ccwc--Wxccccxxxxxxxx
+xxxxxxxxxxcccc-.-xx^-x-xx.x-^xx-.-ccccxxxxxxxx
+xxxxxxxxxxccc--3-x--.--55--.--x-3--cccxxxxxxxx
+xxxxxxxxxxccc.333.^.-.5445.-.^.333.cccxxxxxxxx
+xxxxxxxxxxccc--3-x--.--55--.--x-3--cccxxxxxxxx
+xxxxxxxxxxcccc-.-xx^-x.xx-x-^xx-.-ccccxxxxxxxx
+xxxxxxxxxxccccxW--cwcc-.--ccwc--Wxccccxxxxxxxx
+xxxxxxxxxxcccc.--cc7ccx-.xcc7cc--.ccccxxxxxxxx
+xxxxxxxxxxcccW--cccwcc---.ccwccc--Wcccxxxxxxxx
+xxxxxxxxxxcc.--ccc55ccx-.xcc55ccc--.ccxxxxxxxx
+xxxxxxxxxxcW--.cc.45*c7--7c254.cc.--Wcxxxxxxxx
+xxxxxxxxxxc6...++cccccc-.cccccc++...6cxxxxxxxx
+xxxxxxxxxxc6WccccccccccccccccccccccW6cxxxxxxxx
+xxxxxxxxxxccccccccccccccccccccccccccccxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ENDMAP
diff --git a/crawl-ref/source/dat/des/branches/vaults.des b/crawl-ref/source/dat/des/branches/vaults.des
index 43ac5ad83e..c0a0e9eba6 100644
--- a/crawl-ref/source/dat/des/branches/vaults.des
+++ b/crawl-ref/source/dat/des/branches/vaults.des
@@ -316,7 +316,7 @@ KMONS: S = human; robe
KMONS: B: iron troll / cyclops / stone giant / minotaur / vault guard
# the fans:
SUBST: F = 011112223334455679.........
-MONS: human; leather armour|ring mail . dagger|club|ankus|whip|nothing
+MONS: human; leather armour|ring mail . dagger|club|whip|nothing
MONS: elf; robe|leather armour . w:24 quarterstaff|w:1 lajatang|w:75 nothing
# these are Sludge Elves.
MONS: ghoul / necrophage / rotting hulk / vampire
@@ -377,10 +377,8 @@ ORIENT: float
DEPTH: Vaults:3-7
TAGS: no_secret_doors no_monster_gen no_item_gen uniq_the_teleporter \
patrolling
-COLOUR: ME = yellow
+KFEAT: ME = teleporter
MONS: iron golem / crystal golem / stone golem
-TILE: EM = dngn_the_teleporter_vaults
-SUBST: EM = .
SUBST: em = U
MARKER: v = lua:props_marker { veto_shatter="veto" }
MAP
diff --git a/crawl-ref/source/dat/des/branches/zot.des b/crawl-ref/source/dat/des/branches/zot.des
index 14890cd353..7a9e9e3184 100644
--- a/crawl-ref/source/dat/des/branches/zot.des
+++ b/crawl-ref/source/dat/des/branches/zot.des
@@ -9,6 +9,17 @@
#
##############################################################################
+{{
+ -- Orb of Zot placement, similar to how Vaults places its rune
+ -- Turn one 'Z' into the orb, the rest into orb mimics or nothing.
+ function zot5_orb(e)
+ e.nsubst("Z = 1:Z / *:O")
+ e.subst("O = O:1 .:9")
+ e.kitem("O = Orb of Zot mimic")
+ e.subvault("Z : zot5_orb")
+ end
+
+}}
##############################################################################
##############################################################################
@@ -650,7 +661,7 @@ ORIENT: float
TAGS: no_rotate no_hmirror no_monster_gen
MONS: killer klown
MONS: elephant / w:5 dire elephant / w:2 hellephant
-MONS: human ; ankus
+MONS: human ; club
SUBST: 1 = 1 2:5 3:20
SUBST: 2 = 2 2 .
SUBST: % = !:20 ?:5 $ .:20
@@ -911,17 +922,38 @@ XXXXXXXXXXXcc..............ccXXXc...............cXXXcc..............ccXXXXXXXXXX
XXXXXXXXXXXXccccccccccccccccXXXXcccccccc@ccccccccXXXXccccccccccccccccXXXXXXXXXXX
ENDMAP
-NAME: orb_original
-TAGS: orb_chamber
+###########################################################
+# The orb!
+###########################################################
+
+NAME: zot5_orb
+TAGS: zot5_orb no_item_gen
MARKER: Z = lua:item_pickup_change_flags { \
level_flags="!no_tele_control", item="auto" \
}
KITEM: Z = Orb of Zot
-KMASK: Z1! = no_item_gen
+MAP
+Z
+ENDMAP
+
+###########################################################
+# Zot:5 Orb chambers
+###########################################################
+#
+# Each Orb chamber must be capable of placing the Orb. This is done by
+# placing one or more Z and calling zot5_orb(_G). One Z will have the Orb,
+# others will have a small chance of being an orb mimic, or will otherwise
+# be replaced with '.' (plain floor). Avoid using the glyph O, as it is
+# used internally by zot5_orb().
+
+NAME: orb_original
+TAGS: orb_chamber
+KMASK: 1! = no_item_gen
SUBST: ! = ^ .:40
SUBST: . = .:500 ^
COLOUR: c = magenta
KMONS: 1 = patrolling Orb Guardian
+: zot5_orb(_G)
MAP
ccccccccc
ccccccccccc
@@ -949,15 +981,12 @@ ENDMAP
NAME: orb_monky_inset
TAGS: orb_chamber
WEIGHT: 5
-MARKER: Z = lua:item_pickup_change_flags { \
- level_flags="!no_tele_control", item="auto" \
- }
-KITEM: Z = Orb of Zot
-KMASK: Z1! = no_item_gen
+KMASK: 1! = no_item_gen
SUBST: ! = ^ .:40
SUBST: . = .:500 ^
COLOUR: c = magenta
KMONS: 1 = patrolling Orb Guardian
+: zot5_orb(_G)
MAP
ccccccccc
ccccccccccc
@@ -985,22 +1014,18 @@ ENDMAP
NAME: orb_two_ways
TAGS: orb_chamber
WEIGHT: 5
-NSUBST: Y = 1:Z / *:.
-MARKER: Z = lua:item_pickup_change_flags { \
- level_flags="!no_tele_control", item="auto" \
- }
-KITEM: Z = Orb of Zot
-KMASK: YZ1! = no_item_gen
+KMASK: 1! = no_item_gen
SUBST: ! = ^ .:40
SUBST: . = .:500 ^
COLOUR: c = magenta
KMONS: 1 = patrolling Orb Guardian
+: zot5_orb(_G)
MAP
ccccccccc
XXXXXXXXXXX
cXXXXX.....XXXc
cXXX!!!1X...XXc
- XXX!Y!XXX..XX
+ XXX!Z!XXX..XX
XX!!!XX..XX
XXXXXX..XXX
XXXX.....XXXX
@@ -1012,7 +1037,7 @@ cXXX!!!1X...XXc
XXXX.....XXXX
XXXX..XXXXX
XXX..XX!!!X
- XXX..XXX!Y!XX
+ XXX..XXX!Z!XX
cXXX...X1!!!XXc
cXXXX.....XXXXc
XXXXXXXXXXX
@@ -1022,16 +1047,13 @@ ENDMAP
NAME: orb_monky_within_orb
TAGS: orb_chamber
WEIGHT: 5
-MARKER: Z = lua:item_pickup_change_flags { \
- level_flags="!no_tele_control", item="auto" \
- }
-KITEM: Z = Orb of Zot
-KMASK: Z1! = no_item_gen
+KMASK: 1! = no_item_gen
SUBST: ! = ^ .:40
SUBST: . = .:500 ^
COLOUR: cn = magenta
TILE: n = dngn_transparent_wall_magenta
KMONS: 1 = patrolling Orb Guardian
+: zot5_orb(_G)
MAP
ccccccccc
ccccccccccc
@@ -1059,16 +1081,13 @@ ENDMAP
NAME: orb_monky_twist
TAGS: orb_chamber
WEIGHT: 5
-MARKER: Z = lua:item_pickup_change_flags { \
- level_flags="!no_tele_control", item="auto" \
- }
-KITEM: Z = Orb of Zot
-KMASK: Z1! = no_item_gen
+KMASK: 1! = no_item_gen
SUBST: ! = ^ .:40
SUBST: . = .:500 ^
COLOUR: cn = magenta
TILE: n = dngn_transparent_wall_magenta
KMONS: 1 = patrolling Orb Guardian
+: zot5_orb(_G)
MAP
ccccccccc
ccccccccccc
@@ -1095,17 +1114,14 @@ ENDMAP
NAME: mrperson_orb_statues
TAGS: orb_chamber
-MARKER: Z = lua:item_pickup_change_flags { \
- level_flags="!no_tele_control", item="auto" \
- }
-KITEM: Z = Orb of Zot
-KMASK: Z1! = no_item_gen
+KMASK: 1! = no_item_gen
SUBST: ! = ^ .:40
SUBST: . = .:500 ^
COLOUR: G = magenta
SUBST: G = G:100 F:1
KMONS: F = orange crystal statue / silver statue / ice statue
KMONS: 1 = patrolling Orb Guardian
+: zot5_orb(_G)
MAP
ccccccccc
ccccccccccc
diff --git a/crawl-ref/source/dat/des/builder/shops.des b/crawl-ref/source/dat/des/builder/shops.des
index 98440336b3..edd96e899f 100644
--- a/crawl-ref/source/dat/des/builder/shops.des
+++ b/crawl-ref/source/dat/des/builder/shops.des
@@ -150,7 +150,6 @@ ENDMAP
# Custom blood shop Vault
NAME: guppyfry_shop_blood
TAGS: no_monster_gen
-ORIENT: float
DEPTH: D:12-
KMONS: 1 = vampire / bat
KMONS: 2 = vampire / vampire mage / vampire knight
@@ -174,7 +173,6 @@ ENDMAP
# Custom fishing shop Vault
NAME: guppyfry_shop_fishing
TAGS: no_monster_gen mini_float
-ORIENT: float
DEPTH: D:4-
KMONS: 1 = giant goldfish / big fish
KMONS: 2 = place:Shoals:1
diff --git a/crawl-ref/source/dat/des/entry/twisted.des b/crawl-ref/source/dat/des/entry/twisted.des
index 73742fc7d1..8788c0c6be 100644
--- a/crawl-ref/source/dat/des/entry/twisted.des
+++ b/crawl-ref/source/dat/des/entry/twisted.des
@@ -934,3 +934,42 @@ MAP
.nnnnnnn.
.........
ENDMAP
+
+# Three runes > orb of zot > upstairs
+NAME: nicolae_entry_your_instructions
+TAGS: entry no_monster_gen no_trap_gen no_item_gen
+WEIGHT: 1
+ORIENT: float
+SHUFFLE: [(
+SHUFFLE: ABCDEFHIJKLMNOPQR
+KITEM: A = gossamer rune of zot mimic
+KITEM: B = decaying rune of zot mimic
+KITEM: C = serpentine rune of zot mimic
+KITEM: D = barnacled rune of zot mimic
+KITEM: E = slimy rune of zot mimic
+KITEM: F = silver rune of zot mimic
+KITEM: H = abyssal rune of zot mimic
+KITEM: I = demonic rune of zot mimic
+KITEM: J = glowing rune of zot mimic
+KITEM: K = magical rune of zot mimic
+KITEM: L = fiery rune of zot mimic
+KITEM: M = dark rune of zot mimic
+KITEM: N = iron rune of zot mimic
+KITEM: O = icy rune of zot mimic
+KITEM: P = obsidian rune of zot mimic
+KITEM: Q = bone rune of zot mimic
+KITEM: R = golden rune of zot mimic
+KITEM: Z = Orb of Zot mimic
+KPROP: -><ABCDEFHIJKLMNOPQRZ = no_rtele_into
+SUBST: - = .
+MAP
+xxxxxxxxxxxxxxxxxx
+x................x
+x...cccccccccc...xxxxxxxxx
+x...c---C----n...........@
+x.{.c>-Z<B---n.[.........@
+x...c---A----n...........@
+x...cccccccccc...xxxxxxxxx
+x................x
+xxxxxxxxxxxxxxxxxx
+ENDMAP
diff --git a/crawl-ref/source/dat/des/portals/icecave.des b/crawl-ref/source/dat/des/portals/icecave.des
index c1c7588df6..8e668c0000 100644
--- a/crawl-ref/source/dat/des/portals/icecave.des
+++ b/crawl-ref/source/dat/des/portals/icecave.des
@@ -1101,10 +1101,10 @@ lua_marker('M', m_marker)
-- And the slave.
lua_marker('m', portal_desc { teleport_spot=1})
}}
-COLOUR: M = yellow
-TILE: M = dngn_the_teleporter_ice_cave
+KFEAT: M = teleporter
+TILE: M = dngn_teleporter_ice_cave
KPROP: -2!m_| = no_tele_into
-SUBST: Mm- = .
+SUBST: m- = .
SUBST: ! = *
SUBST: _ = <
: dgn.set_random_mon_list("ice beast w:90 / nothing")
diff --git a/crawl-ref/source/dat/des/portals/trove.des b/crawl-ref/source/dat/des/portals/trove.des
index eaba262cbf..9d230c7809 100644
--- a/crawl-ref/source/dat/des/portals/trove.des
+++ b/crawl-ref/source/dat/des/portals/trove.des
@@ -289,14 +289,10 @@ CHANCE: 5%
: trove.portal(_G)
COLOUR: . = blue
COLOUR: c = blue
-: if you.xl() <= 7 then
-# A pack of gnolls want the treasure more than you do!
-KMONS: e = gnoll
-KMONS: l = gnoll / nothing w:5
-: elseif you.xl() <= 15 then
+: if you.absdepth() <= 15 then
# Got drafted in from Vaults:8, while the mages try and close the portal down.
KMONS: e = vault guard
-: elseif you.xl() <= 20 then
+: else
# And this time he brought some friends...
KMONS: e = vault guard
KMONS: l = vault guard
diff --git a/crawl-ref/source/dat/des/portals/volcano.des b/crawl-ref/source/dat/des/portals/volcano.des
index 18ff9ec80a..3314df185b 100644
--- a/crawl-ref/source/dat/des/portals/volcano.des
+++ b/crawl-ref/source/dat/des/portals/volcano.des
@@ -215,7 +215,7 @@ function setup_loot (e)
" / fire dragon armour w:5")
e.item([[potion of berserk rage w:20 / potion of poison w:2 / potion of might w:5 / potion of brilliance w:5 /
potion of agility w:5 / potion of experience w:1 / potion of resistance]])
- e.item(make_fiery_weapon(e, {"demon whip w:2", "dire flail w:4", "ankus w:20", "dagger w:20",
+ e.item(make_fiery_weapon(e, {"demon whip w:2", "dire flail w:4", "dagger w:20",
"sabre w:20", "scimitar w:20", "demon blade w:2",
"triple sword w:1", "broad axe w:20", "battleaxe w:10",
"executioner's axe w:1", "spear w:20", "trident w:20", "demon " ..
diff --git a/crawl-ref/source/dat/des/portals/wizlab.des b/crawl-ref/source/dat/des/portals/wizlab.des
index 0ab1c8a401..b35bad0f34 100644
--- a/crawl-ref/source/dat/des/portals/wizlab.des
+++ b/crawl-ref/source/dat/des/portals/wizlab.des
@@ -51,6 +51,13 @@
# layout: graveyard
# colour: darkgrey, lightgrey
#
+# The Roulette of Golubria
+# threat: distortion, tloc-themed monsters, Abyss monsters
+# loot: tloc-themed consumables / rings / books, abyss escape aides, cloaks
+# xp: 20000+
+# layout: large maw shape with roulette through teeth, old-abyss-esque innards
+# colour: green floor, green/rarely cyan walls
+#
## Random maps
#
# Cloud Mage's Chambers
@@ -379,6 +386,18 @@ function callback.wizlab_wucad_wucad_died(data, triggerable,
crawl.mpr("The shadows inhabiting this place fade forever.", "talk_visual")
end
+function teleporter_golubria_switch_fn(data, triggerable, triggerer, marker, ev)
+ local position = dgn.point(marker:pos())
+ my_slaves = dgn.find_marker_positions_by_prop("teleport_spot",
+ data.teleport_spot)
+
+ if you.teleport_to(my_slaves[1].x, my_slaves[1].y, true) then
+ crawl.mpr("Your surroundings suddenly seem different!")
+ else
+ crawl.mpr("There is a strange hissing noise.")
+ end
+end
+
}}
default-depth: Vaults:2-7, Crypt, D:22-27, Elf:3-5
@@ -1477,6 +1496,196 @@ tttttttttttttttttttttttttttttttttttttttt
tttttttttttttttttttttttttttttttttttttttt
ENDMAP
+##################################################################################
+# The Roulette of Golubria (by HangedMan.)
+# Golubria's fascination with translocations led him to warp out a sub-realm
+# of the Abyss into his own translocations playground, with some nasty and wild
+# security systems built in to defend his many assorted possessions.
+#
+NAME: wizlab_golubria
+TAGS: wizlab no_monster_gen no_item_gen allow_dup no_pool_fixup
+ORIENT: encompass
+LFLAGS: no_tele_control
+KMONS: 1 = spatial vortex / blink frog / insubstantial wisp w:1 / nothing w:4
+KMONS: 2 = deep elf summoner w:5 ; dart ego:dispersal w:20 | dart w:5 | nothing / \
+ rakshasa w:5 ; dart ego:dispersal w:20 | dart w:5 | nothing / \
+ boggart ; dart ego:dispersal w:20 | dart w:5 | nothing / \
+ wizard ; dart ego:dispersal w:20 | dart w:5 | nothing
+KMONS: 3 = rakshasa w:5 ; staff ego:distortion | staff ego:vorpal w:6 | \
+ dagger ego:distortion | dagger ego:vorpal w:6 | \
+ spear ego:distortion | spear ego:vorpal w:6 . dart ego:dispersal / \
+ crimson imp ; staff ego:distortion | staff ego:vorpal w:6 | \
+ dagger ego:distortion | dagger ego:vorpal w:6 | \
+ spear ego:distortion | spear ego:vorpal w:6 . dart ego:dispersal / \
+ boggart w:5 ; staff ego:distortion | staff ego:vorpal w:6 | \
+ dagger ego:distortion | dagger ego:vorpal w:6 | \
+ spear ego:distortion | spear ego:vorpal w:6 . dart ego:dispersal / \
+ wizard ; staff ego:distortion | staff ego:vorpal w:6 | \
+ dagger ego:distortion | dagger ego:vorpal w:6 | \
+ spear ego:distortion | spear ego:vorpal w:6 . dart ego:dispersal
+# Disclaimer: the following three sets are all Abyss spawns.
+KMONS: 04 = large abomination w:40 / small abomination w:40 / large skeleton w:30 / \
+ small skeleton / chaos spawn w:5 / soul eater / hellwing / orange demon / \
+ rotting devil / hell hound / red devil w:5 / lesser demon w:40 / \
+ flying skull / freezing wraith / octopode w:5 / base draconian w:5 / \
+ ugly thing w:30 / fire elemental w:5 / air elemental w:5
+KMONS: 95 = ynoxinul / smoke demon / sun demon w:5 / sixfirhy / efreet w:5 / \
+ hell knight w:5 / demonic crawler / very ugly thing w:5 / \
+ unseen horror / vapour w:5 / stone golem w:5 / \
+ guardian serpent / naga mage w:5 / brain worm / eidolon w:5 / \
+ shadow wraith / anaconda skeleton w:5 / flaming corpse / \
+ great orb of eyes w:5 / giant orange brain w:5
+KMONS: 6 = executioner w:5 / balrug w:5 / cacodemon / shadow demon / hellion w:5 / \
+ tormentor w:5 / lorocyproca w:5 / blizzard demon / green death / \
+ reaper / lich w:5 / angel / death drake w:5 / \
+ tentacled monstrosity / draconian shifter w:5 / profane servitor w:5
+KMONS: 7 = eldritch tentacle / nothing
+KMONS: 8 = silver statue
+# Translocations items, abyss escape aides, shrouds, and an immeadiate aide.
+KITEM: d = scroll of blinking / scroll of teleportation q:2 / \
+ wand of teleportation w:5 / any scroll w:1
+KITEM: e = ring of teleport control w:5 / ring of teleportation
+KITEM: f = book of spatial translocations w:5 / book of the warp w:5 / \
+ manual of translocations w:5 / randbook disc:translocation numspells:5 / \
+ randbook disc:translocation owner:Golubria numspells:7 \
+ spells:shroud_of_golubria|passage_of_golubria
+KITEM: g = ring of levitation / potion of levitation q:2 / \
+ wand of digging w:5 / lantern of shadows / \
+ potion of speed w:5 / scroll of fog / potion of porridge / \
+ any wand w:1 / any potion w:1 / any scroll w:1
+KITEM: h = pair of boots ego:levitation w:9 / pair of boots ego:running w:1 / \
+ pair of boots ego:stealth w:9 / pair of boots w:1
+KITEM: i = cloak good_item w:75 / randart cloak w:95 / cloak unrand:cloak_of_flash / \
+ cloak unrand:cloak_of_starlight / cloak unrand:cloak_of_the_thief
+KITEM: j = wand of disintegration
+KITEM: * = star_item / any w:5, any w:5 / nothing
+KITEM: % = any level:3, any level:3 / nothing
+KFEAT: - = rock_wall
+KFEAT: J = metal_wall
+KFEAT: K = green_crystal_wall
+KFEAT: m = iron_grate
+KFEAT: l = lava w:6 / deep_water w:4 / shallow_water
+KFEAT: D = permarock_wall
+KFEAT: ~ = known teleport trap
+KFEAT: 8_ = altar_lugonu
+KFEAT: OPQRSTUVWXYZ&?[ = teleporter
+KFEAT: opsrtuvwxyz@!] = floor
+KPROP: "_a = no_rtele_into
+MARKER: ~ = lua:fog_machine { cloud_type = "translocational energy", \
+ pow_max = 15, delay_min = 30, delay_max = 60, size_min = 2, size_max = 3 }
+SHUFFLE: qtwz / twzq / wzqt / zqtw, ypsv / vyps / svyp / psvy, ]?A}
+NSUBST: o = 1:o / 1:Q / 1:Y, p = 1:p / 1:R / 1:Z, q = 1:q / 1:S / 1:&
+NSUBST: r = 1:r / 1:T / 1:O, s = 1:s / 1:U / 1:P, t = 1:t / 1:V / 1:Q
+NSUBST: u = 1:u / 1:W / 1:R, v = 1:v / 1:X / 1:S, w = 1:w / 1:Y / 1:T
+NSUBST: x = 1:x / 1:Z / 1:U, y = 1:y / 1:& / 1:V, z = 1:z / 1:O / 1:W
+NSUBST: @ = 1:@ / 1:P / 1:X / 1:<, 4 = 4:5 / 4:4, ` = 4:d / 4:i / 1:j / 5:% / *:`
+NSUBST: a = 1:_ / 1:_" / *:a, + = 2:+ / *:c, ( = 1:! / 1:[ / *:<
+NSUBST: { = 2:< / *:d, 2 = 1:66699 / 1:66993 / 2:9 / 1:993 / 1:92 / *:2
+NSUBST: d = 2:* / 2:e / 2:f / 3:g / 1:eeggh% / 1:gg% / 3:%
+SUBST: a = ':70 -:40 ncCll, F = ":70 -:40 ncCll, c = cccJK, C = cJK, B = cJKn....
+SUBST: e = de, % = %%%%g., * = **%, 4 = 444'', 5 = 5555544'', } = <
+: colour("' = " .. dgn.random_colour() )
+COLOUR: OPQRSTUVWXYZ&?[ = warp
+COLOUR: opqrstuvwxyz@!] = gold
+COLOUR: D = darkgrey
+FTILE: '"GcJKaFn45_+ = floor_demonic_green
+FTILE: .012369AB{< = floor_rough_green / floor_pebble_green w:15
+FTILE: `~78m = floor_demonic_green / floor_pebble_green / floor_rough_green w:5
+FTILE: defghijk*% = floor_rough_green
+LROCKTILE: wall_zot_green
+TILE: c = dngn_stone_wall_green / dngn_stone_wall_cyan w:5
+TILE: K = dngn_crystal_green / dngn_crystal_cyan w:5
+TILE: J = dngn_metal_wall_green / dngn_metal_wall_cyan w:5
+TILE: n = dngn_transparent_wall_green / dngn_transparen_wall_cyan w:5
+TILE: D = wall_stone_dark
+TILE: OPQRSTUVWXYZ&?[ = dngn_trap_golubria
+FTILE: OPQRSTUVWXYZ&?[ = floor_rough_green
+TILE: opqrstuvwxyz@!] = floor_black_cobalt
+
+{{
+-- This isn't the prettiest way of handling the teleporters, but it guarantees
+-- they behave exactly the same way as in HangedMan's original version. All I've
+-- done is remove some massive code duplication. [evilmike]
+
+local teleporter_glyph = "OPQRSTUVWXYZ&?["
+local teleport_spot_glyph = "opqrstuvwxyz@!]"
+local tele_marker = {}
+
+for i = 1, #teleporter_glyph do
+ tele_marker[i] = TriggerableFunction:new {
+ func="teleporter_golubria_switch_fn",
+ data = {teleport_spot=i},
+ repeated=true }
+ tele_marker[i]:add_triggerer(DgnTriggerer:new { type="player_move" })
+ lua_marker(teleporter_glyph:sub(i,i), tele_marker[i])
+ lua_marker(teleport_spot_glyph:sub(i,i), portal_desc { teleport_spot=i})
+end
+
+set_border_fill_type('permarock_wall')
+dgn.set_feature_desc_short("unnaturally hard rock wall", "The dimension's edge")
+dgn.set_feature_desc_short("wall of green crystal", "wall of crystal")
+wizlab_setup(_G, "The Roulette of Golubria")
+}}
+
+epilogue{{
+ wizlab_milestone(_G, "The Roulette of Golubria")
+}}
+MAP
+ DDDDDDDDDD DDDDDDDDDD
+ DDDDDD DDccccccccDDDDDccccccccDD DDDDDD
+ DDDccccDDDDDDcc..o...ccccccc...p..ccDDDDDDccccDDD
+ Dccc.zcccccccco......ocaaacp......pccccccccq.cccD
+ DDcz....ccaaaan........naaan........naaaacc....qcDD
+ Dcc......caaa"n........n"a"n........n"aaac......ccD
+ Dc....B..cnaaan...BBB..naaan..BBB...naaanc..B....cD
+ Dcz..BBB..n"aac...BB2..caaac..2BB...caa"n..BBB..qcD
+ Dcc...BB..ccaacc...B..0caaac0..B...ccaacc..BB...ccD
+ DDcc....2.0caaacc1....ccaaacc....1ccaaac1.2....ccDD
+ Dcccc...{.ccaaacc1.{.caaaaac.{.1ccaaacc1{...ccccD
+ Dcaannc11..ccaaacc...caaaaac...ccaaacc...0cnnaacD
+ Dcaaa"ccc...caaaacc.ccaaaaacc.ccaaaac...ccc"aaacD
+ Dcaaaaaacc..cFaaaFc+cFaaaaaFc+cFaaaFc..ccaaaaaacD
+ DDca"aaaaaccc+FFaFF'F'FaaaaaF'F'FaaFF+cccaaaaa"acDD
+DDccnnnccaaaaFF'FFF'FFFFFF4FFFFFF'FFF'FFaaaaccnnnccDD
+Dccy....ccaaaaFF'F'FFFFFF'G'FFFFFF'F'FFaaaacc....rccD
+Dc.......ccaaaaFF4''FF'F'FFF'F'FF''4FFaaaacc.......cD
+Dc.......1ccaaFF''GF''C'C'F'C'C''FG''FFaacc1.......cD
+Dcy...BB..1ccFF'F'FFCCCCCC(CCCCCCFF'F'FFcc1..BB...rcD
+Dc....BBB...cc'FFF'Cn'C~'CnC'~C'nC'FFF'cc...BBB....cD
+Dc....B2..{..+FFFF'C'@C'``n``'C@'C'FFFF+..{..2B....cD
+Dc..........cc'FF'CCCC`````````CCCC'FF'cc..........cD
+Dccy....0ccccFFFFF'C~'`````````'~C'FFFFFcccc0....rccDDDDDDDD
+DDccnnncccaaaaaFF'CC'````mmm````'CC'FFaaaaacccnnnccDDDnnnnnD
+ Dcaa"aaaaaaaaFF'F'CC'``mm7mm``'CC'F'FFaaaaaaaa"aacDDDn?.}nD
+ DcaaaaaaaaaaaF4GFF(nn``m787m``nn(FFG4FaaaaaaaaaaacDDDn...nD
+ Dcaa"aaaaaaaaFF'F'CC'``mm7mm``'CC'F'FFaaaaaaaa"aacDDDn].AnD
+DDccnnncccaaaaaFF'CC'````mmm````'CC'FFaaaaacccnnnccDDDnnnnnD
+Dccx....0ccccFFFFF'C~'`````````'~C'FFFFFcccc0....sccDDDDDDDD
+Dc..........cc'FF'CCCC`````````CCCC'FF'cc..........cD
+Dc....B2..{..+FFF'CC'@C'`'n'`'C@'C'FFFF+..{..2B....cD
+Dc....BBB...cc'FFF'Cn'C~'CnC'~C'nC'FFF'cc...BBB....cD
+Dcx...BB..1ccFF'F'FFCCCCCC(CCCCCCFF'F'FFcc...BB...scD
+Dc.......1ccaaFF''GF''C'C'F'C'C''FG''FFaacc1.......cD
+Dc.......ccaaaaFF4''FF'F'FFF'F'FF''4FFaaaacc1......cD
+Dccx....ccaaaaaF'F'FFFFFF'G'FFFFFF'F'Faaaaacc....sccD
+DDccnnnccaaaaFF'FFF'FFFFFF4FFFFFF'FFF'FFaaaaccnnnccDD
+ DDca"aaaaaccc+FFaFF'F'FaFFFaF'F'FaaFF+cccaaaaa"acDD
+ Dcaaaaaacc..cFaaaFc+cFaaaaaFc+cFaaaFc..ccaaaaaacD
+ Dcaaa"ccc...caaaacc.ccaaaaacc.ccaaaac...ccc"aaacD
+ Dcaannc0...ccaaacc...caaaaac...ccaaacc..11cnnaacD
+ Dcccc...{1ccaaacc1.{.caaaaac.{.1ccaaacc.{...ccccD
+ DDcc....2.1caaacc1....ccaaacc....1ccaaac0.2....ccDD
+ Dcc...BB..ccaacc...B..0caaac0..B...ccaacc..BB...ccD
+ Dcw..BBB..n"aac...BB2..caaac..2BB...caa"n..BBB..tcD
+ Dc....B..cnaaan...BBB..naaan..BBB...naaanc..B....cD
+ Dcc......caaa"n........n"a"n........n"aaac......ccD
+ DDcw....ccaaaan........naaan........naaaacc....tcDD
+ Dccc.wccccccccv......vcaaacu......ucccccccct.cccD
+ DDDccccDDDDDDcc..v...ccccccc...u..ccDDDDDDccccDDD
+ DDDDDD DDccccccccDDDDDccccccccDD DDDDDD
+ DDDDDDDDDD DDDDDDDDDD
+ENDMAP
+
###############################################################################
# Random and semi-random Wizard vaults
###############################################################################
diff --git a/crawl-ref/source/dat/des/sprint/sprint_mu.des b/crawl-ref/source/dat/des/sprint/sprint_mu.des
index 7d939f5e3f..2c8efad6c5 100644
--- a/crawl-ref/source/dat/des/sprint/sprint_mu.des
+++ b/crawl-ref/source/dat/des/sprint/sprint_mu.des
@@ -822,7 +822,7 @@ KMONS: b = patrolling Duvessa hp:150 ; great sword ego:freezing \
KMONS: a = patrolling Jozef hd:15 hp:100 \
spells:poison_arrow;teleport_other;.;minor_healing;slow \
; dire flail ego:distortion
-KMONS: b = patrolling Joseph hd:5 hp:150 ; ankus ego:freezing \
+KMONS: b = patrolling Joseph hd:5 hp:150 ; quarterstaff ego:freezing \
. blowgun . needle ego:curare q:7
: else
# changed Francis to Wiglaf for now
@@ -917,7 +917,7 @@ MONS: stone giant / shadow dragon / quicksilver dragon / golden dragon /\
MONS: skeletal warrior
KMONS: 8 = silver statue
KMONS: f = butterfly
-KMONS: U = Norris ; ankus ego:vorpal . large shield ego:reflection / \
+KMONS: U = Norris ; spiked flail ego:vorpal . large shield ego:reflection / \
Frederick ; trident ego:freezing . large shield ego:reflection
KMONS: C = generate_awake Chuck
KMONS: k = yaktaur captain ; crossbow ego:chaos . bolt
diff --git a/crawl-ref/source/dat/des/sprint/sprint_v.des b/crawl-ref/source/dat/des/sprint/sprint_v.des
index 2ac6b0f0a2..02b2863b45 100644
--- a/crawl-ref/source/dat/des/sprint/sprint_v.des
+++ b/crawl-ref/source/dat/des/sprint/sprint_v.des
@@ -62,11 +62,8 @@ function setup_room(e, id)
repeated=true }
m_marker:add_triggerer(DgnTriggerer:new { type="player_move" })
e.lua_marker('A', m_marker)
- e.lua_marker('A', portal_desc {
- desc = "teleporter" })
e.colour("A = lightmagenta")
- e.tile("A = dngn_the_teleporter_vaults")
- e.subst("A = .")
+ e.kfeat("A = teleporter")
if id > 1 then
-- Place the teleporter exit
diff --git a/crawl-ref/source/dat/des/traps/beogh_trap.des b/crawl-ref/source/dat/des/traps/beogh_trap.des
index a2bbfb48e9..109fe75f1b 100644
--- a/crawl-ref/source/dat/des/traps/beogh_trap.des
+++ b/crawl-ref/source/dat/des/traps/beogh_trap.des
@@ -103,7 +103,8 @@ x..l13l^l31l..x
x..M13N.N31M..x
x..M13N.N31M..x
xx.MllNZNllM.xx
- x...xx=xx...x
- xxxxx***xxxxx
- xxxxx
+ x...vv=vv...x
+ xxxxv***vxxxx
+ xxvvvvvxx
+ xxxxxxx
ENDMAP
diff --git a/crawl-ref/source/dat/des/traps/boulders.des b/crawl-ref/source/dat/des/traps/boulders.des
new file mode 100644
index 0000000000..3a59926ef4
--- /dev/null
+++ b/crawl-ref/source/dat/des/traps/boulders.des
@@ -0,0 +1,214 @@
+#########################################################
+# Boulder traps
+# Using the new rolling behaviour of boulder beetles,
+# a number of traps in no way affiliated with Lucasfilm.
+#########################################################
+
+{{
+
+-- Generates a boulder rolling at the target x and y
+function boulder_generate(x, y, targetx, targety)
+ local boulder = dgn.create_monster(x, y, 'generate_awake boulder beetle')
+
+ -- Set x, y, velocity
+ local tx = targetx - x
+ local ty = targety - y
+ boulder.set_prop("boulder_x",x)
+ boulder.set_prop("boulder_y",y)
+ boulder.set_prop("boulder_vx",tx)
+ boulder.set_prop("boulder_vy",ty)
+ -- Let it roll!
+ boulder.add_ench("rolling",1,50)
+
+end
+
+-- TODO: Avoid enemies triggering it (altho allow summons)
+function callback.boulder_grate_trap_stepped(data, triggerable, triggerer, marker, ev)
+ if data.triggered == true then
+ return
+ end
+ local x, y = marker:pos()
+ if not you.see_cell(x, y) then
+ -- pretend the monster avoided it
+ return
+ end
+ local p = dgn.find_marker_positions_by_prop(data.gratename, 1)[1]
+ if (p ~= nil) then
+ -- Monster is in the way, don't do anything
+ if (dgn.mons_at(p.x, p.y) ~= nil or p == you.pos()) then
+ if (you.see_cell(x, y)) then
+ crawl.mpr("A part of the floor depresses, but nothing seems to happen.")
+ return
+ end
+ end
+ dgn.grid(p.x, p.y, "iron_grate")
+ if (you.see_cell(p.x, p.y)) then
+ crawl.mpr("An iron grate slams shut!")
+ else
+ crawl.mpr("You hear a soft click.")
+ end
+ end
+ -- Use trap position as default target
+ local tx, ty = marker:pos()
+ -- Check for an explicit target marker
+ local target = dgn.find_marker_positions_by_prop(data.targetname, 1)[1]
+ if target ~= nil then
+ tx = target.x
+ ty = target.y
+ end
+
+ for slave in iter.slave_iterator(data.bouldername, 1) do
+ boulder_generate(slave.x, slave.y, tx,ty)
+ end
+ -- remove the trap
+ dgn.grid(x, y, "floor")
+ data.triggered = true
+
+end
+}}
+
+######################################
+# Simple boulder corridor
+# by mumra
+# A grate slams shut, meaning you have to run from the boulder
+# (or destroy it)
+#
+NAME: boulder_corridor_run
+DEPTH: D:8-13
+TAGS: luniq_boulder_trap no_monster_gen
+ORIENT: float
+KFEAT: ^ = pressure plate trap
+KITEM: ^ = *
+{{
+local tm = TriggerableFunction:new{func="callback.boulder_grate_trap_stepped",
+ repeated=true,
+ data = {targetname="target_run", gratename="grate_run", bouldername="boulder_run"} }
+tm:add_triggerer(DgnTriggerer:new{type="pressure_plate",})
+lua_marker('^', tm)
+lua_marker(',', props_marker { grate_run=1 })
+lua_marker('A', props_marker { boulder_run=1 })
+lua_marker('B', props_marker { target_run=1 })
+}}
+KFEAT: AB=floor
+MAP
+xxxxxxxxxxxxxxxxxx
+xA..^............B@
+xxx,xxxxxxxxxxxxxx
+ @
+ENDMAP
+
+######################################
+# Dual boulder corridor
+# by mumra
+# Two boulders at either end of the corridor
+#
+NAME: boulder_dual_corridor_run
+DEPTH: Lair:3-8
+TAGS: luniq_boulder_trap no_monster_gen ruin_lair
+ORIENT: float
+KFEAT: ^ = pressure plate trap
+KITEM: ^ = *
+{{
+local tm = TriggerableFunction:new{func="callback.boulder_grate_trap_stepped",
+ repeated=true,
+ data = {targetname="target_dual", gratename="grate_dual", bouldername="boulder_dual"} }
+tm:add_triggerer(DgnTriggerer:new{type="pressure_plate"})
+lua_marker('^', tm)
+lua_marker(',', props_marker { grate_dual=1 })
+lua_marker('A', props_marker { boulder_dual=1 })
+lua_marker('B', props_marker { target_dual=1 })
+}}
+KFEAT: AB=floor
+MAP
+xxxxxxxxxxxxxxxxxxx
+.A.......^.......A.
+xxxxxxxxxxxxxxxxxxx
+ENDMAP
+
+########################################
+# Quad boulder room
+# by mumra
+# Four boulders all go for you in the center of the room
+# -- TODO: Make all the boulders slightly miss each other
+NAME: boulder_quad_collide
+DEPTH: Lair:4-8
+TAGS: luniq_boulder_trap no_monster_gen
+ORIENT: float
+KFEAT: ^ = pressure plate trap
+{{
+local tm = TriggerableFunction:new{func="callback.boulder_grate_trap_stepped",
+ repeated=true,
+ data = {targetname="target_quad", gratename="grate_quad", bouldername="boulder_quad"} }
+tm:add_triggerer(DgnTriggerer:new{type="pressure_plate"})
+lua_marker('^', tm)
+lua_marker('^', props_marker { target_quad=1 })
+lua_marker(',', props_marker { grate_quad=1 })
+lua_marker('A', props_marker { boulder_quad=1 })
+}}
+KFEAT: A=floor
+KITEM: ^=*
+MAP
+ xxx@xxx
+ xxx.....xxx
+ xA.......Ax
+xx.........xx
+x...........x
+x...........x
+@.....^.....@
+x...........x
+x...........x
+xx.........xx
+ xA.......Ax
+ xxx....xxxx
+ xxx@xx
+ENDMAP
+
+###################################################
+# "Indie" (mumra)
+# ZorbaBeta's fault
+# TODO: Could steer the boulder along the corridor better by placing target markers on the corners and using a monster_move event
+NAME: boulder_indie
+DEPTH: D:7-14, Snake:1-4
+TAGS: luniq_boulder_trap no_monster_gen
+ORIENT: float
+{{
+local tm = TriggerableFunction:new{func="callback.boulder_grate_trap_stepped",
+ repeated=true,
+ data = {targetname="target_indie", gratename="grate_indie", bouldername="boulder_indie"} }
+tm:add_triggerer(DgnTriggerer:new{type="pressure_plate"})
+lua_marker('^', tm)
+lua_marker(',', props_marker { grate_indie=1 })
+lua_marker('A', props_marker { boulder_indie=1 })
+lua_marker('B', props_marker { target_indie=1 })
+}}
+KFEAT: ^ = pressure plate trap
+SUBST: 2 = x 1 2
+SUBST: 1 = 1 2 .:5
+KMONS: 1 = ball python
+KMONS: 2 = adder
+ : dgn.delayed_decay(_G,'a', 'human skeleton')
+KFEAT: abAB=floor
+KITEM: b = whip w:50 / cursed whip w:10 / whip ego:reaching w:1
+MAP
+ xxxxx
+ xx222xx
+ xx21112xx
+ x211ab12x
+ xx2..12xx
+ xx...xx
+ xx.xx
+ x.xxxxxx
+ x......x
+ xxxxxx.x
+ x.x
+xxxxxxx x.x
+xB....x x.x
+x.xxx.x x.x
+x.x x.x x.x
+x^x x.xxxx.x
+x.x x......x
+x.x xxxxxxxx
+xAx
+x.x
+x@x
+ENDMAP
diff --git a/crawl-ref/source/dat/des/variable/mini_monsters.des b/crawl-ref/source/dat/des/variable/mini_monsters.des
index a7dd84fde7..5678c2629e 100644
--- a/crawl-ref/source/dat/des/variable/mini_monsters.des
+++ b/crawl-ref/source/dat/des/variable/mini_monsters.des
@@ -1553,7 +1553,6 @@ ENDMAP
# Carrion pond
# Bad water, a lot of carrion and feeders around, yuck!
-# Has either necrophage or jackal, but the former is more memorable.
#
# Perhaps use Sewers style water?
# Would also be nice if we could make the corpses fit the branch.
@@ -1565,11 +1564,7 @@ DEPTH: Lair: 2-7 , Swamp
SUBST: ? = %%.
KITEM: % = any corpse
: dgn.delayed_decay(_G, '%', 'any corpse')
-: if you.xl() > 8 then
MONS: necrophage
-: else
-MONS: jackal
-: end
SUBST: ' = 111.
MAP
..'..?..
@@ -2363,6 +2358,47 @@ MAP
(bab bab bababtt
ENDMAP
+NAME: nicolae_well_that_was_easy
+DEPTH: D:4-13
+TAGS: no_hmirror no_vmirror no_monster_gen no_trap_gen no_item_gen mini_float
+WEIGHT: 3
+MARKER: = = lua:restrict_door()
+SUBST: - = ABCDEFHIJKLMNOPQR
+KITEM: A = gossamer rune of zot mimic
+KITEM: B = decaying rune of zot mimic
+KITEM: C = serpentine rune of zot mimic
+KITEM: D = barnacled rune of zot mimic
+KITEM: E = slimy rune of zot mimic
+KITEM: F = silver rune of zot mimic
+KITEM: H = abyssal rune of zot mimic
+KITEM: I = demonic rune of zot mimic
+KITEM: J = glowing rune of zot mimic
+KITEM: K = magical rune of zot mimic
+KITEM: L = fiery rune of zot mimic
+KITEM: M = dark rune of zot mimic
+KITEM: N = iron rune of zot mimic
+KITEM: O = icy rune of zot mimic
+KITEM: P = obsidian rune of zot mimic
+KITEM: Q = bone rune of zot mimic
+KITEM: R = golden rune of zot mimic
+MAP
+ .......
+ ...........
+ ....ccccc....
+ ..nnc...cnn..
+...n.......n...
+..cc.9...9.cc..
+..cG........c..
+..=....-....c..
+..cG........c..
+..cc.9...9.cc..
+...n.......n...
+ ..nnc...cnn..
+ ....ccccc....
+ ...........
+ .......
+ENDMAP
+
###################################################################
#
# <<7>> Random monsters
diff --git a/crawl-ref/source/dat/descript/features.txt b/crawl-ref/source/dat/descript/features.txt
index bf4a3c5c98..c6fd328718 100644
--- a/crawl-ref/source/dat/descript/features.txt
+++ b/crawl-ref/source/dat/descript/features.txt
@@ -324,6 +324,10 @@ A stone wall
A harder obstacle than rock walls. Only the mightiest magic can shatter stone walls.
%%%%
+A teleporter
+
+Stepping on this teleporter will send you to another room.
+%%%%
A translucent rock wall
The mineral this rock consists of is as translucent as good quality glass. Whether it is natural or magical, you can't tell.
@@ -568,6 +572,12 @@ The ground
No life grows here. It is completely dead.
%%%%
+# wizlab: Golubria
+The dimension's edge
+
+On the edge of this tiny, isolated plane, space itself dissolves into oblivion. Entering or affecting
+this black void is impossible.
+%%%%
# wizlab: Cloud Mage
A damp floor
@@ -821,7 +831,3 @@ geometry you know to be true, there can be no denying that here, in this tiny
room, is a vast and terrible sea of impossible size.
Either that, or it's a blue wall.
-%%%%
-A teleporter
-
-Stepping on this teleporter will send you to another room.
diff --git a/crawl-ref/source/dat/descript/items.txt b/crawl-ref/source/dat/descript/items.txt
index 268b9f6c5b..1fdbfcee7a 100644
--- a/crawl-ref/source/dat/descript/items.txt
+++ b/crawl-ref/source/dat/descript/items.txt
@@ -53,10 +53,6 @@ An amulet meticulously constructed with magical wards to block magical and physi
While the amulet is effective against most translocular magic, plane shifts such as banishment are beyond its ability to block.
%%%%
-ankus
-
-What mahouts steer their elephants with. It basically resembles a fireplace poker with a short, stout handle, and a bluntish spike and hook for communicating one's desires through the pachyderm's thick skin.
-%%%%
animal skin
The skins of several animals.
@@ -1134,7 +1130,9 @@ scroll of vorpalise weapon
This scroll enchants the wielded weapon so as to make it far more effective at inflicting harm on its wielder's enemies. Using it on a weapon already affected by some kind of permanent branding is not advised. On the other hand, the scroll can make permanent the temporary branding of weapons obtained from some spells.
-Brands that are closely tied to one of the gods (Trog, Lugonu, Kikubaaquadgha, the Shining One) cannot be affixed this way. Xom, on the other hand is, let's say... less than predictable.
+Brands that are closely tied to one of the gods (Trog, Lugonu,
+Kikubaaquadgha, the Shining One) cannot be affixed this way.
+Xom, on the other hand, wouldn't let such an opportunity for fun go to waste.
%%%%
scroll of vulnerability
@@ -1234,7 +1232,7 @@ This staff increases the power of charm and hex spells cast by its wielder. In t
%%%%
staff of energy
-This staff allows its wielder to cast magical spells without hungering as a result.
+This staff greatly reduces the hunger cost of the wielder's magical spells.
%%%%
staff of fire
diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt
index ad1b2a5e5c..0ee43a8f2e 100644
--- a/crawl-ref/source/dat/descript/monsters.txt
+++ b/crawl-ref/source/dat/descript/monsters.txt
@@ -492,7 +492,7 @@ An umber beetle with large, powerful mandibles which enable it to bore through s
%%%%
boulder beetle
-A huge grey beetle with an almost impenetrable rocky carapace.
+A huge grey beetle with an almost impenetrable rocky carapace, capable of rolling at its foes at high speed.
%%%%
brain worm
@@ -1136,6 +1136,11 @@ The undead form of someone who died of starvation, this creature drains sustenan
hydra
A great and nightmarish lacertilian beast. It has many heads, and the potential to grow many more!
+
+Hitting it with any cutting weapon bigger than a dagger or a quick blade
+risks lopping a head off, which, considering hydra's unique biology, is not
+what you want unless the blade is hot enough to cauterize the wound. Even
+a troll's claws may be enough to rip hydra heads.
%%%%
ice bat
@@ -1441,7 +1446,11 @@ A creature from the heavenly realms. It consists of a wheel within a wheel, and
%%%%
orange crystal statue
-An intricately carved, brittle-looking idol of some nameless godling, hewn of translucent orange crystal. Its lifeless eyes seem to glitter uncannily with a wicked intelligence.
+An intricately carved idol of some nameless godling, hewn of translucent
+orange crystal. Its lifeless eyes seem to glitter uncannily with a wicked
+intelligence.
+
+This statue is very brittle; it will disintegrate at once.
%%%%
orange demon
@@ -1724,8 +1733,10 @@ An orb of divine energy pulsating with blinding light.
%%%%
silver statue
-A beautiful, brittle-looking statue of an unknown malignant creature,
-glistening with a silvery hue. Its eyes glow with an otherworldly radiance.
+A beautiful statue of an unknown malignant creature, glistening with a
+silvery hue. Its eyes glow with an otherworldly radiance.
+
+This statue is very brittle; it will disintegrate at once.
%%%%
siren
@@ -1803,7 +1814,7 @@ A large creature with a woman's head, a lion's body and the wings of a huge bird
%%%%
spider
-An ordinary orb-weaving spider with a with a distinctive white cross on its back. While not as grotesquely huge as other arachnids to be found in this environment, it is still as big as a small cat.
+An ordinary orb-weaving spider with a distinctive white cross on its back. While not as grotesquely huge as other arachnids to be found in this environment, it is still as big as a small cat.
%%%%
spiny frog
diff --git a/crawl-ref/source/dat/descript/pl/items.txt b/crawl-ref/source/dat/descript/pl/items.txt
index 44ad77a868..59db55cfd3 100644
--- a/crawl-ref/source/dat/descript/pl/items.txt
+++ b/crawl-ref/source/dat/descript/pl/items.txt
@@ -74,11 +74,6 @@ Nie wpływa on jednak na środki nie manipulujące czasoprzestrzenią — jak na
przykład przemianę w kamień. Nie działa on także na przejścia do innych
światów, włącznie z rzuceniem w Otchłań.
%%%%
-ankus
-
-Jest to oścień służący do kierowania słoniem. Przypomina nadziak lub bosak,
-z krótką rękojeścią, hakiem i szpikulcem.
-%%%%
animal skin
Prymitywne okrycie ze zwierzęcej skóry.
@@ -1443,7 +1438,7 @@ wrogie uroki.
%%%%
staff of energy
-Ten kij pozwala rzucać czary bez powodowania głodu.
+Ten kij redukuje głód będący skutkiem rzucania czarów.
%%%%
staff of fire
diff --git a/crawl-ref/source/dat/descript/skills.txt b/crawl-ref/source/dat/descript/skills.txt
index c9d868df5d..6f7302bdc3 100644
--- a/crawl-ref/source/dat/descript/skills.txt
+++ b/crawl-ref/source/dat/descript/skills.txt
@@ -102,7 +102,7 @@ A character trained in Traps & Doors will be more observant to his or her surrou
%%%%
Unarmed Combat
-Being skilled in Unarmed Combat increases your accuracy, damage and attack speed in melee combat when barehanded. It also allows you to occasionally make an additional melee attack even when armed, provided you have the means to do so.
+Being skilled in Unarmed Combat increases your accuracy, damage and attack speed in melee combat when barehanded. It also allows you to occasionally punch with your off hand as an additional melee attack, provided your hand is free to do so.
%%%%
Spellcasting
diff --git a/crawl-ref/source/dat/descript/spells.txt b/crawl-ref/source/dat/descript/spells.txt
index 5985cc7c23..b39780f5b4 100644
--- a/crawl-ref/source/dat/descript/spells.txt
+++ b/crawl-ref/source/dat/descript/spells.txt
@@ -280,7 +280,7 @@ This spell hurls a raging blizzard of ice, sleet and freezing gasses at the targ
%%%%
Ignite Poison
-This spell attempts to convert all poison within the caster's view into liquid flame. It is very effective against poisonous creatures or those carrying poison potions. The caster and his gear are not affected.
+This spell attempts to convert all nearby poison into liquid flame, burning poisoned creatures from within. It is very effective against innately poisonous creatures. The caster is not affected.
%%%%
Inner Flame
@@ -296,7 +296,7 @@ This spell hides a creature from the sight of others. While invisible you will g
%%%%
Iskenderun's Mystic Blast
-This spell throws a crackling sphere of destructive energy.
+This spell throws a crackling sphere of destructive energy. The sphere will sometimes explode on impact, and the chance of it doing so is higher if the sphere has traveled less distance.
%%%%
Leda's Liquefaction
diff --git a/crawl-ref/source/dat/dlua/ziggurat.lua b/crawl-ref/source/dat/dlua/ziggurat.lua
index dc36525765..6e33244c46 100644
--- a/crawl-ref/source/dat/dlua/ziggurat.lua
+++ b/crawl-ref/source/dat/dlua/ziggurat.lua
@@ -313,8 +313,8 @@ end
mset(with_props("place:Slime:$", { jelly_protect = true }),
with_props("place:Snake:$", { weight = 5 }),
with_props("place:Lair:$ w:90 / catoblepas", { weight = 5 }),
- with_props("place:Spider:$ w:50 / ghost moth / red wasp / tarantella",
- { weight = 5}),
+ "place:Spider:$ w:50 / ghost moth / red wasp / tarantella / orb spider/" ..
+ "redback",
"place:Crypt:$",
with_props("place:Dwarf:$", { weight = 5 }),
"place:Abyss",
diff --git a/crawl-ref/source/dat/lua/autofight.lua b/crawl-ref/source/dat/lua/autofight.lua
index 6e7ebaa311..f26905cdbf 100644
--- a/crawl-ref/source/dat/lua/autofight.lua
+++ b/crawl-ref/source/dat/lua/autofight.lua
@@ -114,28 +114,30 @@ local function get_monster_info(dx,dy)
info = {}
info.distance = (abs(dx) > abs(dy)) and -abs(dx) or -abs(dy)
if have_ranged() then
- info.can_hit = you.see_cell_no_trans(dx, dy) and 3 or 0
+ info.attack_type = you.see_cell_no_trans(dx, dy) and 3 or 0
elseif not have_reaching() then
- info.can_hit = (-info.distance < 2) and 2 or 0
+ info.attack_type = (-info.distance < 2) and 2 or 0
else
if -info.distance > 2 then
- info.can_hit = 0
+ info.attack_type = 0
elseif -info.distance < 2 then
- info.can_hit = 2
+ info.attack_type = 2
else
- info.can_hit = 1
+ info.attack_type = view.can_reach(dx, dy) and 1 or 0
end
end
+ info.can_attack = (info.attack_type > 0) and 1 or 0
info.safe = m:is_safe() and -1 or 0
+ info.constricting_you = m:is_constricting_you() and 1 or 0
-- Only prioritize good stabs: sleep and paralysis.
- info.very_stabbable = m:is_very_stabbable() and 1 or 0
+ info.very_stabbable = (m:stabbability() >= 1) and 1 or 0
info.injury = m:damage_level()
info.threat = m:threat()
return info
end
local function compare_monster_info(m1, m2)
- flag_order = {"safe", "distance", "very_stabbable", "injury", "threat"}
+ flag_order = {"can_attack", "safe", "distance", "constricting_you", "very_stabbable", "injury", "threat"}
for i,flag in ipairs(flag_order) do
if m1[flag] > m2[flag] then
return true
@@ -152,7 +154,8 @@ local function is_candidate_for_attack(x,y)
if not m or m:attitude() ~= ATT_HOSTILE then
return false
end
- if string.find(m:desc(), "butterfly") then
+ if string.find(m:desc(), "butterfly")
+ or string.find(m:desc(), "orb of destruction") then
return false
end
if m:is_firewood() then
@@ -211,19 +214,20 @@ end
function attack(allow_movement)
local x, y, info = get_target()
+ local caught = you.caught()
if you.confused() then
crawl.mpr("You are too confused!")
- elseif you.caught() then
- crawl.mpr("You are held in a net!")
+ elseif caught then
+ crawl.mpr("You are " .. caught .. "!")
elseif hp_is_low() then
crawl.mpr("You are too injured to fight blindly!")
elseif info == nil then
crawl.mpr("No target in view!")
- elseif info.can_hit == 3 then
+ elseif info.attack_type == 3 then
attack_fire(x,y)
- elseif info.can_hit == 2 then
+ elseif info.attack_type == 2 then
attack_melee(x,y)
- elseif info.can_hit == 1 then
+ elseif info.attack_type == 1 then
attack_reach(x,y)
elseif allow_movement then
move_towards(x,y)
diff --git a/crawl-ref/source/database.cc b/crawl-ref/source/database.cc
index c7befbb359..0d7d61635a 100644
--- a/crawl-ref/source/database.cc
+++ b/crawl-ref/source/database.cc
@@ -253,8 +253,9 @@ bool TextDB::_needs_update() const
// No point in empty databases, although for simplicity keep ones
// for disappeared translations for now.
ASSERT(english);
- delete english->translation;
- english->translation = 0;
+ TextDB *en = english;
+ delete en->translation; // ie, ourself
+ en->translation = 0;
return false;
}
@@ -309,11 +310,13 @@ void TextDB::_regenerate_db()
// DB system
// ----------------------------------------------------------------------
+#ifndef DGAMELAUNCH
static void* init_db(void *arg)
{
AllDBs[(intptr_t)arg].init();
return 0;
}
+#endif
#define NUM_DB ARRAYSZ(AllDBs)
@@ -594,6 +597,9 @@ static std::string _getWeightedString(TextDB &db, const std::string &key,
const std::string &suffix,
int fixed_weight = -1)
{
+ if (!db.get()) // when called by Gretell's "monster"
+ return "";
+
// We have to canonicalise the key (in case the user typed it
// in and got the case wrong.)
std::string canonical_key = key + suffix;
diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc
index f0a990efe8..6676a97335 100644
--- a/crawl-ref/source/decks.cc
+++ b/crawl-ref/source/decks.cc
@@ -76,10 +76,7 @@
// card), deck.props["drawn_cards"] holds the list of drawn cards
// (with index 0 being the first drawn), deck.props["card_flags"]
// holds the flags for each card, deck.props["num_marked"] is the
-// number of marked cards left in the deck, and
-// deck.props["non_brownie_draws"] is the number of non-marked draws
-// you have to make from that deck before earning brownie points from
-// it again.
+// number of marked cards left in the deck.
//
// The card type and per-card flags are each stored as unsigned bytes,
// for a maximum of 256 different kinds of cards and 8 bits of flags.
@@ -858,10 +855,6 @@ bool deck_peek()
if (flags2 & CFLAG_SEEN)
already_seen++;
- // Always increase if seen 2, 50% increase if seen 1.
- if (already_seen && x_chance_in_y(already_seen, 2))
- deck.props["non_brownie_draws"]++;
-
mprf("You draw two cards from the deck. They are: %s and %s.",
card_name(card1), card_name(card2));
@@ -1156,6 +1149,7 @@ bool deck_stack()
}
_check_buggy_deck(deck);
+ you.wield_change = true;
return (true);
}
@@ -2195,10 +2189,17 @@ void sage_card(int power, deck_rarity_type rarity)
mpr("You feel omnipotent."); // All skills maxed.
else
{
- you.set_duration(DUR_SAGE, random2(1800) + 200);
- you.sage_bonus_skill = result;
- you.sage_bonus_degree = power / 25;
+ int xp = exp_needed(std::min<int>(you.max_level, 27) + 1)
+ - exp_needed(std::min<int>(you.max_level, 27));
+ xp = xp / 10 + random2(xp / 4);
+
+ // There may be concurrent sages for the same skill, with different
+ // bonus multipliers.
+ you.sage_skills.push_back(result);
+ you.sage_xp.push_back(xp);
+ you.sage_bonus.push_back(power / 25);
mprf(MSGCH_PLAIN, "You feel studious about %s.", skill_name(result));
+ dprf("Will redirect %d xp, bonus = %d%%\n", xp, (power / 25) * 2);
}
}
@@ -3099,7 +3100,6 @@ void init_deck(item_def &item)
ASSERT(cards_in_deck(item) == item.plus);
props["num_marked"] = (char) 0;
- props["non_brownie_draws"] = (char) 0;
props.assert_validity();
@@ -3124,7 +3124,6 @@ static void _unmark_deck(item_def& deck)
static_cast<char>((static_cast<char>(flags[i]) & ~CFLAG_MARKED));
}
- // We'll be mean and leave non_brownie_draws as-is.
props["num_marked"] = static_cast<char>(0);
}
diff --git a/crawl-ref/source/decks.h b/crawl-ref/source/decks.h
index 9478720f79..4b45c66876 100644
--- a/crawl-ref/source/decks.h
+++ b/crawl-ref/source/decks.h
@@ -17,9 +17,7 @@
// highest index card being the top card, and index 0 being the bottom
// card), deck.props.["card_flags"] holds the flags for each card,
// deck.props["num_marked"] is the number of marked cards left in the
-// deck, and deck.props["non_brownie_draws"] is the number of
-// non-marked draws you have to make from that deck before earning
-// brownie points from it again.
+// deck.
//
// The card type and per-card flags are each stored as unsigned bytes,
// for a maximum of 256 different kinds of cards and 8 bits of flags.
diff --git a/crawl-ref/source/defines.h b/crawl-ref/source/defines.h
index 8d91f6f16e..aacd631533 100644
--- a/crawl-ref/source/defines.h
+++ b/crawl-ref/source/defines.h
@@ -72,6 +72,9 @@ enum extra_monster_index_type
MISC_MISCAST,
};
+// number of monster attack specs
+#define MAX_NUM_ATTACKS 4
+
// size of Pan monster sets. Also used for wave data in ZotDef.
#define MAX_MONS_ALLOC 20
@@ -213,6 +216,21 @@ const int DEPTH_PAN = 52;
const int BRANCH_DUNGEON_DEPTH = 27;
+//#define DEBUG_MIMIC
+#ifdef DEBUG_MIMIC
+// Missing stairs are replaced in fixup_branch_stairs, but replacing
+// too many breaks interlevel connectivity, so we don't use a chance of 1.
+ #define FEATURE_MIMIC_CHANCE 2
+ #define ITEM_MIMIC_CHANCE 1
+ #define FEATURE_MIMIC_DEPTH 1
+ #define ITEM_MIMIC_DEPTH 1
+#else
+ #define FEATURE_MIMIC_CHANCE 100
+ #define ITEM_MIMIC_CHANCE 500
+ #define FEATURE_MIMIC_DEPTH 10
+ #define ITEM_MIMIC_DEPTH 7
+#endif
+
const int ANTITRAIN_PENALTY = 2;
#define TORNADO_RADIUS 6
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index 3a19bf0613..a2455c8166 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -1336,8 +1336,6 @@ static void _armour_wear_effects(const int item_slot)
{
remove_ice_armour();
}
- if (property(arm, PARM_EVASION))
- you.start_train.insert(SK_ARMOUR);
}
else if (eq_slot == EQ_SHIELD)
{
@@ -1406,6 +1404,13 @@ static void _handle_run_delays(const delay_queue_item &delay)
stop_running();
else
{
+ if (Options.auto_eat_chunks)
+ {
+ const interrupt_block block_interrupts;
+ if (prompt_eat_chunks(true) == 1)
+ return;
+ }
+
switch (delay.type)
{
case DELAY_REST:
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 6cc441b329..afaaf04290 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -23,7 +23,6 @@
#include "artefact.h"
#include "cio.h"
#include "clua.h"
-#include "coord.h"
#include "debug.h"
#include "decks.h"
#include "delay.h"
@@ -2031,7 +2030,7 @@ std::string get_item_description(const item_def &item, bool verbose,
<< max_charges << " charges.";
}
else
- description << "\nIt is fully charged.";
+ description << "\nIts capacity can be increased no further.";
const int recharge_rate = short(item.props["rod_enchantment"]);
if (recharge_rate < max_recharge_rate)
@@ -3455,9 +3454,9 @@ void get_monster_db_desc(const monster_info& mi, describe_info &inf,
inf.quote += "\n";
#ifdef DEBUG_DIAGNOSTICS
- if (mi.pos.origin() || !monster_at(player2grid(mi.pos)))
+ if (mi.pos.origin() || !monster_at(mi.pos))
return; // not a real monster
- monster& mons = *monster_at(player2grid(mi.pos));
+ monster& mons = *monster_at(mi.pos);
inf.body << "\nMonster health: "
<< mons.hit_points << "/" << mons.max_hit_points << "\n";
@@ -3484,7 +3483,6 @@ void get_monster_db_desc(const monster_info& mi, describe_info &inf,
inf.body << "; " << comma_separated_line(attitude.begin(),
attitude.end(),
"; ", "; ");
- inf.body << "\n";
if (mons.can_use_spells())
{
@@ -3504,7 +3502,7 @@ void get_monster_db_desc(const monster_info& mi, describe_info &inf,
inf.body << " " << i << ": "
<< spell_title(hspell_pass[i])
<< " (" << static_cast<int>(hspell_pass[i])
- << ")\n";
+ << ")";
}
}
}
@@ -3516,10 +3514,10 @@ void get_monster_db_desc(const monster_info& mi, describe_info &inf,
{
if (!has_item)
{
- inf.body << "\nMonster Inventory:\n";
+ inf.body << "\n\nMonster Inventory:\n";
has_item = true;
}
- inf.body << " " << i << ") "
+ inf.body << " " << i << ": "
<< mitm[mons.inv[i]].name(DESC_A, false, true);
}
}
diff --git a/crawl-ref/source/dgn-labyrinth.cc b/crawl-ref/source/dgn-labyrinth.cc
index 8227f241f8..220b788530 100644
--- a/crawl-ref/source/dgn-labyrinth.cc
+++ b/crawl-ref/source/dgn-labyrinth.cc
@@ -367,7 +367,8 @@ static void _labyrinth_add_blood_trail(const dgn_region &region)
if (you.wizard)
env.pgrid(start) |= FPROP_HIGHLIGHT;
#endif
- bleed_onto_floor(start, MONS_HUMAN, 150, true, false);
+ bleed_onto_floor(start, MONS_HUMAN, 150, true, false, INVALID_COORD,
+ true);
for (unsigned int step = 0; step < path.size(); step++)
{
diff --git a/crawl-ref/source/dgn-layouts.cc b/crawl-ref/source/dgn-layouts.cc
index 9e5a09361d..7d075f64be 100644
--- a/crawl-ref/source/dgn-layouts.cc
+++ b/crawl-ref/source/dgn-layouts.cc
@@ -163,7 +163,8 @@ void dgn_build_bigger_room_level(void)
// A more chaotic version of city level.
void dgn_build_chaotic_city_level(dungeon_feature_type force_wall)
{
- env.level_build_method += make_stringf(" chaotic_city [%d]", (int) force_wall);
+ env.level_build_method += make_stringf(" chaotic_city [%s]",
+ force_wall == NUM_FEATURES ? "any" : dungeon_feature_name(force_wall));
env.level_layout_types.insert("city");
int number_boxes = 5000;
@@ -457,8 +458,8 @@ static void _builder_extras(int level_number)
static bool _octa_room(dgn_region& region, int oblique_max,
dungeon_feature_type type_floor)
{
- env.level_build_method += make_stringf(" octa_room [%d %d]", oblique_max,
- (int) type_floor);
+ env.level_build_method += make_stringf(" octa_room [%d %s]", oblique_max,
+ dungeon_feature_name(type_floor));
int x,y;
@@ -466,7 +467,8 @@ static bool _octa_room(dgn_region& region, int oblique_max,
coord_def br = region.end();
// Hack - avoid lava in the crypt {gdl}
- if ((player_in_branch(BRANCH_CRYPT) || player_in_branch(BRANCH_TOMB))
+ if ((player_in_branch(BRANCH_CRYPT) || player_in_branch(BRANCH_TOMB)
+ || player_in_branch(BRANCH_COCYTUS))
&& type_floor == DNGN_LAVA)
{
type_floor = DNGN_SHALLOW_WATER;
@@ -1028,8 +1030,8 @@ static void _many_pools(dungeon_feature_type pool_type)
const int num_pools = 20 + random2avg(9, 2);
int pools = 0;
- env.level_build_method += make_stringf(" many_pools [%d %d]", (int)pool_type,
- num_pools);
+ env.level_build_method += make_stringf(" many_pools [%s %d]",
+ dungeon_feature_name(pool_type), num_pools);
for (int timeout = 0; pools < num_pools && timeout < 30000; ++timeout)
{
@@ -1071,7 +1073,8 @@ static void _build_river(dungeon_feature_type river_type) //mv
if (player_in_branch(BRANCH_CRYPT) || player_in_branch(BRANCH_TOMB))
return;
- env.level_build_method += make_stringf(" river [%d]", (int) river_type);
+ env.level_build_method += make_stringf(" river [%s]",
+ dungeon_feature_name(river_type));
// Made rivers less wide... min width five rivers were too annoying. -- bwr
width = 3 + random2(4);
@@ -1118,7 +1121,8 @@ static void _build_lake(dungeon_feature_type lake_type) //mv
if (player_in_branch(BRANCH_CRYPT) || player_in_branch(BRANCH_TOMB))
return;
- env.level_build_method += make_stringf(" lake [%d]", (int) lake_type);
+ env.level_build_method += make_stringf(" lake [%s]",
+ dungeon_feature_name(lake_type));
x1 = 5 + random2(GXM - 30);
y1 = 5 + random2(GYM - 30);
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index 6dc7221057..4e3f8d5610 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -3050,6 +3050,8 @@ static std::string _base_feature_desc(dungeon_feature_type grid,
return ("gateway to Hell");
case DNGN_EXIT_HELL:
return ("gateway back into the Dungeon");
+ case DNGN_TELEPORTER:
+ return ("teleporter");
case DNGN_TRAP_MECHANICAL:
return ("mechanical trap");
case DNGN_TRAP_MAGICAL:
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index cafc175975..8987a5bf36 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -2022,20 +2022,6 @@ static void _ruin_level(Iterator ri,
}
}
-//#define DEBUG_MIMIC
-#ifdef DEBUG_MIMIC
-// Missing stairs are replaced in fixup_branch_stairs, but replacing
-// too many breaks interlevel connectivity, so we don't use a chance of 1.
- #define FEATURE_MIMIC_CHANCE 2
- #define ITEM_MIMIC_CHANCE 1
- #define FEATURE_MIMIC_DEPTH 1
- #define ITEM_MIMIC_DEPTH 1
-#else
- #define FEATURE_MIMIC_CHANCE 100
- #define ITEM_MIMIC_CHANCE 500
- #define FEATURE_MIMIC_DEPTH 10
- #define ITEM_MIMIC_DEPTH 7
-#endif
static void _place_feature_mimics(dungeon_feature_type dest_stairs_type)
{
if (player_in_branch(BRANCH_ECUMENICAL_TEMPLE)
@@ -5027,15 +5013,9 @@ void place_spec_shop(const coord_def& where,
for (j = 0; j < 3; j++)
env.shop[i].keeper_name[j] = 1 + random2(200);
- if (!spec->name.empty())
- env.shop[i].shop_name = spec->name;
-
- if (!spec->type.empty())
- env.shop[i].shop_type_name = spec->type;
-
- if (!spec->suffix.empty())
- env.shop[i].shop_suffix_name = spec->suffix;
-
+ env.shop[i].shop_name = spec->name;
+ env.shop[i].shop_type_name = spec->type;
+ env.shop[i].shop_suffix_name = spec->suffix;
env.shop[i].level = level_number * 2;
env.shop[i].type = static_cast<shop_type>(
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index db262797ea..ea31fa22da 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -334,7 +334,11 @@ int torment(actor *attacker, int taux, const coord_def& where)
los.update();
int r = 0;
for (radius_iterator ri(&los); ri; ++ri)
+ {
+ if (attacker && !attacker->see_cell_no_trans(*ri))
+ continue;
r += torment_monsters(*ri, attacker, taux);
+ }
return (r);
}
@@ -2090,7 +2094,8 @@ void handle_time()
added_contamination++;
bool mutagenic_randart = false;
- if (const int artefact_glow = scan_artefacts(ARTP_MUTAGENIC))
+ const int artefact_glow = player_effect_mutagenic();
+ if (artefact_glow)
{
// Reduced randart glow. Note that one randart will contribute
// 2 - 5 units of glow to artefact_glow. A randart with a mutagen
@@ -2267,7 +2272,8 @@ void handle_time()
false, false, false, false, false, true);
// it would kill itself anyway, but let's speed that up
if (one_chance_in(10)
- && (!wearing_amulet(AMU_RESIST_MUTATION) || one_chance_in(10)))
+ && (!player_res_mutation()
+ || one_chance_in(10)))
{
evol |= delete_mutation(MUT_EVOLUTION, "end of evolution", false);
}
@@ -3104,6 +3110,11 @@ static void _recharge_rod(item_def &rod, int aut, bool in_inv)
if (!item_is_rod(rod) || rod.plus >= rod.plus2)
return;
+ // Skill calculations with a massive scale would overflow, cap it.
+ // The worst case, a -3 rod, takes 17000 aut to fully charge.
+ // -4 rods don't recharge at all.
+ aut = std::min(aut, MAX_ROD_CHARGE * ROD_CHARGE_MULT * 10);
+
int rate = 4 + short(rod.props["rod_enchantment"]);
rate *= 10 * aut + skill_bump(SK_EVOCATIONS, aut);
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 11693fb995..48fc6478a4 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -581,6 +581,7 @@ enum cloud_type
#if TAG_MAJOR_VERSION == 32
CLOUD_PETRIFY,
#endif
+ CLOUD_DUST_TRAIL,
NUM_CLOUD_TYPES,
CLOUD_OPAQUE_FIRST = CLOUD_BLACK_SMOKE,
@@ -1130,6 +1131,7 @@ enum dungeon_char_type
DCHAR_ITEM_AMULET,
DCHAR_CLOUD,
DCHAR_TREE,
+ DCHAR_TELEPORTER,
DCHAR_SPACE,
DCHAR_FIRED_FLASK,
@@ -1176,29 +1178,25 @@ enum dungeon_feature_type
DNGN_DETECTED_SECRET_DOOR,
DNGN_SECRET_DOOR,
DNGN_WAX_WALL,
+ DNGN_MINWALL = DNGN_WAX_WALL,
DNGN_METAL_WALL,
DNGN_GREEN_CRYSTAL_WALL,
DNGN_ROCK_WALL,
DNGN_SLIMY_WALL,
DNGN_STONE_WALL,
DNGN_PERMAROCK_WALL, // for undiggable walls
+ DNGN_MAXOPAQUE = DNGN_PERMAROCK_WALL,
DNGN_CLEAR_ROCK_WALL, // transparent walls
+ // Lowest grid value which can be seen through.
+ DNGN_MINSEE = DNGN_CLEAR_ROCK_WALL,
DNGN_CLEAR_STONE_WALL,
DNGN_CLEAR_PERMAROCK_WALL,
+ DNGN_MAXWALL = DNGN_CLEAR_PERMAROCK_WALL,
DNGN_GRATE,
- // Lowest/highest grid value which is a wall.
- DNGN_MINWALL = DNGN_WAX_WALL,
- DNGN_MAXWALL = DNGN_CLEAR_PERMAROCK_WALL,
-
- // Highest grid value which is opaque.
- DNGN_MAXOPAQUE = DNGN_PERMAROCK_WALL,
-
- // Lowest grid value which can be seen through.
- DNGN_MINSEE = DNGN_CLEAR_ROCK_WALL,
-
- // Highest grid value which can't be reached through.
- DNGN_MAX_NONREACH = DNGN_GRATE,
+#if TAG_MAJOR_VERSION == 32
+ // Highest grid value which can't be reached through.
+ DNGN_MAX_NONREACH = DNGN_GRATE,
DNGN_OPEN_SEA, // Shoals equivalent for permarock
@@ -1207,9 +1205,19 @@ enum dungeon_feature_type
DNGN_ORCISH_IDOL,
DNGN_SWAMP_TREE,
DNGN_LAVA_SEA, // Gehenna equivalent for permarock
+#else
+ DNGN_TREE,
+ DNGN_SWAMP_TREE,
+ // Highest grid value which can't be reached through.
+ DNGN_MAX_NONREACH = DNGN_SWAMP_TREE,
+
+ DNGN_OPEN_SEA, // Shoals equivalent for permarock
+ DNGN_LAVA_SEA, // Gehenna equivalent for permarock
+ DNGN_ORCISH_IDOL,
+#endif
DNGN_GRANITE_STATUE = 21,
- // Highest solid grid value.
- DNGN_MAXSOLID = DNGN_GRANITE_STATUE,
+ // Highest solid grid value.
+ DNGN_MAXSOLID = DNGN_GRANITE_STATUE,
// Lowest grid value which can be passed by walking etc.
DNGN_MINMOVE = 31,
@@ -1218,19 +1226,16 @@ enum dungeon_feature_type
DNGN_SHALLOW_WATER = 65,
DNGN_MOVEMENT_MIN = DNGN_SHALLOW_WATER,
- DNGN_WATER_RESERVED,
// Lowest grid value that an item can be placed on.
DNGN_MINITEM = DNGN_SHALLOW_WATER,
- DNGN_FLOOR_MIN = 67,
- DNGN_FLOOR = DNGN_FLOOR_MIN,
- DNGN_FLOOR_RESERVED = 69,
- DNGN_FLOOR_MAX = DNGN_FLOOR_RESERVED,
+ DNGN_FLOOR = 67,
- DNGN_EXIT_HELL, // 70
+ DNGN_EXIT_HELL = 70, // 70
DNGN_ENTER_HELL, // 71
DNGN_OPEN_DOOR, // 72
+ DNGN_TELEPORTER,
DNGN_TRAP_MECHANICAL = 75, // 75
DNGN_TRAP_MAGICAL,
@@ -1420,7 +1425,9 @@ enum duration_type
DUR_STEALTH,
DUR_MAGIC_SHIELD,
DUR_SLEEP,
+#if TAG_MAJOR_VERSION == 32
DUR_SAGE,
+#endif
DUR_TELEPATHY,
DUR_PETRIFIED,
DUR_LOWERED_MR,
@@ -1533,6 +1540,7 @@ enum enchant_type
ENCH_ROUSED, // Monster has been roused to greatness
ENCH_BREATH_WEAPON, // just a simple timer for dragon breathweapon spam
ENCH_DEATHS_DOOR,
+ ENCH_ROLLING, // Boulder Beetle in ball form
// Update enchantment names in monster.cc when adding or removing
// enchantments.
NUM_ENCHANTMENTS
diff --git a/crawl-ref/source/evoke.cc b/crawl-ref/source/evoke.cc
index 398297ca69..9995e91fac 100644
--- a/crawl-ref/source/evoke.cc
+++ b/crawl-ref/source/evoke.cc
@@ -96,8 +96,8 @@ static bool _reaching_weapon_attack(const item_def& wpn)
const int x_distance = abs(delta.x);
const int y_distance = abs(delta.y);
monster* mons = monster_at(beam.target);
- // don't allow targetting of submerged trapdoor spiders
- if (mons && mons->submerged() && feat_is_floor(grd(beam.target)))
+ // don't allow targetting of submerged monsters (includes trapdoor spiders)
+ if (mons && mons->submerged())
mons = NULL;
const int x_first_middle = you.pos().x + (delta.x)/2;
@@ -112,8 +112,8 @@ static bool _reaching_weapon_attack(const item_def& wpn)
mpr("Your weapon cannot reach that far!");
return (false); // Shouldn't happen with confused swings
}
- else if (grd(first_middle) <= DNGN_MAX_NONREACH
- && grd(second_middle) <= DNGN_MAX_NONREACH)
+ else if (!feat_is_reachable_past(grd(first_middle))
+ && !feat_is_reachable_past(grd(second_middle)))
{
// Might also be a granite statue/orcish idol which you
// can reach _past_.
@@ -137,13 +137,12 @@ static bool _reaching_weapon_attack(const item_def& wpn)
// Choose one of the two middle squares (which might be the same).
const coord_def middle =
- (grd(first_middle) <= DNGN_MAX_NONREACH ? second_middle :
- (grd(second_middle) <= DNGN_MAX_NONREACH ? first_middle :
- (coinflip() ? first_middle : second_middle)));
+ (!feat_is_reachable_past(grd(first_middle)) ? second_middle :
+ (!feat_is_reachable_past(grd(second_middle)) ? first_middle :
+ (coinflip() ? first_middle : second_middle)));
- // BCR - Added a check for monsters in the way. Only checks cardinal
- // directions. Knight moves are ignored. Assume the weapon
- // slips between the squares.
+ // Check for a monster in the way. If there is one, it blocks the reaching
+ // attack 50% of the time, and the attack tries to hit it if it is hostile.
// If we're attacking more than a space away...
if (x_distance > 1 || y_distance > 1)
@@ -658,12 +657,6 @@ bool evoke_item(int slot)
return (false);
}
- if (!player_can_handle_equipment())
- {
- canned_msg(MSG_PRESENT_FORM);
- return (false);
- }
-
if (slot == -1)
{
slot = prompt_invent_item("Evoke which item? (* to show all)",
diff --git a/crawl-ref/source/exercise.cc b/crawl-ref/source/exercise.cc
index 6feca72d95..1ae795538d 100644
--- a/crawl-ref/source/exercise.cc
+++ b/crawl-ref/source/exercise.cc
@@ -254,10 +254,6 @@ static bool _check_train_armour(int amount)
{
if (const item_def *armour = you.slot_item(EQ_BODY_ARMOUR, false))
{
- // Don't train armour if we have no EVP.
- if (!property(*armour, PARM_EVASION))
- return (false);
-
// XXX: animal skin; should be a better way to get at that.
const int mass_base = 100;
const int mass = std::max(item_mass(*armour) - mass_base, 0);
diff --git a/crawl-ref/source/feature.cc b/crawl-ref/source/feature.cc
index 3244a33048..4b83d18dda 100644
--- a/crawl-ref/source/feature.cc
+++ b/crawl-ref/source/feature.cc
@@ -223,6 +223,13 @@ static void _init_feat(feature_def &f, dungeon_feature_type feat)
f.minimap = MF_STAIR_BRANCH;
break;
+ case DNGN_TELEPORTER:
+ f.dchar = DCHAR_TELEPORTER;
+ f.colour = YELLOW;
+ f.map_colour = YELLOW;
+ f.minimap = MF_FEATURE;
+ break;
+
case DNGN_TRAP_MECHANICAL:
f.colour = LIGHTCYAN;
f.dchar = DCHAR_TRAP;
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index a8fbdaed47..41d75519b9 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -65,7 +65,7 @@
* for each attack. Combat effects should not go here, if at all possible. This
* is merely a wrapper function which is used to start combat.
*/
-bool fight_melee(actor *attacker, actor *defender, bool *did_hit)
+bool fight_melee(actor *attacker, actor *defender, bool *did_hit, bool simu)
{
if (defender->is_player())
{
@@ -79,6 +79,10 @@ bool fight_melee(actor *attacker, actor *defender, bool *did_hit)
if (attacker->as_monster()->withdrawn())
return (false);
+ // Boulders can't melee while they're rolling past you
+ if (attacker->as_monster()->rolling())
+ return (false);
+
// In case the monster hasn't noticed you, bumping into it will
// change that.
behaviour_event(attacker->as_monster(), ME_ALERT, MHITYOU);
@@ -95,6 +99,9 @@ bool fight_melee(actor *attacker, actor *defender, bool *did_hit)
melee_attack attk(&you, defender);
+ if (simu)
+ attk.simu = true;
+
// We're trying to hit a monster, break out of travel/explore now.
if (!travel_kill_monster(defender->type))
interrupt_activity(AI_HIT_MONSTER, defender->as_monster());
@@ -183,10 +190,15 @@ bool fight_melee(actor *attacker, actor *defender, bool *did_hit)
melee_attack melee_attk(attacker, defender, attack_number,
effective_attack_number);
+ if (simu)
+ melee_attk.simu = true;
+
// If the attack fails out, keep effective_attack_number up to
// date so that we don't cause excess energy loss in monsters
if (!melee_attk.attack())
effective_attack_number = melee_attk.effective_attack_number;
+ else if (did_hit and not *did_hit)
+ *did_hit = melee_attk.did_hit;
}
return (true);
diff --git a/crawl-ref/source/fight.h b/crawl-ref/source/fight.h
index 1a05bf2677..88e2dfea1f 100644
--- a/crawl-ref/source/fight.h
+++ b/crawl-ref/source/fight.h
@@ -25,7 +25,8 @@ enum unchivalric_attack_type
UCAT_ALLY,
};
-bool fight_melee(actor *attacker, actor *defender, bool *did_hit = NULL);
+bool fight_melee(actor *attacker, actor *defender, bool *did_hit = NULL,
+ bool simu = false);
int resist_adjust_damage(actor *defender, beam_type flavour,
int res, int rawdamage, bool ranged = false);
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index 7d1a3e0fb2..91c044ce14 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -843,6 +843,7 @@ static int _get_dest_stair_type(branch_type old_branch,
if (player_in_hell() && stair_taken >= DNGN_STONE_STAIRS_DOWN_I
&& stair_taken <= DNGN_STONE_STAIRS_DOWN_III)
{
+ find_first = false;
return DNGN_ENTER_HELL;
}
diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc
index 7bb761f1df..c291d62568 100644
--- a/crawl-ref/source/food.cc
+++ b/crawl-ref/source/food.cc
@@ -55,9 +55,8 @@
static corpse_effect_type _determine_chunk_effect(corpse_effect_type chunktype,
bool rotten_chunk);
-static void _eat_chunk(corpse_effect_type chunk_effect, bool cannibal,
- int mon_intel = 0, bool orc = false, bool holy = false);
-static void _eating(object_class_type item_class, int item_type);
+static void _eat_chunk(item_def& food);
+static void _eating(item_def &food);
static void _describe_food_change(int hunger_increment);
static bool _vampire_consume_corpse(int slot, bool invent);
static void _heal_from_food(int hp_amt, bool unrot = false,
@@ -1033,22 +1032,13 @@ void eat_inventory_item(int which_inventory_slot)
if (food.sub_type == FOOD_CHUNK)
{
- const monster_type mons_type = food.mon_type;
- const bool cannibal = is_player_same_species(mons_type);
- const int intel = mons_class_intel(mons_type) - I_ANIMAL;
- const bool rotten = food_is_rotten(food);
- const bool orc = (mons_genus(mons_type) == MONS_ORC);
- const bool holy = (mons_class_holiness(mons_type) == MH_HOLY);
- const corpse_effect_type chunk_type = mons_corpse_effect(mons_type);
-
- if (rotten && !_player_can_eat_rotten_meat(true))
+ if (food_is_rotten(food) && !_player_can_eat_rotten_meat(true))
return;
- _eat_chunk(_determine_chunk_effect(chunk_type, rotten), cannibal,
- intel, orc, holy);
+ _eat_chunk(food);
}
else
- _eating(food.base_type, food.sub_type);
+ _eating(food);
you.turn_is_over = true;
dec_inv_item_quantity(which_inventory_slot, 1);
@@ -1069,21 +1059,13 @@ void eat_floor_item(int item_link)
}
else if (food.sub_type == FOOD_CHUNK)
{
- const bool cannibal = is_player_same_species(food.mon_type);
- const int intel = mons_class_intel(food.mon_type) - I_ANIMAL;
- const bool rotten = food_is_rotten(food);
- const bool orc = (mons_genus(food.mon_type) == MONS_ORC);
- const bool holy = (mons_class_holiness(food.mon_type) == MH_HOLY);
- const corpse_effect_type chunk_type = mons_corpse_effect(food.mon_type);
-
- if (rotten && !_player_can_eat_rotten_meat(true))
+ if (food_is_rotten(food) && !_player_can_eat_rotten_meat(true))
return;
- _eat_chunk(_determine_chunk_effect(chunk_type, rotten), cannibal,
- intel, orc, holy);
+ _eat_chunk(food);
}
else
- _eating(food.base_type, food.sub_type);
+ _eating(food);
you.turn_is_over = true;
@@ -1521,7 +1503,8 @@ int prompt_eat_chunks(bool only_auto)
const bool easy_eat = (Options.easy_eat_chunks || only_auto)
&& !you.is_undead && !you.duration[DUR_NAUSEA];
const bool easy_contam = easy_eat
- && (Options.easy_eat_gourmand && wearing_amulet(AMU_THE_GOURMAND)
+ && (Options.easy_eat_gourmand
+ && player_effect_gourmand()
|| Options.easy_eat_contaminated);
if (found_valid)
@@ -1689,7 +1672,7 @@ static int _chunk_nutrition(int likes_chunks)
}
const int gourmand =
- wearing_amulet(AMU_THE_GOURMAND) ? you.duration[DUR_GOURMAND] : 0;
+ player_effect_gourmand() ? you.duration[DUR_GOURMAND] : 0;
const int effective_nutrition =
_apply_gourmand_nutrition_effects(nutrition, gourmand);
@@ -1742,7 +1725,7 @@ static int _contamination_ratio(corpse_effect_type chunk_effect)
// contaminated meat as though it were "clean" meat - level 3
// saprovores get rotting meat effect from clean chunks, since they
// love rotting meat.
- if (wearing_amulet(AMU_THE_GOURMAND))
+ if (player_effect_gourmand())
{
int left = GOURMAND_MAX - you.duration[DUR_GOURMAND];
// [dshaligram] Level 3 saprovores relish contaminated meat.
@@ -1760,9 +1743,16 @@ static int _contamination_ratio(corpse_effect_type chunk_effect)
// Never called directly - chunk_effect values must pass
// through food::_determine_chunk_effect() first. {dlb}:
-static void _eat_chunk(corpse_effect_type chunk_effect, bool cannibal,
- int mon_intel, bool orc, bool holy)
+static void _eat_chunk(item_def& food)
{
+ const bool cannibal = is_player_same_species(food.mon_type);
+ const int intel = mons_class_intel(food.mon_type) - I_ANIMAL;
+ const bool rotten = food_is_rotten(food);
+ const bool orc = (mons_genus(food.mon_type) == MONS_ORC);
+ const bool holy = (mons_class_holiness(food.mon_type) == MH_HOLY);
+ corpse_effect_type chunk_effect = mons_corpse_effect(food.mon_type);
+ chunk_effect = _determine_chunk_effect(chunk_effect, rotten);
+
int likes_chunks = player_likes_chunks(true);
int nutrition = _chunk_nutrition(likes_chunks);
bool suppress_msg = false; // do we display the chunk nutrition message?
@@ -1857,8 +1847,8 @@ static void _eat_chunk(corpse_effect_type chunk_effect, bool cannibal,
if (cannibal)
did_god_conduct(DID_CANNIBALISM, 10);
- else if (mon_intel > 0)
- did_god_conduct(DID_EAT_SOULED_BEING, mon_intel);
+ else if (intel > 0)
+ did_god_conduct(DID_EAT_SOULED_BEING, intel);
if (orc)
did_god_conduct(DID_DESECRATE_ORCISH_REMAINS, 2);
@@ -1868,170 +1858,39 @@ static void _eat_chunk(corpse_effect_type chunk_effect, bool cannibal,
if (do_eat)
{
dprf("nutrition: %d", nutrition);
- start_delay(DELAY_EAT, 2, (suppress_msg) ? 0 : nutrition, -1);
+ start_delay(DELAY_EAT, food_turns(food) - 1,
+ (suppress_msg) ? 0 : nutrition, -1);
lessen_hunger(nutrition, true);
}
}
-static void _eating(object_class_type item_class, int item_type)
+static void _eating(item_def& food)
{
- int food_value = 0;
- int how_herbivorous = player_mutation_level(MUT_HERBIVOROUS);
- int how_carnivorous = player_mutation_level(MUT_CARNIVOROUS);
- int carnivore_modifier = 0;
- int herbivore_modifier = 0;
+ int food_value = ::food_value(food);
+ ASSERT(food_value > 0);
- switch (item_class)
+ if (you.duration[DUR_NAUSEA])
{
- case OBJ_FOOD:
- // apply base sustenance {dlb}:
- switch (item_type)
- {
- case FOOD_MEAT_RATION:
- case FOOD_ROYAL_JELLY:
- food_value = 5000;
- break;
- case FOOD_BREAD_RATION:
- food_value = 4400;
- break;
- case FOOD_AMBROSIA:
- food_value = 2500;
- break;
- case FOOD_HONEYCOMB:
- food_value = 2000;
- break;
- case FOOD_SNOZZCUMBER: // Maybe a nasty side-effect from RD's book?
- // I'd like that, but I don't dare. (jpeg)
- case FOOD_PIZZA:
- case FOOD_BEEF_JERKY:
- food_value = 1500;
- break;
- case FOOD_CHEESE:
- case FOOD_SAUSAGE:
- food_value = 1200;
- break;
- case FOOD_ORANGE:
- case FOOD_BANANA:
- case FOOD_LEMON:
- food_value = 1000;
- break;
- case FOOD_PEAR:
- case FOOD_APPLE:
- case FOOD_APRICOT:
- food_value = 700;
- break;
- case FOOD_CHOKO:
- case FOOD_RAMBUTAN:
- case FOOD_LYCHEE:
- food_value = 600;
- break;
- case FOOD_STRAWBERRY:
- food_value = 200;
- break;
- case FOOD_GRAPE:
- food_value = 100;
- break;
- case FOOD_SULTANA:
- food_value = 70; // Will not save you from starvation.
- break;
- default:
- break;
- }
-
- // Next, sustenance modifier for carnivores/herbivores {dlb}:
- switch (item_type)
- {
- case FOOD_MEAT_RATION:
- carnivore_modifier = 500;
- herbivore_modifier = -1500;
- break;
- case FOOD_BEEF_JERKY:
- case FOOD_SAUSAGE:
- carnivore_modifier = 200;
- herbivore_modifier = -200;
- break;
- case FOOD_BREAD_RATION:
- carnivore_modifier = -1000;
- herbivore_modifier = 500;
- break;
- case FOOD_BANANA:
- case FOOD_ORANGE:
- case FOOD_LEMON:
- carnivore_modifier = -300;
- herbivore_modifier = 300;
- break;
- case FOOD_PEAR:
- case FOOD_APPLE:
- case FOOD_APRICOT:
- case FOOD_CHOKO:
- case FOOD_SNOZZCUMBER:
- case FOOD_RAMBUTAN:
- case FOOD_LYCHEE:
- carnivore_modifier = -200;
- herbivore_modifier = 200;
- break;
- case FOOD_STRAWBERRY:
- carnivore_modifier = -50;
- herbivore_modifier = 50;
- break;
- case FOOD_GRAPE:
- case FOOD_SULTANA:
- carnivore_modifier = -20;
- herbivore_modifier = 20;
- break;
- default:
- carnivore_modifier = 0;
- herbivore_modifier = 0;
- break;
- }
-
- // Finally, modify player's hunger level {dlb}:
- if (carnivore_modifier && how_carnivorous > 0)
- food_value += (carnivore_modifier * how_carnivorous);
-
- if (herbivore_modifier && how_herbivorous > 0)
- food_value += (herbivore_modifier * how_herbivorous);
-
- if (food_value > 0)
- {
- int duration = 1;
-
- if (item_type == FOOD_MEAT_RATION || item_type == FOOD_BREAD_RATION)
- {
- duration = 3;
- }
- else if (item_type == FOOD_AMBROSIA || item_type == FOOD_GRAPE
- || item_type == FOOD_SULTANA)
- {
- duration = 0;
- }
-
- if (you.duration[DUR_NAUSEA])
- {
- // possible only when starving or near starving
- mpr("You force it down, but cannot stomach much of it.");
- food_value /= 2;
- }
+ // possible only when starving or near starving
+ mpr("You force it down, but cannot stomach much of it.");
+ food_value /= 2;
+ }
- // use delay.parm3 to figure out whether to output "finish eating"
- start_delay(DELAY_EAT, duration, 0, item_type, duration);
+ int duration = food_turns(food) - 1;
- lessen_hunger(food_value, true);
+ // use delay.parm3 to figure out whether to output "finish eating"
+ start_delay(DELAY_EAT, duration, 0, food.sub_type, duration);
- if (player_mutation_level(MUT_FOOD_JELLY)
- && x_chance_in_y(food_value, 12000))
- {
- mgen_data mg(MONS_JELLY, BEH_STRICT_NEUTRAL, 0, 0, 0,
- you.pos(), MHITNOT, 0, you.religion);
+ lessen_hunger(food_value, true);
- if (create_monster(mg))
- mprf("A jelly spawns from your body.");
- }
- }
- break;
+ if (player_mutation_level(MUT_FOOD_JELLY)
+ && x_chance_in_y(food_value, 12000))
+ {
+ mgen_data mg(MONS_JELLY, BEH_STRICT_NEUTRAL, 0, 0, 0,
+ you.pos(), MHITNOT, 0, you.religion);
- default:
- break;
+ if (create_monster(mg))
+ mprf("A jelly spawns from your body.");
}
}
diff --git a/crawl-ref/source/format.cc b/crawl-ref/source/format.cc
index 11286649bb..ca0cc95f02 100644
--- a/crawl-ref/source/format.cc
+++ b/crawl-ref/source/format.cc
@@ -6,6 +6,7 @@
#include "format.h"
#include "libutil.h"
#include "showsymb.h"
+#include "lang-fake.h"
#include "unicode.h"
#include "viewchar.h"
@@ -508,6 +509,13 @@ void formatted_string::capitalize()
}
}
+void formatted_string::filter_lang()
+{
+ for (unsigned int i = 0; i < ops.size(); i++)
+ if (ops[i].type == FSOP_TEXT)
+ ::filter_lang(ops[i].text);
+}
+
int count_linebreaks(const formatted_string& fs)
{
std::string::size_type where = 0;
diff --git a/crawl-ref/source/format.h b/crawl-ref/source/format.h
index 8d3dc23d7a..b33c036020 100644
--- a/crawl-ref/source/format.h
+++ b/crawl-ref/source/format.h
@@ -33,6 +33,7 @@ public:
void del_char();
void all_caps();
void capitalize();
+ void filter_lang();
void clear();
bool empty();
diff --git a/crawl-ref/source/fprop.h b/crawl-ref/source/fprop.h
index 7f2c0488e0..62b6f3de5e 100644
--- a/crawl-ref/source/fprop.h
+++ b/crawl-ref/source/fprop.h
@@ -30,6 +30,7 @@ enum feature_property_type
FPROP_BLOOD_WEST = (1 << 16),
FPROP_BLOOD_NORTH = (1 << 17),
FPROP_BLOOD_EAST = FPROP_BLOOD_WEST | FPROP_BLOOD_NORTH,
+ FPROP_OLD_BLOOD = (1 << 18),
};
diff --git a/crawl-ref/source/godabil.cc b/crawl-ref/source/godabil.cc
index 62a8682b65..7183eae812 100644
--- a/crawl-ref/source/godabil.cc
+++ b/crawl-ref/source/godabil.cc
@@ -84,7 +84,8 @@ std::string zin_recite_text(int* trits, size_t len, int prayertype, int step)
// We change it to turn 1, turn 2, turn 3.
// 'trits' && 'len':
- // To have deterministic passages we need to store a random seed. Ours consists of an array of trinary bits.
+ // To have deterministic passages we need to store a random seed.
+ // Ours consists of an array of trinary bits.
// Yes, really.
@@ -213,22 +214,31 @@ std::string zin_recite_text(int* trits, size_t len, int prayertype, int step)
switch (chapter)
{
case 1:
- turn[1] = make_stringf("It was the word of Zin that there would not be %s...", sin[1].c_str());
- turn[2] = make_stringf("...and did the people not suffer until they had %s...", smite[1].c_str());
+ turn[1] = make_stringf("It was the word of Zin that there would not be %s...",
+ sin[1].c_str());
+ turn[2] = make_stringf("...and did the people not suffer until they had %s...",
+ smite[1].c_str());
turn[3] = make_stringf("...the %s, after which all was well?", sinner.c_str());
break;
case 2:
- turn[1] = make_stringf("The voice of Zin, pure and clear, did say that the %s...", sinner.c_str());
- turn[2] = make_stringf("...were not %s! And hearing this, the people rose up...", virtue[0].c_str());
- turn[3] = make_stringf("...and embraced %s, for they feared Zin's wrath.", virtue[1].c_str());
+ turn[1] = make_stringf("The voice of Zin, pure and clear, did say that the %s...",
+ sinner.c_str());
+ turn[2] = make_stringf("...were not %s! And hearing this, the people rose up...",
+ virtue[0].c_str());
+ turn[3] = make_stringf("...and embraced %s, for they feared Zin's wrath.",
+ virtue[1].c_str());
break;
case 3:
- turn[1] = make_stringf("Zin spoke of the doctrine of %s, and...", virtue[1].c_str());
- turn[2] = make_stringf("...saw the %s filled with fear, for they were...", sinner.c_str());
- turn[3] = make_stringf("...%s and knew Zin's wrath would come for them.", sin[0].c_str());
+ turn[1] = make_stringf("Zin spoke of the doctrine of %s, and...",
+ virtue[1].c_str());
+ turn[2] = make_stringf("...saw the %s filled with fear, for they were...",
+ sinner.c_str());
+ turn[3] = make_stringf("...%s and knew Zin's wrath would come for them.",
+ sin[0].c_str());
break;
case 4:
- turn[1] = make_stringf("And so Zin bade the %s to come before...", sinner.c_str());
+ turn[1] = make_stringf("And so Zin bade the %s to come before...",
+ sinner.c_str());
turn[2] = make_stringf("...the altar, that judgement might be passed...");
turn[3] = make_stringf("...upon those who were not %s.", virtue[0].c_str());
break;
@@ -238,63 +248,82 @@ std::string zin_recite_text(int* trits, size_t len, int prayertype, int step)
turn[3] = make_stringf("...of %s, Zin taketh.", sin[1].c_str());
break;
case 6:
- turn[1] = make_stringf("Zin saw the %s of the %s, and...", sin[1].c_str(), sinner.c_str());
+ turn[1] = make_stringf("Zin saw the %s of the %s, and...",
+ sin[1].c_str(), sinner.c_str());
turn[2] = make_stringf("...was displeased, for did the law not say that...");
- turn[3] = make_stringf("...those who did not become %s would be %s?", virtue[0].c_str(), smite[1].c_str());
+ turn[3] = make_stringf("...those who did not become %s would be %s?",
+ virtue[0].c_str(), smite[1].c_str());
break;
case 7:
- turn[1] = make_stringf("Zin said that %s shall be the law of the land, and...", virtue[1].c_str());
- turn[2] = make_stringf("...those who turn to %s will be %s. This was fair...", sin[1].c_str(), smite[1].c_str());
+ turn[1] = make_stringf("Zin said that %s shall be the law of the land, and...",
+ virtue[1].c_str());
+ turn[2] = make_stringf("...those who turn to %s will be %s. This was fair...",
+ sin[1].c_str(), smite[1].c_str());
turn[3] = make_stringf("...and just, and not a voice dissented.");
break;
case 8:
turn[1] = make_stringf("Damned, damned be the %s and...", sinner.c_str());
- turn[2] = make_stringf("...all else who abandon %s! Let them...", virtue[1].c_str());
- turn[3] = make_stringf("...be %s by the jurisprudence of Zin!", smite[1].c_str());
+ turn[2] = make_stringf("...all else who abandon %s! Let them...",
+ virtue[1].c_str());
+ turn[3] = make_stringf("...be %s by the jurisprudence of Zin!",
+ smite[1].c_str());
break;
case 9:
turn[1] = make_stringf("And Zin said to all in attendance, 'Which of ye...");
- turn[2] = make_stringf("...number among the %s? Come before me, that...", sinner.c_str());
- turn[3] = make_stringf("...I may %s you now for your %s!'", smite[0].c_str(), sin[1].c_str());
+ turn[2] = make_stringf("...number among the %s? Come before me, that...",
+ sinner.c_str());
+ turn[3] = make_stringf("...I may %s you now for your %s!'",
+ smite[0].c_str(), sin[1].c_str());
break;
case 10:
turn[1] = make_stringf("Yea, I say unto thee, bring forth...");
turn[2] = make_stringf("...the %s that they may know...", sinner.c_str());
- turn[3] = make_stringf("...the wrath of Zin, and thus be %s!", smite[1].c_str());
+ turn[3] = make_stringf("...the wrath of Zin, and thus be %s!",
+ smite[1].c_str());
break;
case 11:
turn[1] = make_stringf("In a great set of silver scales are weighed the...");
- turn[2] = make_stringf("...souls of the %s, and with their %s...", sinner.c_str(), sin[0].c_str());
+ turn[2] = make_stringf("...souls of the %s, and with their %s...",
+ sinner.c_str(), sin[0].c_str());
turn[3] = make_stringf("...ways, the balance hath tipped against them!");
break;
case 12:
- turn[1] = make_stringf("It is just that the %s shall be %s...", sinner.c_str(), smite[1].c_str());
- turn[2] = make_stringf("...in due time, for %s is what Zin has declared...", virtue[1].c_str());
+ turn[1] = make_stringf("It is just that the %s shall be %s...",
+ sinner.c_str(), smite[1].c_str());
+ turn[2] = make_stringf("...in due time, for %s is what Zin has declared...",
+ virtue[1].c_str());
turn[3] = make_stringf("...the law of the land, and Zin's word is law!");
break;
case 13:
- turn[1] = make_stringf("Thus the people made the covenant of %s with...", virtue[1].c_str());
+ turn[1] = make_stringf("Thus the people made the covenant of %s with...",
+ virtue[1].c_str());
turn[2] = make_stringf("...Zin, and all was good, for they knew that the...");
turn[3] = make_stringf("...%s would trouble them no longer.", sinner.c_str());
break;
case 14:
- turn[1] = make_stringf("What of the %s? %s for their...", sinner.c_str(), uppercase_first(smite[1]).c_str());
- turn[2] = make_stringf("...%s they shall be! Zin will %s them again...", sin[1].c_str(), smite[0].c_str());
+ turn[1] = make_stringf("What of the %s? %s for their...",
+ sinner.c_str(), uppercase_first(smite[1]).c_str());
+ turn[2] = make_stringf("...%s they shall be! Zin will %s them again...",
+ sin[1].c_str(), smite[0].c_str());
turn[3] = make_stringf("...and again, and again!");
break;
case 15:
turn[1] = make_stringf("And lo, the wrath of Zin did find...");
- turn[2] = make_stringf("...them wherever they hid, and the %s...", sinner.c_str());
- turn[3] = make_stringf("...were %s for their %s!", smite[1].c_str(), sin[1].c_str());
+ turn[2] = make_stringf("...them wherever they hid, and the %s...",
+ sinner.c_str());
+ turn[3] = make_stringf("...were %s for their %s!",
+ smite[1].c_str(), sin[1].c_str());
break;
case 16:
- turn[1] = make_stringf("Zin looked out upon the remains of the %s...", sinner.c_str());
+ turn[1] = make_stringf("Zin looked out upon the remains of the %s...",
+ sinner.c_str());
turn[2] = make_stringf("...and declared it good that they had been...");
turn[3] = make_stringf("...%s. And thus justice was done.", smite[1].c_str());
break;
case 17:
turn[1] = make_stringf("The law of Zin demands thee...");
- turn[2] = make_stringf("...be %s, and that the punishment for %s...", virtue[0].c_str(), sin[1].c_str());
+ turn[2] = make_stringf("...be %s, and that the punishment for %s...",
+ virtue[0].c_str(), sin[1].c_str());
turn[3] = make_stringf("...shall be swift and harsh!");
break;
case 18:
@@ -303,48 +332,66 @@ std::string zin_recite_text(int* trits, size_t len, int prayertype, int step)
turn[3] = make_stringf("...they become as damned as the %s.", sinner.c_str());
break;
case 19:
- turn[1] = make_stringf("Only the %s shall be judged worthy, and...", virtue[0].c_str());
- turn[2] = make_stringf("...all the %s will be found wanting. Such is...", sinner.c_str());
+ turn[1] = make_stringf("Only the %s shall be judged worthy, and...",
+ virtue[0].c_str());
+ turn[2] = make_stringf("...all the %s will be found wanting. Such is...",
+ sinner.c_str());
turn[3] = make_stringf("...the word of Zin, and such is the law!");
break;
case 20:
- turn[1] = make_stringf("To those who would swear an oath of %s on my altar...", virtue[1].c_str());
- turn[2] = make_stringf("...I bring ye salvation. To the rest, ye %s...", sinner.c_str());
- turn[3] = make_stringf("...and the %s, the name of Zin shall be thy damnation.", sin[0].c_str());
+ turn[1] = make_stringf("To those who would swear an oath of %s on my altar...",
+ virtue[1].c_str());
+ turn[2] = make_stringf("...I bring ye salvation. To the rest, ye %s...",
+ sinner.c_str());
+ turn[3] = make_stringf("...and the %s, the name of Zin shall be thy damnation.",
+ sin[0].c_str());
break;
case 21:
turn[1] = make_stringf("And Zin decreed that the people would be...");
- turn[2] = make_stringf("...protected from %s in all its forms, and...", sin[1].c_str());
- turn[3] = make_stringf("...preserved in their %s for all the days to come.", virtue[1].c_str());
+ turn[2] = make_stringf("...protected from %s in all its forms, and...",
+ sin[1].c_str());
+ turn[3] = make_stringf("...preserved in their %s for all the days to come.",
+ virtue[1].c_str());
break;
case 22:
turn[1] = make_stringf("For those who would enter Zin's holy bosom...");
- turn[2] = make_stringf("...and live in %s, Zin provideth. Such is...", virtue[1].c_str());
+ turn[2] = make_stringf("...and live in %s, Zin provideth. Such is...",
+ virtue[1].c_str());
turn[3] = make_stringf("...the covenant, and such is the way of things.");
break;
case 23:
- turn[1] = make_stringf("Zin hath not damned the %s, but it is they...", sinner.c_str());
- turn[2] = make_stringf("...that have damned themselves for their %s, for...", sin[1].c_str());
- turn[3] = make_stringf("...did Zin not decree that to be %s was wrong?", sin[0].c_str());
+ turn[1] = make_stringf("Zin hath not damned the %s, but it is they...",
+ sinner.c_str());
+ turn[2] = make_stringf("...that have damned themselves for their %s, for...",
+ sin[1].c_str());
+ turn[3] = make_stringf("...did Zin not decree that to be %s was wrong?",
+ sin[0].c_str());
break;
case 24:
turn[1] = make_stringf("And Zin, furious at their %s, held...", sin[1].c_str());
turn[2] = make_stringf("...aloft a silver sceptre! The %s...", sinner.c_str());
- turn[3] = make_stringf("...were %s, and thus the way of things was maintained.", smite[1].c_str());
+ turn[3] = make_stringf("...were %s, and thus the way of things was maintained.",
+ smite[1].c_str());
break;
case 25:
turn[1] = make_stringf("When the law of the land faltered, Zin rose...");
- turn[2] = make_stringf("...from the silver throne, and the %s were...", sinner.c_str());
- turn[3] = make_stringf("...%s. And it was thus that the law was made good.", smite[1].c_str());
+ turn[2] = make_stringf("...from the silver throne, and the %s were...",
+ sinner.c_str());
+ turn[3] = make_stringf("...%s. And it was thus that the law was made good.",
+ smite[1].c_str());
break;
case 26:
turn[1] = make_stringf("Zin descended from on high in a silver chariot...");
- turn[2] = make_stringf("...to %s the %s for their...", smite[0].c_str(), sinner.c_str());
- turn[3] = make_stringf("...%s, and thus judgement was rendered.", sin[1].c_str());
+ turn[2] = make_stringf("...to %s the %s for their...",
+ smite[0].c_str(), sinner.c_str());
+ turn[3] = make_stringf("...%s, and thus judgement was rendered.",
+ sin[1].c_str());
break;
case 27:
- turn[1] = make_stringf("The %s stood before Zin, and in that instant...", sinner.c_str());
- turn[2] = make_stringf("...they knew they would be found guilty of %s...", sin[1].c_str());
+ turn[1] = make_stringf("The %s stood before Zin, and in that instant...",
+ sinner.c_str());
+ turn[2] = make_stringf("...they knew they would be found guilty of %s...",
+ sin[1].c_str());
turn[3] = make_stringf("...for that is the word of Zin, and Zin's word is law.");
break;
}
@@ -2203,8 +2250,7 @@ bool fedhas_sunlight()
processed_count++;
}
else if (one_chance_in(100)
- && ftype >= DNGN_FLOOR_MIN
- && ftype <= DNGN_FLOOR_MAX
+ && ftype == DNGN_FLOOR
&& orig_type == DNGN_SHALLOW_WATER)
{
// Create a plant.
@@ -2607,8 +2653,7 @@ int fedhas_rain(const coord_def &target)
// x/192.
if (x_chance_in_y(5, 192)
&& !actor_at(*rad)
- && ftype >= DNGN_FLOOR_MIN
- && ftype <= DNGN_FLOOR_MAX)
+ && ftype == DNGN_FLOOR)
{
if (create_monster(mgen_data(
coinflip() ? MONS_PLANT : MONS_FUNGUS,
@@ -2631,7 +2676,7 @@ int fedhas_rain(const coord_def &target)
}
// Turn regular floor squares only into shallow water.
- if (ftype >= DNGN_FLOOR_MIN && ftype <= DNGN_FLOOR_MAX)
+ if (ftype == DNGN_FLOOR)
{
dungeon_terrain_changed(*rad, DNGN_SHALLOW_WATER);
diff --git a/crawl-ref/source/goditem.cc b/crawl-ref/source/goditem.cc
index cccf498bf8..c3573876fd 100644
--- a/crawl-ref/source/goditem.cc
+++ b/crawl-ref/source/goditem.cc
@@ -22,6 +22,31 @@
#include "spl-cast.h"
#include "spl-util.h"
+static bool _is_bookrod_type(const item_def& item,
+ bool (*suitable)(spell_type spell))
+{
+ if (!item_is_spellbook(item) && !item_is_rod(item))
+ return false;
+
+ int total = 0;
+ int total_liked = 0;
+
+ for (int i = 0; i < SPELLBOOK_SIZE; ++i)
+ {
+ spell_type spell = which_spell_in_book(item, i);
+ if (spell == SPELL_NO_SPELL)
+ continue;
+
+ total++;
+ if (suitable(spell))
+ total_liked++;
+ }
+
+ // If at least half of the available spells are suitable, the whole
+ // spellbook or rod is, too.
+ return (total_liked >= (total / 2) + 1);
+}
+
bool is_holy_item(const item_def& item)
{
bool retval = false;
@@ -76,10 +101,8 @@ bool is_unholy_item(const item_def& item)
retval = (item.sub_type == SCR_SUMMONING);
break;
case OBJ_BOOKS:
- retval = is_unholy_spellbook(item);
- break;
case OBJ_STAVES:
- retval = is_unholy_rod(item);
+ retval = _is_bookrod_type(item, is_unholy_spell);
break;
case OBJ_MISCELLANY:
retval = (item.sub_type == MISC_BOTTLED_EFREET);
@@ -145,10 +168,8 @@ bool is_corpse_violating_item(const item_def& item)
retval = (item.sub_type == SCR_SUMMONING);
break;
case OBJ_BOOKS:
- retval = (is_corpse_violating_spellbook(item));
- break;
case OBJ_STAVES:
- retval = (is_corpse_violating_rod(item));
+ retval = _is_bookrod_type(item, is_corpse_violating_spell);
break;
default:
break;
@@ -189,11 +210,11 @@ bool is_evil_item(const item_def& item)
case OBJ_SCROLLS:
retval = (item.sub_type == SCR_TORMENT);
break;
- case OBJ_BOOKS:
- retval = is_evil_spellbook(item);
- break;
case OBJ_STAVES:
- retval = (item.sub_type == STAFF_DEATH || is_evil_rod(item));
+ if (item.sub_type == STAFF_DEATH)
+ return true;
+ case OBJ_BOOKS:
+ retval = _is_bookrod_type(item, is_evil_spell);
break;
case OBJ_MISCELLANY:
retval = (item.sub_type == MISC_LANTERN_OF_SHADOWS);
@@ -220,10 +241,8 @@ bool is_unclean_item(const item_def& item)
switch (item.base_type)
{
case OBJ_BOOKS:
- retval = is_unclean_spellbook(item);
- break;
case OBJ_STAVES:
- retval = is_unclean_rod(item);
+ retval = _is_bookrod_type(item, is_unclean_spell);
break;
default:
break;
@@ -268,10 +287,8 @@ bool is_chaotic_item(const item_def& item)
retval = (item.sub_type == SCR_SUMMONING);
break;
case OBJ_BOOKS:
- retval = is_chaotic_spellbook(item);
- break;
case OBJ_STAVES:
- retval = is_chaotic_rod(item);
+ retval = _is_bookrod_type(item, is_chaotic_spell);
break;
default:
break;
@@ -286,7 +303,7 @@ bool is_chaotic_item(const item_def& item)
return (retval);
}
-bool is_potentially_hasty_item(const item_def& item)
+static bool _is_potentially_hasty_item(const item_def& item)
{
switch (item.base_type)
{
@@ -347,10 +364,8 @@ bool is_hasty_item(const item_def& item)
|| item.sub_type == POT_BERSERK_RAGE);
break;
case OBJ_BOOKS:
- retval = is_hasty_spellbook(item);
- break;
case OBJ_STAVES:
- retval = is_hasty_rod(item);
+ retval = _is_bookrod_type(item, is_hasty_spell);
break;
default:
break;
@@ -395,175 +410,51 @@ bool is_poisoned_item(const item_def& item)
return (false);
}
-bool is_evil_discipline(int discipline)
+bool is_unholy_spell(spell_type spell)
{
- return (discipline & SPTYP_NECROMANCY);
-}
-
-bool is_unholy_spell(spell_type spell, god_type god)
-{
- UNUSED(god);
-
unsigned int flags = get_spell_flags(spell);
return (flags & SPFLAG_UNHOLY);
}
-bool is_corpse_violating_spell(spell_type spell, god_type god)
+bool is_corpse_violating_spell(spell_type spell)
{
- UNUSED(god);
-
unsigned int flags = get_spell_flags(spell);
return (flags & SPFLAG_CORPSE_VIOLATING);
}
-bool is_evil_spell(spell_type spell, god_type god)
+bool is_evil_spell(spell_type spell)
{
- UNUSED(god);
-
unsigned int disciplines = get_spell_disciplines(spell);
- return (is_evil_discipline(disciplines));
+ return (disciplines & SPTYP_NECROMANCY);
}
-bool is_unclean_spell(spell_type spell, god_type god)
+bool is_unclean_spell(spell_type spell)
{
- UNUSED(god);
-
unsigned int flags = get_spell_flags(spell);
return (flags & SPFLAG_UNCLEAN);
}
-bool is_chaotic_spell(spell_type spell, god_type god)
+bool is_chaotic_spell(spell_type spell)
{
- UNUSED(god);
-
unsigned int flags = get_spell_flags(spell);
return (flags & SPFLAG_CHAOTIC);
}
-bool is_hasty_spell(spell_type spell, god_type god)
+bool is_hasty_spell(spell_type spell)
{
- UNUSED(god);
-
unsigned int flags = get_spell_flags(spell);
return (flags & SPFLAG_HASTY);
}
-// The default suitable() function for is_spellbook_type().
-bool is_any_spell(spell_type spell, god_type god)
+static bool _your_god_hates_spell(spell_type spell)
{
- UNUSED(god);
-
- return (true);
-}
-
-// If book_or_rod is false, only look at actual spellbooks. Otherwise,
-// only look at rods.
-bool is_spellbook_type(const item_def& item, bool book_or_rod,
- bool (*suitable)(spell_type spell, god_type god),
- god_type god)
-{
- const bool is_spellbook = item_is_spellbook(item);
- const bool is_rod = item_is_rod(item);
-
- if (!is_spellbook && !is_rod)
- return (false);
-
- if (!book_or_rod && is_rod)
- return (false);
-
- int total = 0;
- int total_liked = 0;
-
- for (int i = 0; i < SPELLBOOK_SIZE; ++i)
- {
- spell_type spell = which_spell_in_book(item, i);
- if (spell == SPELL_NO_SPELL)
- continue;
-
- total++;
- if (suitable(spell, god))
- total_liked++;
- }
-
- // If at least half of the available spells are suitable, the whole
- // spellbook or rod is, too.
- return (total_liked >= (total / 2) + 1);
-}
-
-bool is_unholy_spellbook(const item_def& item)
-{
- return (is_spellbook_type(item, false, is_unholy_spell));
-}
-
-bool is_evil_spellbook(const item_def& item)
-{
- return (is_spellbook_type(item, false, is_evil_spell));
-}
-
-bool is_unclean_spellbook(const item_def& item)
-{
- return (is_spellbook_type(item, false, is_unclean_spell));
-}
-
-bool is_chaotic_spellbook(const item_def& item)
-{
- return (is_spellbook_type(item, false, is_chaotic_spell));
-}
-
-bool is_hasty_spellbook(const item_def& item)
-{
- return (is_spellbook_type(item, false, is_hasty_spell));
-}
-
-bool is_corpse_violating_spellbook(const item_def & item)
-{
- return (is_spellbook_type(item, false, is_corpse_violating_spell));
-}
-
-static bool _god_hates_spellbook(const item_def& item)
-{
- return (is_spellbook_type(item, false, god_hates_spell));
-}
-
-bool is_unholy_rod(const item_def& item)
-{
- return (is_spellbook_type(item, true, is_unholy_spell));
-}
-
-bool is_evil_rod(const item_def& item)
-{
- return (is_spellbook_type(item, true, is_evil_spell));
-}
-
-bool is_unclean_rod(const item_def& item)
-{
- return (is_spellbook_type(item, true, is_unclean_spell));
-}
-
-bool is_chaotic_rod(const item_def& item)
-{
- return (is_spellbook_type(item, true, is_chaotic_spell));
-}
-
-bool is_hasty_rod(const item_def& item)
-{
- return (is_spellbook_type(item, true, is_hasty_spell));
-}
-
-bool is_corpse_violating_rod(const item_def & item)
-{
- return (is_spellbook_type(item, true, is_corpse_violating_spell));
-}
-
-static bool _god_hates_rod(const item_def& item)
-{
- return (is_spellbook_type(item, true, god_hates_spell));
+ return god_hates_spell(spell, you.religion);
}
conduct_type good_god_hates_item_handling(const item_def &item)
@@ -616,6 +507,9 @@ conduct_type god_hates_item_handling(const item_def &item)
case GOD_TROG:
if (item_is_spellbook(item))
return (DID_SPELL_MEMORISE);
+ // Only Trog cares about spellsbooks vs rods.
+ if (item_is_rod(item))
+ return (DID_NOTHING);
break;
case GOD_FEDHAS:
@@ -625,7 +519,7 @@ conduct_type god_hates_item_handling(const item_def &item)
case GOD_CHEIBRIADOS:
if (item_type_known(item)
- && (is_potentially_hasty_item(item) || is_hasty_item(item)))
+ && (_is_potentially_hasty_item(item) || is_hasty_item(item)))
{
return (DID_HASTY);
}
@@ -647,8 +541,7 @@ conduct_type god_hates_item_handling(const item_def &item)
return (DID_NECROMANCY);
}
- if (item_type_known(item)
- && (_god_hates_spellbook(item) || _god_hates_rod(item)))
+ if (item_type_known(item) && _is_bookrod_type(item, _your_god_hates_spell))
{
return (NUM_CONDUCTS); // FIXME: Get the specific reason, if it
} // will ever be needed for spellbooks.
@@ -716,7 +609,7 @@ bool god_dislikes_spell_discipline(int discipline, god_type god)
{
ASSERT(discipline < (1 << (SPTYP_LAST_EXPONENT + 1)));
- if (is_good_god(god) && is_evil_discipline(discipline))
+ if (is_good_god(god) && (discipline & SPTYP_NECROMANCY))
return (true);
switch (god)
diff --git a/crawl-ref/source/goditem.h b/crawl-ref/source/goditem.h
index 5b8dff9751..bf4e6fecf4 100644
--- a/crawl-ref/source/goditem.h
+++ b/crawl-ref/source/goditem.h
@@ -14,33 +14,14 @@ bool is_corpse_violating_item(const item_def& item);
bool is_evil_item(const item_def& item);
bool is_unclean_item(const item_def& item);
bool is_chaotic_item(const item_def& item);
-bool is_potentially_hasty_item(const item_def& item);
bool is_hasty_item(const item_def& item);
bool is_poisoned_item(const item_def& item);
-bool is_evil_discipline(int discipline);
-bool is_unholy_spell(spell_type spell, god_type god = GOD_NO_GOD);
-bool is_corpse_violating_spell(spell_type spell, god_type = GOD_NO_GOD);
-bool is_evil_spell(spell_type spell, god_type god = GOD_NO_GOD);
-bool is_unclean_spell(spell_type spell, god_type god = GOD_NO_GOD);
-bool is_chaotic_spell(spell_type spell, god_type god = GOD_NO_GOD);
-bool is_hasty_spell(spell_type spell, god_type god = GOD_NO_GOD);
-bool is_any_spell(spell_type spell, god_type god = GOD_NO_GOD);
-bool is_spellbook_type(const item_def& item, bool book_or_rod,
- bool (*suitable)(spell_type spell, god_type god) =
- is_any_spell,
- god_type god = you.religion);
-bool is_unholy_spellbook(const item_def& item);
-bool is_evil_spellbook(const item_def& item);
-bool is_unclean_spellbook(const item_def& item);
-bool is_chaotic_spellbook(const item_def& item);
-bool is_hasty_spellbook(const item_def& item);
-bool is_corpse_violating_spellbook(const item_def & item);
-bool is_unholy_rod(const item_def& item);
-bool is_evil_rod(const item_def& item);
-bool is_unclean_rod(const item_def& item);
-bool is_chaotic_rod(const item_def& item);
-bool is_hasty_rod(const item_def& item);
-bool is_corpse_violating_rod(const item_def & item);
+bool is_unholy_spell(spell_type spell);
+bool is_corpse_violating_spell(spell_type spell);
+bool is_evil_spell(spell_type spell);
+bool is_unclean_spell(spell_type spell);
+bool is_chaotic_spell(spell_type spell);
+bool is_hasty_spell(spell_type spell);
conduct_type good_god_hates_item_handling(const item_def &item);
conduct_type god_hates_item_handling(const item_def &item);
diff --git a/crawl-ref/source/godprayer.cc b/crawl-ref/source/godprayer.cc
index 5d4801e69f..b6a0c73b62 100644
--- a/crawl-ref/source/godprayer.cc
+++ b/crawl-ref/source/godprayer.cc
@@ -624,8 +624,10 @@ static piety_gain_t _sacrifice_one_item_noncount(const item_def& item,
const int shop_value = item_value(item, true) / item.quantity;
// Since the god is taking the items as a sacrifice, they must have at
// least minimal value, otherwise they wouldn't be taken.
- const int value = (item.base_type == OBJ_CORPSES ? 50 :
- (is_worthless_consumable(item) ? 1 : shop_value));
+ const int value = (item.base_type == OBJ_CORPSES ?
+ 50 * stepdown_value(std::max(1,
+ get_max_corpse_chunks(item.mon_type)), 4, 4, 12, 12) :
+ (is_worthless_consumable(item) ? 1 : shop_value));
#if defined(DEBUG_DIAGNOSTICS) || defined(DEBUG_SACRIFICE)
mprf(MSGCH_DIAGNOSTICS, "Sacrifice item value: %d", value);
diff --git a/crawl-ref/source/godwrath.cc b/crawl-ref/source/godwrath.cc
index 2f22082485..3372c7f86c 100644
--- a/crawl-ref/source/godwrath.cc
+++ b/crawl-ref/source/godwrath.cc
@@ -849,7 +849,6 @@ static bool _sif_muna_retribution()
// a duration of one round, thus potentially exposing
// the player to real danger.
antimagic();
- mpr("Your magical effects suddenly unravel.", MSGCH_WARN);
break;
}
diff --git a/crawl-ref/source/hints.cc b/crawl-ref/source/hints.cc
index 5dd25acfbe..4d41511c74 100644
--- a/crawl-ref/source/hints.cc
+++ b/crawl-ref/source/hints.cc
@@ -4600,6 +4600,7 @@ static void _hints_describe_cloud(int x, int y)
case CLOUD_PURPLE_SMOKE:
case CLOUD_MIST:
case CLOUD_MAGIC_TRAIL:
+ case CLOUD_DUST_TRAIL:
ostr << "harmless. ";
break;
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index 7ffe2d096f..1e075adb31 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -880,9 +880,8 @@ void game_options::reset_options()
#ifdef WIZARD
fsim_rounds = 4000L;
- fsim_mons = "worm";
- fsim_str = fsim_int = fsim_dex = -1;
- fsim_xl = -1;
+ fsim_mons = "";
+ fsim_scale.clear();
fsim_kit.clear();
#endif
@@ -1024,7 +1023,9 @@ void game_options::reset_options()
stat_colour.clear();
stat_colour.push_back(std::pair<int, int>(3, RED));
enemy_hp_colour.clear();
- enemy_hp_colour.push_back(GREEN); // I think these defaults are pretty ugly but apparently OS X has problems with lighter colours
+ // I think these defaults are pretty ugly but apparently OS X has problems
+ // with lighter colours
+ enemy_hp_colour.push_back(GREEN);
enemy_hp_colour.push_back(GREEN);
enemy_hp_colour.push_back(BROWN);
enemy_hp_colour.push_back(BROWN);
@@ -2197,6 +2198,16 @@ void game_options::read_option_line(const std::string &str, bool runscript)
lang = "de";
else if (field == "fr" || field == "french" || field == "français")
lang = "fr";
+ else if (field == "dwarven" || field == "dwarf")
+ lang = "dwarven";
+ else if (field == "jäger" || field == "jägerkin" || field == "jager" || field == "jagerkin")
+ lang = "jägerkin";
+ else if (field == "lisp" || field == "lithp")
+ lang = "lisp";
+ else if (field == "wide" || field == "doublewidth" || field == "fullwidth")
+ lang = "wide";
+ else if (field == "en" || field == "english")
+ lang = 0;
else
{
report_error(make_stringf("No translations for language: %s\n",
@@ -2800,6 +2811,10 @@ void game_options::read_option_line(const std::string &str, bool runscript)
}
else BOOL_OPTION(pickup_thrown);
#ifdef WIZARD
+ else if (key == "fsim_mode")
+ fsim_mode = field;
+ else if (key == "fsim_scale")
+ append_vector(fsim_scale, split_string(",", field));
else if (key == "fsim_kit")
append_vector(fsim_kit, split_string(",", field));
else if (key == "fsim_rounds")
@@ -2812,14 +2827,6 @@ void game_options::read_option_line(const std::string &str, bool runscript)
}
else if (key == "fsim_mons")
fsim_mons = field;
- else if (key == "fsim_str")
- fsim_str = atoi(field.c_str());
- else if (key == "fsim_int")
- fsim_int = atoi(field.c_str());
- else if (key == "fsim_dex")
- fsim_dex = atoi(field.c_str());
- else if (key == "fsim_xl")
- fsim_xl = atoi(field.c_str());
#endif // WIZARD
else if (key == "sort_menus")
{
diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc
index 10cd3bf9e3..e95f3a6294 100644
--- a/crawl-ref/source/invent.cc
+++ b/crawl-ref/source/invent.cc
@@ -950,36 +950,6 @@ bool in_inventory(const item_def &i)
return i.pos.x == -1 && i.pos.y == -1;
}
-unsigned char get_invent(int invent_type)
-{
- unsigned char select;
- int flags = MF_SINGLESELECT;
- if (you.dead || crawl_state.updating_scores)
- flags |= MF_EASY_EXIT;
-
- while (true)
- {
- select = invent_select(NULL, MT_INVLIST, invent_type, -1, flags);
-
- if (isaalpha(select))
- {
- const int invidx = letter_to_index(select);
- if (you.inv[invidx].defined())
- {
- if (!describe_item(you.inv[invidx], true))
- break;
- }
- }
- else
- break;
- }
-
- if (!crawl_state.doing_prev_cmd_again)
- redraw_screen();
-
- return select;
-}
-
std::string item_class_name(int type, bool terse)
{
if (terse)
@@ -1225,16 +1195,18 @@ bool any_items_to_select(int selector, bool msg, int excluded_slot)
return (false);
}
-unsigned char invent_select(const char *title,
- menu_type type,
- int item_selector,
- int excluded_slot,
- int flags,
- invtitle_annotator titlefn,
- std::vector<SelItem> *items,
- std::vector<text_pattern> *filter,
- Menu::selitem_tfn selitemfn,
- const std::vector<SelItem> *pre_select)
+// Use title = NULL for stock Inventory title
+// type = MT_DROP allows the multidrop toggle
+static unsigned char _invent_select(const char *title = NULL,
+ menu_type type = MT_INVLIST,
+ int item_selector = OSEL_ANY,
+ int excluded_slot = -1,
+ int flags = MF_NOSELECT,
+ invtitle_annotator titlefn = NULL,
+ std::vector<SelItem> *items = NULL,
+ std::vector<text_pattern> *filter = NULL,
+ Menu::selitem_tfn selitemfn = NULL,
+ const std::vector<SelItem> *pre_select = NULL)
{
InvMenu menu(flags | MF_ALLOW_FORMATTING);
@@ -1258,6 +1230,36 @@ unsigned char invent_select(const char *title,
return (menu.getkey());
}
+unsigned char get_invent(int invent_type)
+{
+ unsigned char select;
+ int flags = MF_SINGLESELECT;
+ if (you.dead || crawl_state.updating_scores)
+ flags |= MF_EASY_EXIT;
+
+ while (true)
+ {
+ select = _invent_select(NULL, MT_INVLIST, invent_type, -1, flags);
+
+ if (isaalpha(select))
+ {
+ const int invidx = letter_to_index(select);
+ if (you.inv[invidx].defined())
+ {
+ if (!describe_item(you.inv[invidx], true))
+ break;
+ }
+ }
+ else
+ break;
+ }
+
+ if (!crawl_state.doing_prev_cmd_again)
+ redraw_screen();
+
+ return select;
+}
+
void browse_inventory()
{
get_invent(OSEL_ANY);
@@ -1363,7 +1365,7 @@ std::vector<SelItem> prompt_invent_items(
MF_MULTISELECT | MF_ALLOW_FILTER;
// The "view inventory listing" mode.
- const int ch = invent_select(prompt,
+ const int ch = _invent_select(prompt,
mtype,
keyin == '*' ? OSEL_ANY : type_expect,
-1,
@@ -1808,7 +1810,7 @@ int prompt_invent_item(const char *prompt,
{
// The "view inventory listing" mode.
std::vector< SelItem > items;
- keyin = invent_select(
+ keyin = _invent_select(
prompt,
mtype,
keyin == '*' ? OSEL_ANY : type_expect,
diff --git a/crawl-ref/source/invent.h b/crawl-ref/source/invent.h
index 09d68171d2..47340ceee3 100644
--- a/crawl-ref/source/invent.h
+++ b/crawl-ref/source/invent.h
@@ -206,21 +206,6 @@ std::vector<SelItem> prompt_invent_items(
Menu::selitem_tfn fn = NULL,
const std::vector<SelItem> *pre_select = NULL);
-
-unsigned char invent_select(
- // Use NULL for stock Inventory title
- const char *title = NULL,
- // MT_DROP allows the multidrop toggle
- menu_type type = MT_INVLIST,
- int item_selector = OSEL_ANY,
- int excluded_slot = -1,
- int menu_select_flags = MF_NOSELECT,
- invtitle_annotator titlefn = NULL,
- std::vector<SelItem> *sels = NULL,
- std::vector<text_pattern> *filter = NULL,
- Menu::selitem_tfn fn = NULL,
- const std::vector<SelItem> *pre_select = NULL);
-
void browse_inventory();
unsigned char get_invent(int invent_type);
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index 10c9bfdd56..4e756c6b63 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -1263,6 +1263,11 @@ static bool _fire_validate_item(int slot, std::string &err)
err = "You are wearing that object!";
return (false);
}
+ else if (you.inv[slot].base_type == OBJ_ORBS)
+ {
+ err = "You don't feel like leaving the orb behind!";
+ return (false);
+ }
return (true);
}
@@ -3259,7 +3264,10 @@ static int _prompt_ring_to_remove_octopode(int new_ring)
const item_def *rings[8];
char slots[8];
- for (int i = 0; i < 8; i++)
+ const int num_rings = (form_keeps_mutations() || you.form == TRAN_SPIDER
+ ? 8 : 2);
+
+ for (int i = 0; i < num_rings; i++)
{
rings[i] = you.slot_item((equipment_type)(EQ_RING_ONE + i), true);
ASSERT(rings[i]);
@@ -3270,12 +3278,12 @@ static int _prompt_ring_to_remove_octopode(int new_ring)
// mprf("Wearing %s.", you.inv[new_ring].name(DESC_A).c_str());
mprf(MSGCH_PROMPT,
- "You're wearing eight rings. Remove which one?");
+ "You're wearing all the rings you can. Remove which one?");
//I think it looks better without the letters.
// (%c/%c/%c/%c/%c/%c/%c/%c/Esc)",
// one_slot, two_slot, three_slot, four_slot, five_slot, six_slot, seven_slot, eight_slot);
- for (int i = 0; i < 8; i++)
+ for (int i = 0; i < num_rings; i++)
mprf_nocap("%s", rings[i]->name(DESC_INVENTORY).c_str());
flush_prev_message();
@@ -3289,7 +3297,7 @@ static int _prompt_ring_to_remove_octopode(int new_ring)
do
{
c = getchm();
- for (int i = 0; i < 8; i++)
+ for (int i = 0; i < num_rings; i++)
if (c == slots[i])
{
eqslot = EQ_RING_ONE + i;
@@ -3456,6 +3464,12 @@ static bool _swap_rings(int ring_slot)
const item_def* lring = you.slot_item(EQ_LEFT_RING, true);
const item_def* rring = you.slot_item(EQ_RIGHT_RING, true);
+ // If ring slots were melded, we should have been prevented from
+ // putting on the ring at all. If it becomes possible for just
+ // one ring slot to be melded, the subsequent code will need to
+ // be revisited, so prevent that, too.
+ ASSERT(!you.melded[EQ_LEFT_RING] && !you.melded[EQ_RIGHT_RING]);
+
if (lring->cursed() && rring->cursed())
{
mprf("You're already wearing two cursed rings!");
@@ -3509,42 +3523,51 @@ static bool _swap_rings_octopode(int ring_slot)
int array = 0;
int unwanted = 0;
int cursed = 0;
- int uncursed = 0;
+ int melded = 0; // Both melded rings and unavailable slots.
+ int available = 0;
for (int slots = EQ_RING_ONE;
slots < NUM_EQUIP && array < 8;
++slots, ++array)
{
- if (ring[array] != NULL)
+ if (!you_tran_can_wear(slots) || you.melded[slots])
+ melded++;
+ else if (ring[array] != NULL)
{
if (ring[array]->cursed())
- {
cursed++;
- continue;
- }
else
{
- uncursed++;
+ available++;
unwanted = you.equip[slots];
}
}
}
// We can't put a ring on, because we're wearing 8 cursed ones.
- if (cursed == 8)
+ if (melded == 8)
+ {
+ // Shouldn't happen, because hogs and bats can't put on jewellery at
+ // all and thus won't get this far.
+ mpr("You can't wear that in your present form.");
+ return (false);
+ }
+ else if (available == 0)
{
- mpr("You're already wearing eight cursed rings! Isn't that enough for you?");
+ mprf("You're already wearing %s cursed rings!%s",
+ number_in_words(cursed).c_str(),
+ (cursed == 8 ? " Isn't that enough for you?" : ""));
return (false);
}
- // The simple case - only one uncursed ring.
- else if (uncursed == 1)
+ // The simple case - only one available ring.
+ else if (available == 1)
{
if (!remove_ring(unwanted, false))
return (false);
}
// We can't put a ring on without swapping - because we found
- // multiple uncursed rings.
- else if (uncursed > 1)
+ // multiple available rings.
+ else if (available > 1)
{
unwanted = _prompt_ring_to_remove_octopode(ring_slot);
if (!remove_ring(unwanted, false))
@@ -3601,15 +3624,27 @@ static bool _puton_item(int item_slot)
{
blinged_octopode = true;
for (int eq = EQ_RING_ONE; eq <= EQ_RING_EIGHT; eq++)
+ {
+ // Skip unavailable slots.
+ if (!you_tran_can_wear(eq))
+ continue;
+
if (!you.slot_item((equipment_type)eq, true))
{
blinged_octopode = false;
break;
}
+ }
}
if (!is_amulet) // i.e. it's a ring
{
+ if (!you_tran_can_wear(item))
+ {
+ mpr("You can't wear that in your present form.");
+ return (false);
+ }
+
const item_def* gloves = you.slot_item(EQ_GLOVES, false);
// Cursed gloves cannot be removed.
if (gloves && gloves->cursed())
@@ -3657,6 +3692,10 @@ static bool _puton_item(int item_slot)
for (hand_used = EQ_RING_ONE; hand_used <= EQ_RING_EIGHT;
hand_used = (equipment_type)(hand_used + 1))
{
+ // Skip unavailble slots.
+ if (!you_tran_can_wear(hand_used))
+ continue;
+
if (!you.slot_item(hand_used, true))
break;
}
@@ -3688,12 +3727,6 @@ static bool _puton_item(int item_slot)
bool puton_ring(int slot)
{
- if (!player_can_handle_equipment())
- {
- mpr("You can't put on anything in your present form.");
- return (false);
- }
-
int item_slot;
if (inv_count() < 1)
@@ -3725,15 +3758,10 @@ bool puton_ring(int slot)
bool remove_ring(int slot, bool announce)
{
- if (!player_can_handle_equipment())
- {
- mpr("You can't wear or remove anything in your present form.");
- return (false);
- }
-
equipment_type hand_used = EQ_NONE;
int ring_wear_2;
bool has_jewellery = false;
+ bool has_melded = false;
const equipment_type first = you.species == SP_OCTOPODE ? EQ_AMULET
: EQ_LEFT_RING;
const equipment_type last = you.species == SP_OCTOPODE ? EQ_RING_EIGHT
@@ -3753,11 +3781,17 @@ bool remove_ring(int slot, bool announce)
has_jewellery = true;
}
+ else if (you.melded[eq])
+ has_melded = true;
}
if (!has_jewellery)
{
- mpr("You aren't wearing any rings or amulets.");
+ if (has_melded)
+ mpr("You aren't wearing any unmelded rings or amulets.");
+ else
+ mpr("You aren't wearing any rings or amulets.");
+
return (false);
}
@@ -3886,18 +3920,12 @@ static bool _dont_use_invis()
void zap_wand(int slot)
{
- if (you.species == SP_FELID)
+ if (you.species == SP_FELID || !player_can_handle_equipment())
{
mpr("You have no means to grasp a wand firmly enough.");
return;
}
- if (!player_can_handle_equipment())
- {
- canned_msg(MSG_PRESENT_FORM);
- return;
- }
-
bolt beam;
dist zap_wand;
int item_slot;
@@ -4205,7 +4233,7 @@ void drink(int slot)
return;
}
- if (!player_can_handle_equipment())
+ if (you.form == TRAN_BAT)
{
canned_msg(MSG_PRESENT_FORM);
_vampire_corpse_help();
@@ -4522,14 +4550,12 @@ static bool _vorpalise_weapon(bool already_known)
case SPWPN_CHAOS:
mprf("%s erupts in a glittering mayhem of all colours.", itname.c_str());
- success = !one_chance_in(3); // You mean, you wanted this... guaranteed?
// need to affix it immediately, otherwise transformation will break it
- if (success)
- you.duration[DUR_WEAPON_BRAND] = 0;
+ you.duration[DUR_WEAPON_BRAND] = 0;
xom_is_stimulated(200);
// but the eruption _is_ guaranteed. What it will do is not.
_explosion(you.pos(), &you, BEAM_CHAOS, "chaos eruption", "chaos affixation");
- switch (random2(success ? 2 : 4))
+ switch (random2(coinflip() ? 2 : 4))
{
case 3:
if (transform(50, coinflip() ? TRAN_PIG :
@@ -4620,7 +4646,7 @@ bool enchant_weapon(item_def &wpn, int acc, int dam, const char *colour)
|| (wpn.base_type == OBJ_WEAPONS
&& wpn.sub_type == WPN_BLOWGUN))
{
- acc = std::max(acc, dam);
+ acc = acc + dam;
dam = 0;
}
@@ -4994,12 +5020,6 @@ void read_scroll(int slot)
return;
}
- if (!player_can_handle_equipment())
- {
- canned_msg(MSG_PRESENT_FORM);
- return;
- }
-
if (you.confused())
{
mpr("You're too confused.");
@@ -5132,7 +5152,7 @@ void read_scroll(int slot)
// mpr("You stumble in your attempt to read the scroll. Nothing happens!");
// mpr("Your reading takes too long for the scroll to take effect.");
// mpr("Your low mental capacity makes reading really difficult. You give up!");
- mpr("You try to decipher the scroll, but fail in the attempt.");
+ mpr("You almost manage to decipher the scroll, but fail in this attempt.");
return;
}
@@ -5481,7 +5501,7 @@ bool wearing_slot(int inv_slot)
bool item_blocks_teleport(bool calc_unid, bool permit_id)
{
- return (scan_artefacts(ARTP_PREVENT_TELEPORTATION, calc_unid)
+ return (player_effect_notele(calc_unid)
|| stasis_blocks_effect(calc_unid, permit_id, NULL)
|| crawl_state.game_is_zotdef() && orb_haloed(you.pos()));
}
@@ -5491,7 +5511,7 @@ bool stasis_blocks_effect(bool calc_unid,
const char *msg, int noise,
const char *silenced_msg)
{
- if (wearing_amulet(AMU_STASIS, calc_unid))
+ if (player_effect_stasis(calc_unid))
{
item_def *amulet = you.slot_item(EQ_AMULET, false);
diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc
index 84475e5413..1b824324ae 100644
--- a/crawl-ref/source/itemname.cc
+++ b/crawl-ref/source/itemname.cc
@@ -216,36 +216,27 @@ std::string item_def::name(description_level_type descrip,
break;
case EQ_LEFT_RING:
case EQ_RIGHT_RING:
+ case EQ_RING_ONE:
+ case EQ_RING_TWO:
buff << " (";
- buff << (eq == EQ_LEFT_RING ? "left" : "right");
+ buff << ((eq == EQ_LEFT_RING || eq == EQ_RING_ONE)
+ ? "left" : "right");
buff << " ";
buff << you.hand_name(false);
buff << ")";
break;
case EQ_AMULET:
- if (you.species == SP_OCTOPODE)
+ if (you.species == SP_OCTOPODE && form_keeps_mutations())
buff << " (around mantle)";
else
buff << " (around neck)";
break;
- case EQ_RING_ONE:
- case EQ_RING_TWO:
case EQ_RING_THREE:
case EQ_RING_FOUR:
- if (you.form == TRAN_SPIDER)
- {
- buff << " (on front leg)";
- break;
- }
case EQ_RING_FIVE:
case EQ_RING_SIX:
case EQ_RING_SEVEN:
case EQ_RING_EIGHT:
- if (you.form == TRAN_SPIDER)
- {
- buff << " (on hind leg)";
- break;
- }
buff << " (on tentacle)";
break;
default:
@@ -2704,8 +2695,10 @@ bool is_bad_item(const item_def &item, bool temp)
switch (item.sub_type)
{
case SCR_CURSE_ARMOUR:
- case SCR_CURSE_JEWELLERY:
case SCR_CURSE_WEAPON:
+ if (you.species == SP_FELID)
+ return false;
+ case SCR_CURSE_JEWELLERY:
return (you.religion != GOD_ASHENZARI);
case SCR_SUMMONING:
// Summoning will always produce hostile monsters if you
diff --git a/crawl-ref/source/itemprop-enum.h b/crawl-ref/source/itemprop-enum.h
index 9b72a2ad89..ad5763e819 100644
--- a/crawl-ref/source/itemprop-enum.h
+++ b/crawl-ref/source/itemprop-enum.h
@@ -470,7 +470,9 @@ enum weapon_type
WPN_LONGBOW,
WPN_MAX_RACIAL = WPN_LONGBOW,
+#if TAG_MAJOR_VERSION == 32
WPN_ANKUS,
+#endif
WPN_DEMON_WHIP,
WPN_GIANT_CLUB,
WPN_GIANT_SPIKED_CLUB,
diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc
index 52056bed70..362639a3ca 100644
--- a/crawl-ref/source/itemprop.cc
+++ b/crawl-ref/source/itemprop.cc
@@ -193,12 +193,14 @@ static weapon_def Weapon_prop[NUM_WEAPONS] =
{ WPN_FLAIL, "flail", 9, 2, 15, 130, 8,
SK_MACES_FLAILS, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
DAMV_CRUSHING, 10 },
+#if TAG_MAJOR_VERSION == 32
{ WPN_ANKUS, "ankus", 9, 2, 14, 120, 8,
SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
- DAMV_PIERCING | DAM_BLUDGEON, 1 },
+ DAMV_CRUSHING | DAM_PIERCE, 1 },
+#endif
{ WPN_MORNINGSTAR, "morningstar", 10, -1, 15, 140, 8,
SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
- DAMV_PIERCING | DAM_BLUDGEON, 10 },
+ DAMV_CRUSHING | DAM_PIERCE, 10 },
{ WPN_DEMON_WHIP, "demon whip", 11, 1, 11, 30, 2,
SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLASHING, 2 },
@@ -207,13 +209,13 @@ static weapon_def Weapon_prop[NUM_WEAPONS] =
DAMV_SLASHING, 0 },
{ WPN_SPIKED_FLAIL, "spiked flail", 12, -2, 16, 190, 8,
SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
- DAMV_PIERCING | DAM_BLUDGEON, 10 },
+ DAMV_CRUSHING | DAM_PIERCE, 10 },
{ WPN_DIRE_FLAIL, "dire flail", 13, -3, 13, 240, 9,
SK_MACES_FLAILS, HANDS_DOUBLE, SIZE_LARGE, MI_NONE, false,
- DAMV_PIERCING | DAM_BLUDGEON, 10 },
+ DAMV_CRUSHING | DAM_PIERCE, 10 },
{ WPN_EVENINGSTAR, "eveningstar", 14, -1, 15, 180, 8,
SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
- DAMV_PIERCING | DAM_BLUDGEON, 2 },
+ DAMV_CRUSHING | DAM_PIERCE, 2 },
{ WPN_GREAT_MACE, "great mace", 18, -4, 17, 270, 9,
SK_MACES_FLAILS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_CRUSHING, 10 },
@@ -222,7 +224,7 @@ static weapon_def Weapon_prop[NUM_WEAPONS] =
DAMV_CRUSHING, 10 },
{ WPN_GIANT_SPIKED_CLUB, "giant spiked club", 22, -7, 18, 350, 10,
SK_MACES_FLAILS, HANDS_TWO, SIZE_BIG, MI_NONE, false,
- DAMV_PIERCING | DAM_BLUDGEON, 10 },
+ DAMV_CRUSHING | DAM_PIERCE, 10 },
// Short Blades
#if TAG_MAJOR_VERSION == 32
@@ -324,7 +326,7 @@ static weapon_def Weapon_prop[NUM_WEAPONS] =
DAMV_CHOPPING | DAM_PIERCE, 10 },
{ WPN_SCYTHE, "scythe", 14, -4, 20, 220, 7,
SK_POLEARMS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
- DAMV_SLICING, 10 },
+ DAMV_SLICING, 0 },
{ WPN_DEMON_TRIDENT, "demon trident", 12, 1, 13, 160, 4,
SK_POLEARMS, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
DAMV_PIERCING, 2 },
@@ -422,30 +424,30 @@ static int Food_index[NUM_FOODS];
static food_def Food_prop[NUM_FOODS] =
{
{ FOOD_MEAT_RATION, "meat ration", 5000, 500, -1500, 80, 4, FFL_NONE },
- { FOOD_SAUSAGE, "sausage", 1500, 150, -400, 40, 1, FFL_NONE },
+ { FOOD_SAUSAGE, "sausage", 1200, 150, -400, 40, 2, FFL_NONE },
{ FOOD_CHUNK, "chunk", 1000, 100, -500, 100, 3, FFL_NONE },
- { FOOD_BEEF_JERKY, "beef jerky", 800, 100, -250, 20, 1, FFL_NONE },
-
- { FOOD_BREAD_RATION, "bread ration", 4400, -1500, 750, 80, 4, FFL_NONE },
-
- { FOOD_SNOZZCUMBER, "snozzcumber", 1500, -500, 500, 50, 1, FFL_FRUIT},
- { FOOD_ORANGE, "orange", 1000, -350, 400, 20, 1, FFL_FRUIT},
- { FOOD_BANANA, "banana", 1000, -350, 400, 20, 1, FFL_FRUIT},
- { FOOD_LEMON, "lemon", 1000, -350, 400, 20, 1, FFL_FRUIT},
- { FOOD_PEAR, "pear", 700, -250, 300, 20, 1, FFL_FRUIT},
- { FOOD_APPLE, "apple", 700, -250, 300, 20, 1, FFL_FRUIT},
- { FOOD_APRICOT, "apricot", 700, -250, 300, 15, 1, FFL_FRUIT},
- { FOOD_CHOKO, "choko", 600, -200, 250, 30, 1, FFL_FRUIT},
- { FOOD_RAMBUTAN, "rambutan", 600, -200, 250, 10, 1, FFL_FRUIT},
- { FOOD_LYCHEE, "lychee", 600, -200, 250, 10, 1, FFL_FRUIT},
- { FOOD_STRAWBERRY, "strawberry", 200, -80, 100, 5, 1, FFL_FRUIT},
- { FOOD_GRAPE, "grape", 100, -40, 50, 2, 1, FFL_FRUIT},
- { FOOD_SULTANA, "sultana", 70, -30, 30, 1, 1, FFL_FRUIT},
-
- { FOOD_ROYAL_JELLY, "royal jelly", 4000, 0, 0, 55, 1, FFL_NONE },
- { FOOD_HONEYCOMB, "honeycomb", 2000, 0, 0, 40, 1, FFL_NONE },
- { FOOD_PIZZA, "pizza", 1500, -100, 0, 40, 1, FFL_NONE },
- { FOOD_CHEESE, "cheese", 1200, 100, 0, 40, 1, FFL_NONE },
+ { FOOD_BEEF_JERKY, "beef jerky", 1500, 200, -200, 20, 2, FFL_NONE },
+
+ { FOOD_BREAD_RATION, "bread ration", 4400, -1000, 500, 80, 4, FFL_NONE },
+
+ { FOOD_SNOZZCUMBER, "snozzcumber", 1500, -500, 500, 50, 2, FFL_FRUIT},
+ { FOOD_ORANGE, "orange", 1000, -300, 300, 20, 2, FFL_FRUIT},
+ { FOOD_BANANA, "banana", 1000, -300, 300, 20, 2, FFL_FRUIT},
+ { FOOD_LEMON, "lemon", 1000, -300, 300, 20, 2, FFL_FRUIT},
+ { FOOD_PEAR, "pear", 700, -200, 200, 20, 2, FFL_FRUIT},
+ { FOOD_APPLE, "apple", 700, -200, 200, 20, 2, FFL_FRUIT},
+ { FOOD_APRICOT, "apricot", 700, -200, 200, 15, 2, FFL_FRUIT},
+ { FOOD_CHOKO, "choko", 600, -200, 200, 30, 2, FFL_FRUIT},
+ { FOOD_RAMBUTAN, "rambutan", 600, -200, 200, 10, 2, FFL_FRUIT},
+ { FOOD_LYCHEE, "lychee", 600, -200, 200, 10, 2, FFL_FRUIT},
+ { FOOD_STRAWBERRY, "strawberry", 200, -50, 50, 5, 2, FFL_FRUIT},
+ { FOOD_GRAPE, "grape", 100, -20, 20, 2, 1, FFL_FRUIT},
+ { FOOD_SULTANA, "sultana", 70, -20, 20, 1, 1, FFL_FRUIT},
+
+ { FOOD_ROYAL_JELLY, "royal jelly", 5000, 0, 0, 55, 2, FFL_NONE },
+ { FOOD_HONEYCOMB, "honeycomb", 2000, 0, 0, 40, 2, FFL_NONE },
+ { FOOD_PIZZA, "pizza", 1500, 0, 0, 40, 2, FFL_NONE },
+ { FOOD_CHEESE, "cheese", 1200, 0, 0, 40, 2, FFL_NONE },
{ FOOD_AMBROSIA, "ambrosia", 2500, 0, 0, 40, 1, FFL_NONE },
};
@@ -532,6 +534,10 @@ void do_curse_item(item_def &item, bool quiet)
// This might prevent a carried item from allowing training.
maybe_change_train(item, false);
+ // If the item isn't equipped, you might not be able to use it for training.
+ if (!item_is_equipped(item))
+ item_skills(item, you.stop_train);
+
item.flags |= ISFLAG_CURSED;
// Xom is amused by the player's items being cursed, especially if
@@ -1406,7 +1412,6 @@ int weapon_rarity(int w_type)
case WPN_GREAT_MACE:
return (3);
- case WPN_ANKUS:
case WPN_DIRE_FLAIL:
case WPN_SCYTHE:
case WPN_LONGBOW:
@@ -1421,6 +1426,7 @@ int weapon_rarity(int w_type)
#if TAG_MAJOR_VERSION == 32
case WPN_KATANA:
case WPN_BLESSED_KATANA:
+ case WPN_ANKUS:
#endif
case WPN_DOUBLE_SWORD:
case WPN_EVENINGSTAR:
@@ -2355,24 +2361,21 @@ bool is_fizzing_potion (const item_def &item)
return (item.sub_type == POT_FIZZING);
}
-// Returns food value for one turn of eating.
int food_value(const item_def &item)
{
ASSERT(item.defined() && item.base_type == OBJ_FOOD);
const int herb = player_mutation_level(MUT_HERBIVOROUS);
-
- // XXX: This needs to be better merged with the mutation system.
const int carn = player_mutation_level(MUT_CARNIVOROUS);
const food_def &food = Food_prop[Food_index[item.sub_type]];
int ret = food.value;
- ret += (carn * food.carn_mod);
- ret += (herb * food.herb_mod);
+ ret += carn * food.carn_mod;
+ ret += herb * food.herb_mod;
- return ((ret > 0) ? div_rand_round(ret, food.turns) : 0);
+ return ret;
}
int food_turns(const item_def &item)
diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc
index 1f6fe2d1c5..c4a307a875 100644
--- a/crawl-ref/source/items.cc
+++ b/crawl-ref/source/items.cc
@@ -603,24 +603,11 @@ void item_was_lost(const item_def &item)
xom_check_lost_item(item);
}
-static void _note_item_destruction(const item_def &item)
-{
- if (item_is_orb(item))
- {
- mprf(MSGCH_WARN, "A great rumbling fills the air... "
- "the Orb of Zot has been destroyed!");
- mark_milestone("orb.destroy", "destroyed the Orb of Zot");
- env.orb_pos.reset();
- invalidate_agrid(false);
- }
-}
-
void item_was_destroyed(const item_def &item, int cause)
{
if (item.props.exists("destroy_xp"))
gain_exp(item.props["destroy_xp"].get_int());
_handle_gone_item(item);
- _note_item_destruction(item);
xom_check_destroyed_item(item, cause);
}
@@ -1991,10 +1978,7 @@ bool move_item_to_grid(int *const obj, const coord_def& p, bool silent)
igrd(p) = ob;
if (item_is_orb(item))
- {
env.orb_pos = p;
- invalidate_agrid(true);
- }
return (true);
}
@@ -2207,6 +2191,12 @@ bool drop_item(int item_dropped, int quant_drop)
return (false);
}
+ if (you.inv[item_dropped].base_type == OBJ_ORBS)
+ {
+ mpr("You don't feel like leaving the orb behind!");
+ return (false);
+ }
+
if (item_dropped == you.equip[EQ_WEAPON]
&& you.inv[item_dropped].base_type == OBJ_WEAPONS
&& you.inv[item_dropped].cursed())
@@ -2976,7 +2966,8 @@ item_def *find_floor_item(object_class_type cls, int sub_type)
for (int x = 0; x < GXM; ++x)
for (stack_iterator si(coord_def(x,y)); si; ++si)
if (si->defined()
- && si->base_type == cls && si->sub_type == sub_type)
+ && si->base_type == cls && si->sub_type == sub_type
+ && !(si->flags & ISFLAG_MIMIC))
{
return (& (*si));
}
@@ -3912,7 +3903,10 @@ item_info get_item_info(const item_def& item)
found_unmarked = true;
}
}
- // TODO: this leaks both whether the seen cards are still there and their order: the representation needs to be fixed
+ // TODO: this leaks both whether the seen cards are still there
+ // and their order: the representation needs to be fixed
+
+ // The above comment seems obsolete now that Mark Four is gone.
for (int i = 0; i < num_cards; ++i)
{
uint8_t flags;
@@ -3988,19 +3982,7 @@ int runes_in_pack()
bool player_has_orb()
{
- if (you.char_direction != GDT_ASCENDING)
- return false;
-
- for (int i = 0; i < ENDOFPACK; i++)
- {
- if (you.inv[i].defined()
- && you.inv[i].base_type == OBJ_ORBS
- && you.inv[i].sub_type == ORB_ZOT)
- {
- return (true);
- }
- }
- return false;
+ return you.char_direction == GDT_ASCENDING;
}
static const object_class_type _mimic_item_classes[] =
diff --git a/crawl-ref/source/json.cc b/crawl-ref/source/json.cc
index 47729a7d20..bcbc2221bb 100644
--- a/crawl-ref/source/json.cc
+++ b/crawl-ref/source/json.cc
@@ -21,97 +21,100 @@
THE SOFTWARE.
*/
+#include "AppHdr.h"
#include "json.h"
-#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#define out_of_memory() do { \
- fprintf(stderr, "Out of memory.\n"); \
- exit(EXIT_FAILURE); \
- } while (0)
+#define out_of_memory() do \
+ { \
+ fprintf(stderr, "Out of memory.\n"); \
+ exit(EXIT_FAILURE); \
+ } while (0)
/* Sadly, strdup is not portable. */
static char *json_strdup(const char *str)
{
- char *ret = (char*) malloc(strlen(str) + 1);
- if (ret == NULL)
- out_of_memory();
- strcpy(ret, str);
- return ret;
+ char *ret = (char*)malloc(strlen(str) + 1);
+ if (ret == NULL)
+ out_of_memory();
+ strcpy(ret, str);
+ return ret;
}
/* String buffer */
typedef struct
{
- char *cur;
- char *end;
- char *start;
+ char *cur;
+ char *end;
+ char *start;
} SB;
static void sb_init(SB *sb)
{
- sb->start = (char*) malloc(17);
- if (sb->start == NULL)
- out_of_memory();
- sb->cur = sb->start;
- sb->end = sb->start + 16;
+ sb->start = (char*)malloc(17);
+ if (sb->start == NULL)
+ out_of_memory();
+ sb->cur = sb->start;
+ sb->end = sb->start + 16;
}
/* sb and need may be evaluated multiple times. */
-#define sb_need(sb, need) do { \
- if ((sb)->end - (sb)->cur < (need)) \
- sb_grow(sb, need); \
- } while (0)
+#define sb_need(sb, need) do \
+ { \
+ if ((sb)->end - (sb)->cur < (need)) \
+ sb_grow(sb, need); \
+ } while (0)
static void sb_grow(SB *sb, int need)
{
- size_t length = sb->cur - sb->start;
- size_t alloc = sb->end - sb->start;
-
- do {
- alloc *= 2;
- } while (alloc < length + need);
-
- sb->start = (char*) realloc(sb->start, alloc + 1);
- if (sb->start == NULL)
- out_of_memory();
- sb->cur = sb->start + length;
- sb->end = sb->start + alloc;
+ size_t length = sb->cur - sb->start;
+ size_t alloc = sb->end - sb->start;
+
+ do { alloc *= 2; }
+ while (alloc < length + need);
+
+ sb->start = (char*)realloc(sb->start, alloc + 1);
+ if (sb->start == NULL)
+ out_of_memory();
+ sb->cur = sb->start + length;
+ sb->end = sb->start + alloc;
}
static void sb_put(SB *sb, const char *bytes, int count)
{
- sb_need(sb, count);
- memcpy(sb->cur, bytes, count);
- sb->cur += count;
+ sb_need(sb, count);
+ memcpy(sb->cur, bytes, count);
+ sb->cur += count;
}
-#define sb_putc(sb, c) do { \
- if ((sb)->cur >= (sb)->end) \
- sb_grow(sb, 1); \
- *(sb)->cur++ = (c); \
- } while (0)
+#define sb_putc(sb, c) do \
+ { \
+ if ((sb)->cur >= (sb)->end) \
+ sb_grow(sb, 1); \
+ *(sb)->cur++ = (c); \
+ } while (0)
static void sb_puts(SB *sb, const char *str)
{
- sb_put(sb, str, strlen(str));
+ sb_put(sb, str, strlen(str));
}
static char *sb_finish(SB *sb)
{
- *sb->cur = 0;
- assert(sb->start <= sb->cur && strlen(sb->start) == (size_t)(sb->cur - sb->start));
- return sb->start;
+ *sb->cur = 0;
+ ASSERT(sb->start <= sb->cur);
+ ASSERT(strlen(sb->start) == (size_t)(sb->cur - sb->start));
+ return sb->start;
}
static void sb_free(SB *sb)
{
- free(sb->start);
+ free(sb->start);
}
/*
@@ -150,70 +153,78 @@ typedef uint32_t uchar_t;
*/
static int utf8_validate_cz(const char *s)
{
- unsigned char c = *s++;
+ unsigned char c = *s++;
+
+ if (c <= 0x7F) /* 00..7F */
+ return 1;
+ else if (c <= 0xC1) /* 80..C1 */
+ {
+ /* Disallow overlong 2-byte sequence. */
+ return 0;
+ }
+ else if (c <= 0xDF) /* C2..DF */
+ {
+ /* Make sure subsequent byte is in the range 0x80..0xBF. */
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+
+ return 2;
+ }
+ else if (c <= 0xEF) /* E0..EF */
+ {
+ /* Disallow overlong 3-byte sequence. */
+ if (c == 0xE0 && (unsigned char)*s < 0xA0)
+ return 0;
+
+ /* Disallow U+D800..U+DFFF. */
+ if (c == 0xED && (unsigned char)*s > 0x9F)
+ return 0;
+
+ /* Make sure subsequent bytes are in the range 0x80..0xBF. */
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+
+ return 3;
+ }
+ else if (c <= 0xF4) /* F0..F4 */
+ {
+ /* Disallow overlong 4-byte sequence. */
+ if (c == 0xF0 && (unsigned char)*s < 0x90)
+ return 0;
+
+ /* Disallow codepoints beyond U+10FFFF. */
+ if (c == 0xF4 && (unsigned char)*s > 0x8F)
+ return 0;
+
+ /* Make sure subsequent bytes are in the range 0x80..0xBF. */
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
- if (c <= 0x7F) { /* 00..7F */
- return 1;
- } else if (c <= 0xC1) { /* 80..C1 */
- /* Disallow overlong 2-byte sequence. */
- return 0;
- } else if (c <= 0xDF) { /* C2..DF */
- /* Make sure subsequent byte is in the range 0x80..0xBF. */
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
-
- return 2;
- } else if (c <= 0xEF) { /* E0..EF */
- /* Disallow overlong 3-byte sequence. */
- if (c == 0xE0 && (unsigned char)*s < 0xA0)
- return 0;
-
- /* Disallow U+D800..U+DFFF. */
- if (c == 0xED && (unsigned char)*s > 0x9F)
- return 0;
-
- /* Make sure subsequent bytes are in the range 0x80..0xBF. */
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
-
- return 3;
- } else if (c <= 0xF4) { /* F0..F4 */
- /* Disallow overlong 4-byte sequence. */
- if (c == 0xF0 && (unsigned char)*s < 0x90)
- return 0;
-
- /* Disallow codepoints beyond U+10FFFF. */
- if (c == 0xF4 && (unsigned char)*s > 0x8F)
- return 0;
-
- /* Make sure subsequent bytes are in the range 0x80..0xBF. */
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
- if (((unsigned char)*s++ & 0xC0) != 0x80)
- return 0;
-
- return 4;
- } else { /* F5..FF */
- return 0;
- }
+ return 4;
+ }
+ else /* F5..FF */
+ return 0;
}
/* Validate a null-terminated UTF-8 string. */
static bool utf8_validate(const char *s)
{
- int len;
+ int len;
- for (; *s != 0; s += len) {
- len = utf8_validate_cz(s);
- if (len == 0)
- return false;
- }
+ for (; *s != 0; s += len)
+ {
+ len = utf8_validate_cz(s);
+ if (len == 0)
+ return false;
+ }
- return true;
+ return true;
}
/*
@@ -225,33 +236,40 @@ static bool utf8_validate(const char *s)
*/
static int utf8_read_char(const char *s, uchar_t *out)
{
- const unsigned char *c = (const unsigned char*) s;
-
- assert(utf8_validate_cz(s));
-
- if (c[0] <= 0x7F) {
- /* 00..7F */
- *out = c[0];
- return 1;
- } else if (c[0] <= 0xDF) {
- /* C2..DF (unless input is invalid) */
- *out = ((uchar_t)c[0] & 0x1F) << 6 |
- ((uchar_t)c[1] & 0x3F);
- return 2;
- } else if (c[0] <= 0xEF) {
- /* E0..EF */
- *out = ((uchar_t)c[0] & 0xF) << 12 |
- ((uchar_t)c[1] & 0x3F) << 6 |
- ((uchar_t)c[2] & 0x3F);
- return 3;
- } else {
- /* F0..F4 (unless input is invalid) */
- *out = ((uchar_t)c[0] & 0x7) << 18 |
- ((uchar_t)c[1] & 0x3F) << 12 |
- ((uchar_t)c[2] & 0x3F) << 6 |
- ((uchar_t)c[3] & 0x3F);
- return 4;
- }
+ const unsigned char *c = (const unsigned char*) s;
+
+ ASSERT(utf8_validate_cz(s));
+
+ if (c[0] <= 0x7F)
+ {
+ /* 00..7F */
+ *out = c[0];
+ return 1;
+ }
+ else if (c[0] <= 0xDF)
+ {
+ /* C2..DF (unless input is invalid) */
+ *out = ((uchar_t)c[0] & 0x1F) << 6 |
+ ((uchar_t)c[1] & 0x3F);
+ return 2;
+ }
+ else if (c[0] <= 0xEF)
+ {
+ /* E0..EF */
+ *out = ((uchar_t)c[0] & 0xF) << 12 |
+ ((uchar_t)c[1] & 0x3F) << 6 |
+ ((uchar_t)c[2] & 0x3F);
+ return 3;
+ }
+ else
+ {
+ /* F0..F4 (unless input is invalid) */
+ *out = ((uchar_t)c[0] & 0x7) << 18 |
+ ((uchar_t)c[1] & 0x3F) << 12 |
+ ((uchar_t)c[2] & 0x3F) << 6 |
+ ((uchar_t)c[3] & 0x3F);
+ return 4;
+ }
}
/*
@@ -264,33 +282,41 @@ static int utf8_read_char(const char *s, uchar_t *out)
*/
static int utf8_write_char(uchar_t unicode, char *out)
{
- unsigned char *o = (unsigned char*) out;
-
- assert(unicode <= 0x10FFFF && !(unicode >= 0xD800 && unicode <= 0xDFFF));
-
- if (unicode <= 0x7F) {
- /* U+0000..U+007F */
- *o++ = unicode;
- return 1;
- } else if (unicode <= 0x7FF) {
- /* U+0080..U+07FF */
- *o++ = 0xC0 | unicode >> 6;
- *o++ = 0x80 | (unicode & 0x3F);
- return 2;
- } else if (unicode <= 0xFFFF) {
- /* U+0800..U+FFFF */
- *o++ = 0xE0 | unicode >> 12;
- *o++ = 0x80 | (unicode >> 6 & 0x3F);
- *o++ = 0x80 | (unicode & 0x3F);
- return 3;
- } else {
- /* U+10000..U+10FFFF */
- *o++ = 0xF0 | unicode >> 18;
- *o++ = 0x80 | (unicode >> 12 & 0x3F);
- *o++ = 0x80 | (unicode >> 6 & 0x3F);
- *o++ = 0x80 | (unicode & 0x3F);
- return 4;
- }
+ unsigned char *o = (unsigned char*) out;
+
+ ASSERT(unicode <= 0x10FFFF);
+ ASSERT(!(unicode >= 0xD800 && unicode <= 0xDFFF)); // UTF-16 surrogates
+
+ if (unicode <= 0x7F)
+ {
+ /* U+0000..U+007F */
+ *o++ = unicode;
+ return 1;
+ }
+ else if (unicode <= 0x7FF)
+ {
+ /* U+0080..U+07FF */
+ *o++ = 0xC0 | unicode >> 6;
+ *o++ = 0x80 | (unicode & 0x3F);
+ return 2;
+ }
+ else if (unicode <= 0xFFFF)
+ {
+ /* U+0800..U+FFFF */
+ *o++ = 0xE0 | unicode >> 12;
+ *o++ = 0x80 | (unicode >> 6 & 0x3F);
+ *o++ = 0x80 | (unicode & 0x3F);
+ return 3;
+ }
+ else
+ {
+ /* U+10000..U+10FFFF */
+ *o++ = 0xF0 | unicode >> 18;
+ *o++ = 0x80 | (unicode >> 12 & 0x3F);
+ *o++ = 0x80 | (unicode >> 6 & 0x3F);
+ *o++ = 0x80 | (unicode & 0x3F);
+ return 4;
+ }
}
/*
@@ -301,12 +327,13 @@ static int utf8_write_char(uchar_t unicode, char *out)
*/
static bool from_surrogate_pair(uint16_t uc, uint16_t lc, uchar_t *unicode)
{
- if (uc >= 0xD800 && uc <= 0xDBFF && lc >= 0xDC00 && lc <= 0xDFFF) {
- *unicode = 0x10000 + ((((uchar_t)uc & 0x3FF) << 10) | (lc & 0x3FF));
- return true;
- } else {
- return false;
- }
+ if (uc >= 0xD800 && uc <= 0xDBFF && lc >= 0xDC00 && lc <= 0xDFFF)
+ {
+ *unicode = 0x10000 + ((((uchar_t)uc & 0x3FF) << 10) | (lc & 0x3FF));
+ return true;
+ }
+ else
+ return false;
}
/*
@@ -316,35 +343,35 @@ static bool from_surrogate_pair(uint16_t uc, uint16_t lc, uchar_t *unicode)
*/
static void to_surrogate_pair(uchar_t unicode, uint16_t *uc, uint16_t *lc)
{
- uchar_t n;
+ uchar_t n;
- assert(unicode >= 0x10000 && unicode <= 0x10FFFF);
+ ASSERT(unicode >= 0x10000 && unicode <= 0x10FFFF);
- n = unicode - 0x10000;
- *uc = ((n >> 10) & 0x3FF) | 0xD800;
- *lc = (n & 0x3FF) | 0xDC00;
+ n = unicode - 0x10000;
+ *uc = ((n >> 10) & 0x3FF) | 0xD800;
+ *lc = (n & 0x3FF) | 0xDC00;
}
#define is_space(c) ((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
#define is_digit(c) ((c) >= '0' && (c) <= '9')
-static bool parse_value (const char **sp, JsonNode **out);
-static bool parse_string (const char **sp, char **out);
-static bool parse_number (const char **sp, double *out);
-static bool parse_array (const char **sp, JsonNode **out);
-static bool parse_object (const char **sp, JsonNode **out);
-static bool parse_hex16 (const char **sp, uint16_t *out);
+static bool parse_value (const char **sp, JsonNode **out);
+static bool parse_string (const char **sp, char **out);
+static bool parse_number (const char **sp, double *out);
+static bool parse_array (const char **sp, JsonNode **out);
+static bool parse_object (const char **sp, JsonNode **out);
+static bool parse_hex16 (const char **sp, uint16_t *out);
static bool expect_literal (const char **sp, const char *str);
static void skip_space (const char **sp);
-static void emit_value (SB *out, const JsonNode *node);
+static void emit_value (SB *out, const JsonNode *node);
static void emit_value_indented (SB *out, const JsonNode *node, const char *space, int indent_level);
-static void emit_string (SB *out, const char *str);
-static void emit_number (SB *out, double num);
-static void emit_array (SB *out, const JsonNode *array);
+static void emit_string (SB *out, const char *str);
+static void emit_number (SB *out, double num);
+static void emit_array (SB *out, const JsonNode *array);
static void emit_array_indented (SB *out, const JsonNode *array, const char *space, int indent_level);
-static void emit_object (SB *out, const JsonNode *object);
+static void emit_object (SB *out, const JsonNode *object);
static void emit_object_indented (SB *out, const JsonNode *object, const char *space, int indent_level);
static int write_hex16(char *out, uint16_t val);
@@ -360,555 +387,589 @@ static bool number_is_valid(const char *num);
JsonNode *json_decode(const char *json)
{
- const char *s = json;
- JsonNode *ret;
+ const char *s = json;
+ JsonNode *ret;
- skip_space(&s);
- if (!parse_value(&s, &ret))
- return NULL;
+ skip_space(&s);
+ if (!parse_value(&s, &ret))
+ return NULL;
- skip_space(&s);
- if (*s != 0) {
- json_delete(ret);
- return NULL;
- }
+ skip_space(&s);
+ if (*s != 0)
+ {
+ json_delete(ret);
+ return NULL;
+ }
- return ret;
+ return ret;
}
char *json_encode(const JsonNode *node)
{
- return json_stringify(node, NULL);
+ return json_stringify(node, NULL);
}
char *json_encode_string(const char *str)
{
- SB sb;
- sb_init(&sb);
+ SB sb;
+ sb_init(&sb);
- emit_string(&sb, str);
+ emit_string(&sb, str);
- return sb_finish(&sb);
+ return sb_finish(&sb);
}
char *json_stringify(const JsonNode *node, const char *space)
{
- SB sb;
- sb_init(&sb);
+ SB sb;
+ sb_init(&sb);
- if (space != NULL)
- emit_value_indented(&sb, node, space, 0);
- else
- emit_value(&sb, node);
+ if (space != NULL)
+ emit_value_indented(&sb, node, space, 0);
+ else
+ emit_value(&sb, node);
- return sb_finish(&sb);
+ return sb_finish(&sb);
}
void json_delete(JsonNode *node)
{
- if (node != NULL) {
- json_remove_from_parent(node);
-
- switch (node->tag) {
- case JSON_STRING:
- free(node->string_);
- break;
- case JSON_ARRAY:
- case JSON_OBJECT:
- {
- JsonNode *child, *next;
- for (child = node->children.head; child != NULL; child = next) {
- next = child->next;
- json_delete(child);
- }
- break;
- }
- default:;
+ if (node != NULL)
+ {
+ json_remove_from_parent(node);
+
+ switch (node->tag)
+ {
+ case JSON_STRING:
+ free(node->string_);
+ break;
+ case JSON_ARRAY:
+ case JSON_OBJECT:
+ {
+ JsonNode *child, *next;
+ for (child = node->children.head; child != NULL; child = next)
+ {
+ next = child->next;
+ json_delete(child);
}
-
- free(node);
+ break;
+ }
+ default:;
}
+
+ free(node);
+ }
}
bool json_validate(const char *json)
{
- const char *s = json;
+ const char *s = json;
- skip_space(&s);
- if (!parse_value(&s, NULL))
- return false;
+ skip_space(&s);
+ if (!parse_value(&s, NULL))
+ return false;
- skip_space(&s);
- if (*s != 0)
- return false;
+ skip_space(&s);
+ if (*s != 0)
+ return false;
- return true;
+ return true;
}
JsonNode *json_find_element(JsonNode *array, int index)
{
- JsonNode *element;
- int i = 0;
+ JsonNode *element;
+ int i = 0;
- if (array == NULL || array->tag != JSON_ARRAY)
- return NULL;
+ if (array == NULL || array->tag != JSON_ARRAY)
+ return NULL;
- json_foreach(element, array) {
- if (i == index)
- return element;
- i++;
- }
+ json_foreach(element, array)
+ {
+ if (i == index)
+ return element;
+ i++;
+ }
- return NULL;
+ return NULL;
}
JsonNode *json_find_member(JsonNode *object, const char *name)
{
- JsonNode *member;
+ JsonNode *member;
- if (object == NULL || object->tag != JSON_OBJECT)
- return NULL;
+ if (object == NULL || object->tag != JSON_OBJECT)
+ return NULL;
- json_foreach(member, object)
- if (strcmp(member->key, name) == 0)
- return member;
+ json_foreach(member, object)
+ if (strcmp(member->key, name) == 0)
+ return member;
- return NULL;
+ return NULL;
}
JsonNode *json_first_child(const JsonNode *node)
{
- if (node != NULL && (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT))
- return node->children.head;
- return NULL;
+ if (node != NULL && (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT))
+ return node->children.head;
+ return NULL;
}
static JsonNode *mknode(JsonTag tag)
{
- JsonNode *ret = (JsonNode*) calloc(1, sizeof(JsonNode));
- if (ret == NULL)
- out_of_memory();
- ret->tag = tag;
- return ret;
+ JsonNode *ret = (JsonNode*) calloc(1, sizeof(JsonNode));
+ if (ret == NULL)
+ out_of_memory();
+ ret->tag = tag;
+ return ret;
}
JsonNode *json_mknull(void)
{
- return mknode(JSON_NULL);
+ return mknode(JSON_NULL);
}
JsonNode *json_mkbool(bool b)
{
- JsonNode *ret = mknode(JSON_BOOL);
- ret->bool_ = b;
- return ret;
+ JsonNode *ret = mknode(JSON_BOOL);
+ ret->bool_ = b;
+ return ret;
}
static JsonNode *mkstring(char *s)
{
- JsonNode *ret = mknode(JSON_STRING);
- ret->string_ = s;
- return ret;
+ JsonNode *ret = mknode(JSON_STRING);
+ ret->string_ = s;
+ return ret;
}
JsonNode *json_mkstring(const char *s)
{
- return mkstring(json_strdup(s));
+ return mkstring(json_strdup(s));
}
JsonNode *json_mknumber(double n)
{
- JsonNode *node = mknode(JSON_NUMBER);
- node->number_ = n;
- return node;
+ JsonNode *node = mknode(JSON_NUMBER);
+ node->number_ = n;
+ return node;
}
JsonNode *json_mkarray(void)
{
- return mknode(JSON_ARRAY);
+ return mknode(JSON_ARRAY);
}
JsonNode *json_mkobject(void)
{
- return mknode(JSON_OBJECT);
+ return mknode(JSON_OBJECT);
}
static void append_node(JsonNode *parent, JsonNode *child)
{
- child->parent = parent;
- child->prev = parent->children.tail;
- child->next = NULL;
+ child->parent = parent;
+ child->prev = parent->children.tail;
+ child->next = NULL;
- if (parent->children.tail != NULL)
- parent->children.tail->next = child;
- else
- parent->children.head = child;
- parent->children.tail = child;
+ if (parent->children.tail != NULL)
+ parent->children.tail->next = child;
+ else
+ parent->children.head = child;
+ parent->children.tail = child;
}
static void prepend_node(JsonNode *parent, JsonNode *child)
{
- child->parent = parent;
- child->prev = NULL;
- child->next = parent->children.head;
+ child->parent = parent;
+ child->prev = NULL;
+ child->next = parent->children.head;
- if (parent->children.head != NULL)
- parent->children.head->prev = child;
- else
- parent->children.tail = child;
- parent->children.head = child;
+ if (parent->children.head != NULL)
+ parent->children.head->prev = child;
+ else
+ parent->children.tail = child;
+ parent->children.head = child;
}
static void append_member(JsonNode *object, char *key, JsonNode *value)
{
- value->key = key;
- append_node(object, value);
+ value->key = key;
+ append_node(object, value);
}
void json_append_element(JsonNode *array, JsonNode *element)
{
- assert(array->tag == JSON_ARRAY);
- assert(element->parent == NULL);
+ ASSERT(array->tag == JSON_ARRAY);
+ ASSERT(element->parent == NULL);
- append_node(array, element);
+ append_node(array, element);
}
void json_prepend_element(JsonNode *array, JsonNode *element)
{
- assert(array->tag == JSON_ARRAY);
- assert(element->parent == NULL);
+ ASSERT(array->tag == JSON_ARRAY);
+ ASSERT(element->parent == NULL);
- prepend_node(array, element);
+ prepend_node(array, element);
}
void json_append_member(JsonNode *object, const char *key, JsonNode *value)
{
- assert(object->tag == JSON_OBJECT);
- assert(value->parent == NULL);
+ ASSERT(object->tag == JSON_OBJECT);
+ ASSERT(value->parent == NULL);
- append_member(object, json_strdup(key), value);
+ append_member(object, json_strdup(key), value);
}
void json_prepend_member(JsonNode *object, const char *key, JsonNode *value)
{
- assert(object->tag == JSON_OBJECT);
- assert(value->parent == NULL);
+ ASSERT(object->tag == JSON_OBJECT);
+ ASSERT(value->parent == NULL);
- value->key = json_strdup(key);
- prepend_node(object, value);
+ value->key = json_strdup(key);
+ prepend_node(object, value);
}
void json_remove_from_parent(JsonNode *node)
{
- JsonNode *parent = node->parent;
+ JsonNode *parent = node->parent;
- if (parent != NULL) {
- if (node->prev != NULL)
- node->prev->next = node->next;
- else
- parent->children.head = node->next;
- if (node->next != NULL)
- node->next->prev = node->prev;
- else
- parent->children.tail = node->prev;
+ if (parent != NULL)
+ {
+ if (node->prev != NULL)
+ node->prev->next = node->next;
+ else
+ parent->children.head = node->next;
+ if (node->next != NULL)
+ node->next->prev = node->prev;
+ else
+ parent->children.tail = node->prev;
- free(node->key);
+ free(node->key);
- node->parent = NULL;
- node->prev = node->next = NULL;
- node->key = NULL;
- }
+ node->parent = NULL;
+ node->prev = node->next = NULL;
+ node->key = NULL;
+ }
}
static bool parse_value(const char **sp, JsonNode **out)
{
- const char *s = *sp;
-
- switch (*s) {
- case 'n':
- if (expect_literal(&s, "null")) {
- if (out)
- *out = json_mknull();
- *sp = s;
- return true;
- }
- return false;
-
- case 'f':
- if (expect_literal(&s, "false")) {
- if (out)
- *out = json_mkbool(false);
- *sp = s;
- return true;
- }
- return false;
-
- case 't':
- if (expect_literal(&s, "true")) {
- if (out)
- *out = json_mkbool(true);
- *sp = s;
- return true;
- }
- return false;
-
- case '"': {
- char *str;
- if (parse_string(&s, out ? &str : NULL)) {
- if (out)
- *out = mkstring(str);
- *sp = s;
- return true;
- }
- return false;
- }
+ const char *s = *sp;
+
+ switch (*s)
+ {
+ case 'n':
+ if (expect_literal(&s, "null"))
+ {
+ if (out)
+ *out = json_mknull();
+ *sp = s;
+ return true;
+ }
+ return false;
- case '[':
- if (parse_array(&s, out)) {
- *sp = s;
- return true;
- }
- return false;
-
- case '{':
- if (parse_object(&s, out)) {
- *sp = s;
- return true;
- }
- return false;
-
- default: {
- double num;
- if (parse_number(&s, out ? &num : NULL)) {
- if (out)
- *out = json_mknumber(num);
- *sp = s;
- return true;
- }
- return false;
- }
+ case 'f':
+ if (expect_literal(&s, "false"))
+ {
+ if (out)
+ *out = json_mkbool(false);
+ *sp = s;
+ return true;
}
+ return false;
+
+ case 't':
+ if (expect_literal(&s, "true"))
+ {
+ if (out)
+ *out = json_mkbool(true);
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ case '"':
+ {
+ char *str;
+ if (parse_string(&s, out ? &str : NULL))
+ {
+ if (out)
+ *out = mkstring(str);
+ *sp = s;
+ return true;
+ }
+ return false;
+ }
+
+ case '[':
+ if (parse_array(&s, out))
+ {
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ case '{':
+ if (parse_object(&s, out))
+ {
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ default:
+ {
+ double num;
+ if (parse_number(&s, out ? &num : NULL))
+ {
+ if (out)
+ *out = json_mknumber(num);
+ *sp = s;
+ return true;
+ }
+ return false;
+ }
+ }
}
static bool parse_array(const char **sp, JsonNode **out)
{
- const char *s = *sp;
- JsonNode *ret = out ? json_mkarray() : NULL;
- JsonNode *element;
-
- if (*s++ != '[')
- goto failure;
- skip_space(&s);
+ const char *s = *sp;
+ JsonNode *ret = out ? json_mkarray() : NULL;
+ JsonNode *element;
- if (*s == ']') {
- s++;
- goto success;
- }
+ if (*s++ != '[')
+ goto failure;
+ skip_space(&s);
- for (;;) {
- if (!parse_value(&s, out ? &element : NULL))
- goto failure;
- skip_space(&s);
+ if (*s == ']')
+ {
+ s++;
+ goto success;
+ }
- if (out)
- json_append_element(ret, element);
+ for (;;)
+ {
+ if (!parse_value(&s, out ? &element : NULL))
+ goto failure;
+ skip_space(&s);
- if (*s == ']') {
- s++;
- goto success;
- }
+ if (out)
+ json_append_element(ret, element);
- if (*s++ != ',')
- goto failure;
- skip_space(&s);
+ if (*s == ']')
+ {
+ s++;
+ goto success;
}
+ if (*s++ != ',')
+ goto failure;
+ skip_space(&s);
+ }
+
success:
- *sp = s;
- if (out)
- *out = ret;
- return true;
+ *sp = s;
+ if (out)
+ *out = ret;
+ return true;
failure:
- json_delete(ret);
- return false;
+ json_delete(ret);
+ return false;
}
static bool parse_object(const char **sp, JsonNode **out)
{
- const char *s = *sp;
- JsonNode *ret = out ? json_mkobject() : NULL;
- char *key;
- JsonNode *value;
-
- if (*s++ != '{')
- goto failure;
- skip_space(&s);
+ const char *s = *sp;
+ JsonNode *ret = out ? json_mkobject() : NULL;
+ char *key;
+ JsonNode *value;
- if (*s == '}') {
- s++;
- goto success;
- }
+ if (*s++ != '{')
+ goto failure;
+ skip_space(&s);
- for (;;) {
- if (!parse_string(&s, out ? &key : NULL))
- goto failure;
- skip_space(&s);
+ if (*s == '}')
+ {
+ s++;
+ goto success;
+ }
- if (*s++ != ':')
- goto failure_free_key;
- skip_space(&s);
+ for (;;)
+ {
+ if (!parse_string(&s, out ? &key : NULL))
+ goto failure;
+ skip_space(&s);
- if (!parse_value(&s, out ? &value : NULL))
- goto failure_free_key;
- skip_space(&s);
+ if (*s++ != ':')
+ goto failure_free_key;
+ skip_space(&s);
- if (out)
- append_member(ret, key, value);
+ if (!parse_value(&s, out ? &value : NULL))
+ goto failure_free_key;
+ skip_space(&s);
- if (*s == '}') {
- s++;
- goto success;
- }
+ if (out)
+ append_member(ret, key, value);
- if (*s++ != ',')
- goto failure;
- skip_space(&s);
+ if (*s == '}')
+ {
+ s++;
+ goto success;
}
+ if (*s++ != ',')
+ goto failure;
+ skip_space(&s);
+ }
+
success:
- *sp = s;
- if (out)
- *out = ret;
- return true;
+ *sp = s;
+ if (out)
+ *out = ret;
+ return true;
failure_free_key:
- if (out)
- free(key);
+ if (out)
+ free(key);
failure:
- json_delete(ret);
- return false;
+ json_delete(ret);
+ return false;
}
bool parse_string(const char **sp, char **out)
{
- const char *s = *sp;
- SB sb;
- char throwaway_buffer[4];
- /* enough space for a UTF-8 character */
- char *b;
-
- if (*s++ != '"')
- return false;
-
- if (out) {
- sb_init(&sb);
- sb_need(&sb, 4);
- b = sb.cur;
- } else {
- b = throwaway_buffer;
- }
+ const char *s = *sp;
+ SB sb;
+ char throwaway_buffer[4];
+ /* enough space for a UTF-8 character */
+ char *b;
- while (*s != '"') {
- unsigned char c = *s++;
-
- /* Parse next character, and write it to b. */
- if (c == '\\') {
- c = *s++;
- switch (c) {
- case '"':
- case '\\':
- case '/':
- *b++ = c;
- break;
- case 'b':
- *b++ = '\b';
- break;
- case 'f':
- *b++ = '\f';
- break;
- case 'n':
- *b++ = '\n';
- break;
- case 'r':
- *b++ = '\r';
- break;
- case 't':
- *b++ = '\t';
- break;
- case 'u':
- {
- uint16_t uc, lc;
- uchar_t unicode;
-
- if (!parse_hex16(&s, &uc))
- goto failed;
-
- if (uc >= 0xD800 && uc <= 0xDFFF) {
- /* Handle UTF-16 surrogate pair. */
- if (*s++ != '\\' || *s++ != 'u' || !parse_hex16(&s, &lc))
- goto failed; /* Incomplete surrogate pair. */
- if (!from_surrogate_pair(uc, lc, &unicode))
- goto failed; /* Invalid surrogate pair. */
- } else if (uc == 0) {
- /* Disallow "\u0000". */
- goto failed;
- } else {
- unicode = uc;
- }
-
- b += utf8_write_char(unicode, b);
- break;
- }
- default:
- /* Invalid escape */
- goto failed;
- }
- } else if (c <= 0x1F) {
- /* Control characters are not allowed in string literals. */
- goto failed;
- } else {
- /* Validate and echo a UTF-8 character. */
- int len;
-
- s--;
- len = utf8_validate_cz(s);
- if (len == 0)
- goto failed; /* Invalid UTF-8 character. */
-
- while (len--)
- *b++ = *s++;
- }
+ if (*s++ != '"')
+ return false;
- /*
- * Update sb to know about the new bytes,
- * and set up b to write another character.
- */
- if (out) {
- sb.cur = b;
- sb_need(&sb, 4);
- b = sb.cur;
- } else {
- b = throwaway_buffer;
+ if (out)
+ {
+ sb_init(&sb);
+ sb_need(&sb, 4);
+ b = sb.cur;
+ }
+ else
+ b = throwaway_buffer;
+
+ while (*s != '"')
+ {
+ unsigned char c = *s++;
+
+ /* Parse next character, and write it to b. */
+ if (c == '\\')
+ {
+ c = *s++;
+ switch (c)
+ {
+ case '"':
+ case '\\':
+ case '/':
+ *b++ = c;
+ break;
+ case 'b':
+ *b++ = '\b';
+ break;
+ case 'f':
+ *b++ = '\f';
+ break;
+ case 'n':
+ *b++ = '\n';
+ break;
+ case 'r':
+ *b++ = '\r';
+ break;
+ case 't':
+ *b++ = '\t';
+ break;
+ case 'u':
+ {
+ uint16_t uc, lc;
+ uchar_t unicode;
+
+ if (!parse_hex16(&s, &uc))
+ goto failed;
+
+ if (uc >= 0xD800 && uc <= 0xDFFF)
+ {
+ /* Handle UTF-16 surrogate pair. */
+ if (*s++ != '\\' || *s++ != 'u' || !parse_hex16(&s, &lc))
+ goto failed; /* Incomplete surrogate pair. */
+ if (!from_surrogate_pair(uc, lc, &unicode))
+ goto failed; /* Invalid surrogate pair. */
+ }
+ else if (uc == 0)
+ {
+ /* Disallow "\u0000". */
+ goto failed;
}
+ else
+ unicode = uc;
+
+ b += utf8_write_char(unicode, b);
+ break;
+ }
+ default:
+ /* Invalid escape */
+ goto failed;
+ }
+ }
+ else if (c <= 0x1F)
+ {
+ /* Control characters are not allowed in string literals. */
+ goto failed;
+ }
+ else
+ {
+ /* Validate and echo a UTF-8 character. */
+ int len;
+
+ s--;
+ len = utf8_validate_cz(s);
+ if (len == 0)
+ goto failed; /* Invalid UTF-8 character. */
+
+ while (len--)
+ *b++ = *s++;
}
- s++;
+ /*
+ * Update sb to know about the new bytes,
+ * and set up b to write another character.
+ */
if (out)
- *out = sb_finish(&sb);
- *sp = s;
- return true;
+ {
+ sb.cur = b;
+ sb_need(&sb, 4);
+ b = sb.cur;
+ }
+ else
+ b = throwaway_buffer;
+ }
+ s++;
+
+ if (out)
+ *out = sb_finish(&sb);
+ *sp = s;
+ return true;
failed:
- if (out)
- sb_free(&sb);
- return false;
+ if (out)
+ sb_free(&sb);
+ return false;
}
/*
* The JSON spec says that a number shall follow this precise pattern
* (spaces and quotes added for readability):
- * '-'? (0 | [1-9][0-9]*) ('.' [0-9]+)? ([Ee] [+-]? [0-9]+)?
+ * '-'? (0 | [1-9][0-9]*) ('.' [0-9]+)? ([Ee] [+-]? [0-9]+)?
*
* However, some JSON parsers are more liberal. For instance, PHP accepts
* '.5' and '1.'. JSON.parse accepts '+3'.
@@ -917,348 +978,369 @@ failed:
*/
bool parse_number(const char **sp, double *out)
{
- const char *s = *sp;
-
- /* '-'? */
- if (*s == '-')
- s++;
-
- /* (0 | [1-9][0-9]*) */
- if (*s == '0') {
- s++;
- } else {
- if (!is_digit(*s))
- return false;
- do {
- s++;
- } while (is_digit(*s));
- }
-
- /* ('.' [0-9]+)? */
- if (*s == '.') {
- s++;
- if (!is_digit(*s))
- return false;
- do {
- s++;
- } while (is_digit(*s));
- }
-
- /* ([Ee] [+-]? [0-9]+)? */
- if (*s == 'E' || *s == 'e') {
- s++;
- if (*s == '+' || *s == '-')
- s++;
- if (!is_digit(*s))
- return false;
- do {
- s++;
- } while (is_digit(*s));
- }
+ const char *s = *sp;
- if (out)
- *out = strtod(*sp, NULL);
+ /* '-'? */
+ if (*s == '-')
+ s++;
- *sp = s;
- return true;
+ /* (0 | [1-9][0-9]*) */
+ if (*s == '0')
+ s++;
+ else
+ {
+ if (!is_digit(*s))
+ return false;
+ do { s++; } while (is_digit(*s));
+ }
+
+ /* ('.' [0-9]+)? */
+ if (*s == '.')
+ {
+ s++;
+ if (!is_digit(*s))
+ return false;
+ do { s++; } while (is_digit(*s));
+ }
+
+ /* ([Ee] [+-]? [0-9]+)? */
+ if (*s == 'E' || *s == 'e')
+ {
+ s++;
+ if (*s == '+' || *s == '-')
+ s++;
+ if (!is_digit(*s))
+ return false;
+ do { s++; } while (is_digit(*s));
+ }
+
+ if (out)
+ *out = strtod(*sp, NULL);
+
+ *sp = s;
+ return true;
}
static void skip_space(const char **sp)
{
- const char *s = *sp;
- while (is_space(*s))
- s++;
- *sp = s;
+ const char *s = *sp;
+ while (is_space(*s))
+ s++;
+ *sp = s;
}
static void emit_value(SB *out, const JsonNode *node)
{
- assert(tag_is_valid(node->tag));
- switch (node->tag) {
- case JSON_NULL:
- sb_puts(out, "null");
- break;
- case JSON_BOOL:
- sb_puts(out, node->bool_ ? "true" : "false");
- break;
- case JSON_STRING:
- emit_string(out, node->string_);
- break;
- case JSON_NUMBER:
- emit_number(out, node->number_);
- break;
- case JSON_ARRAY:
- emit_array(out, node);
- break;
- case JSON_OBJECT:
- emit_object(out, node);
- break;
- default:
- assert(false);
- }
+ ASSERT(tag_is_valid(node->tag));
+ switch (node->tag)
+ {
+ case JSON_NULL:
+ sb_puts(out, "null");
+ break;
+ case JSON_BOOL:
+ sb_puts(out, node->bool_ ? "true" : "false");
+ break;
+ case JSON_STRING:
+ emit_string(out, node->string_);
+ break;
+ case JSON_NUMBER:
+ emit_number(out, node->number_);
+ break;
+ case JSON_ARRAY:
+ emit_array(out, node);
+ break;
+ case JSON_OBJECT:
+ emit_object(out, node);
+ break;
+ default:
+ die("invalid JSON tag type");
+ }
}
void emit_value_indented(SB *out, const JsonNode *node, const char *space, int indent_level)
{
- assert(tag_is_valid(node->tag));
- switch (node->tag) {
- case JSON_NULL:
- sb_puts(out, "null");
- break;
- case JSON_BOOL:
- sb_puts(out, node->bool_ ? "true" : "false");
- break;
- case JSON_STRING:
- emit_string(out, node->string_);
- break;
- case JSON_NUMBER:
- emit_number(out, node->number_);
- break;
- case JSON_ARRAY:
- emit_array_indented(out, node, space, indent_level);
- break;
- case JSON_OBJECT:
- emit_object_indented(out, node, space, indent_level);
- break;
- default:
- assert(false);
- }
+ ASSERT(tag_is_valid(node->tag));
+ switch (node->tag)
+ {
+ case JSON_NULL:
+ sb_puts(out, "null");
+ break;
+ case JSON_BOOL:
+ sb_puts(out, node->bool_ ? "true" : "false");
+ break;
+ case JSON_STRING:
+ emit_string(out, node->string_);
+ break;
+ case JSON_NUMBER:
+ emit_number(out, node->number_);
+ break;
+ case JSON_ARRAY:
+ emit_array_indented(out, node, space, indent_level);
+ break;
+ case JSON_OBJECT:
+ emit_object_indented(out, node, space, indent_level);
+ break;
+ default:
+ die("invalid JSON tag type");
+ }
}
static void emit_array(SB *out, const JsonNode *array)
{
- const JsonNode *element;
-
- sb_putc(out, '[');
- json_foreach(element, array) {
- emit_value(out, element);
- if (element->next != NULL)
- sb_putc(out, ',');
- }
- sb_putc(out, ']');
+ const JsonNode *element;
+
+ sb_putc(out, '[');
+ json_foreach(element, array)
+ {
+ emit_value(out, element);
+ if (element->next != NULL)
+ sb_putc(out, ',');
+ }
+ sb_putc(out, ']');
}
static void emit_array_indented(SB *out, const JsonNode *array, const char *space, int indent_level)
{
- const JsonNode *element = array->children.head;
- int i;
-
- if (element == NULL) {
- sb_puts(out, "[]");
- return;
- }
-
- sb_puts(out, "[\n");
- while (element != NULL) {
- for (i = 0; i < indent_level + 1; i++)
- sb_puts(out, space);
- emit_value_indented(out, element, space, indent_level + 1);
-
- element = element->next;
- sb_puts(out, element != NULL ? ",\n" : "\n");
- }
- for (i = 0; i < indent_level; i++)
- sb_puts(out, space);
- sb_putc(out, ']');
+ const JsonNode *element = array->children.head;
+ int i;
+
+ if (element == NULL)
+ {
+ sb_puts(out, "[]");
+ return;
+ }
+
+ sb_puts(out, "[\n");
+ while (element != NULL)
+ {
+ for (i = 0; i < indent_level + 1; i++)
+ sb_puts(out, space);
+ emit_value_indented(out, element, space, indent_level + 1);
+
+ element = element->next;
+ sb_puts(out, element != NULL ? ",\n" : "\n");
+ }
+ for (i = 0; i < indent_level; i++)
+ sb_puts(out, space);
+ sb_putc(out, ']');
}
static void emit_object(SB *out, const JsonNode *object)
{
- const JsonNode *member;
-
- sb_putc(out, '{');
- json_foreach(member, object) {
- emit_string(out, member->key);
- sb_putc(out, ':');
- emit_value(out, member);
- if (member->next != NULL)
- sb_putc(out, ',');
- }
- sb_putc(out, '}');
+ const JsonNode *member;
+
+ sb_putc(out, '{');
+ json_foreach(member, object)
+ {
+ emit_string(out, member->key);
+ sb_putc(out, ':');
+ emit_value(out, member);
+ if (member->next != NULL)
+ sb_putc(out, ',');
+ }
+ sb_putc(out, '}');
}
static void emit_object_indented(SB *out, const JsonNode *object, const char *space, int indent_level)
{
- const JsonNode *member = object->children.head;
- int i;
-
- if (member == NULL) {
- sb_puts(out, "{}");
- return;
- }
-
- sb_puts(out, "{\n");
- while (member != NULL) {
- for (i = 0; i < indent_level + 1; i++)
- sb_puts(out, space);
- emit_string(out, member->key);
- sb_puts(out, ": ");
- emit_value_indented(out, member, space, indent_level + 1);
-
- member = member->next;
- sb_puts(out, member != NULL ? ",\n" : "\n");
- }
- for (i = 0; i < indent_level; i++)
- sb_puts(out, space);
- sb_putc(out, '}');
+ const JsonNode *member = object->children.head;
+ int i;
+
+ if (member == NULL)
+ {
+ sb_puts(out, "{}");
+ return;
+ }
+
+ sb_puts(out, "{\n");
+ while (member != NULL)
+ {
+ for (i = 0; i < indent_level + 1; i++)
+ sb_puts(out, space);
+ emit_string(out, member->key);
+ sb_puts(out, ": ");
+ emit_value_indented(out, member, space, indent_level + 1);
+
+ member = member->next;
+ sb_puts(out, member != NULL ? ",\n" : "\n");
+ }
+ for (i = 0; i < indent_level; i++)
+ sb_puts(out, space);
+ sb_putc(out, '}');
}
void emit_string(SB *out, const char *str)
{
- bool escape_unicode = false;
- const char *s = str;
- char *b;
+ bool escape_unicode = false;
+ const char *s = str;
+ char *b;
+
+ ASSERT(utf8_validate(str));
+
+ /*
+ * 14 bytes is enough space to write up to two
+ * \uXXXX escapes and two quotation marks.
+ */
+ sb_need(out, 14);
+ b = out->cur;
+
+ *b++ = '"';
+ while (*s != 0)
+ {
+ unsigned char c = *s++;
- assert(utf8_validate(str));
+ /* Encode the next character, and write it to b. */
+ switch (c)
+ {
+ case '"':
+ *b++ = '\\';
+ *b++ = '"';
+ break;
+ case '\\':
+ *b++ = '\\';
+ *b++ = '\\';
+ break;
+ case '\b':
+ *b++ = '\\';
+ *b++ = 'b';
+ break;
+ case '\f':
+ *b++ = '\\';
+ *b++ = 'f';
+ break;
+ case '\n':
+ *b++ = '\\';
+ *b++ = 'n';
+ break;
+ case '\r':
+ *b++ = '\\';
+ *b++ = 'r';
+ break;
+ case '\t':
+ *b++ = '\\';
+ *b++ = 't';
+ break;
+ default:
+ {
+ int len;
+
+ s--;
+ len = utf8_validate_cz(s);
+
+ if (len == 0)
+ {
+ /*
+ * Handle invalid UTF-8 character gracefully in production
+ * by writing a replacement character (U+FFFD)
+ * and skipping a single byte.
+ *
+ * This should never happen when assertions are enabled
+ * due to the assertion at the beginning of this function.
+ */
+ die("mangled character");
+ if (escape_unicode)
+ {
+ strcpy(b, "\\uFFFD");
+ b += 6;
+ }
+ else
+ {
+ *b++ = 0xEF;
+ *b++ = 0xBF;
+ *b++ = 0xBD;
+ }
+ s++;
+ }
+ else if (c < 0x1F || (c >= 0x80 && escape_unicode))
+ {
+ /* Encode using \u.... */
+ uint32_t unicode;
+
+ s += utf8_read_char(s, &unicode);
+
+ if (unicode <= 0xFFFF)
+ {
+ *b++ = '\\';
+ *b++ = 'u';
+ b += write_hex16(b, unicode);
+ }
+ else
+ {
+ /* Produce a surrogate pair. */
+ uint16_t uc, lc;
+ ASSERT(unicode <= 0x10FFFF);
+ to_surrogate_pair(unicode, &uc, &lc);
+ *b++ = '\\';
+ *b++ = 'u';
+ b += write_hex16(b, uc);
+ *b++ = '\\';
+ *b++ = 'u';
+ b += write_hex16(b, lc);
+ }
+ }
+ else
+ {
+ /* Write the character directly. */
+ while (len--)
+ *b++ = *s++;
+ }
+
+ break;
+ }
+ }
/*
- * 14 bytes is enough space to write up to two
- * \uXXXX escapes and two quotation marks.
+ * Update *out to know about the new bytes,
+ * and set up b to write another encoded character.
*/
+ out->cur = b;
sb_need(out, 14);
b = out->cur;
+ }
+ *b++ = '"';
- *b++ = '"';
- while (*s != 0) {
- unsigned char c = *s++;
-
- /* Encode the next character, and write it to b. */
- switch (c) {
- case '"':
- *b++ = '\\';
- *b++ = '"';
- break;
- case '\\':
- *b++ = '\\';
- *b++ = '\\';
- break;
- case '\b':
- *b++ = '\\';
- *b++ = 'b';
- break;
- case '\f':
- *b++ = '\\';
- *b++ = 'f';
- break;
- case '\n':
- *b++ = '\\';
- *b++ = 'n';
- break;
- case '\r':
- *b++ = '\\';
- *b++ = 'r';
- break;
- case '\t':
- *b++ = '\\';
- *b++ = 't';
- break;
- default: {
- int len;
-
- s--;
- len = utf8_validate_cz(s);
-
- if (len == 0) {
- /*
- * Handle invalid UTF-8 character gracefully in production
- * by writing a replacement character (U+FFFD)
- * and skipping a single byte.
- *
- * This should never happen when assertions are enabled
- * due to the assertion at the beginning of this function.
- */
- assert(false);
- if (escape_unicode) {
- strcpy(b, "\\uFFFD");
- b += 6;
- } else {
- *b++ = 0xEF;
- *b++ = 0xBF;
- *b++ = 0xBD;
- }
- s++;
- } else if (c < 0x1F || (c >= 0x80 && escape_unicode)) {
- /* Encode using \u.... */
- uint32_t unicode;
-
- s += utf8_read_char(s, &unicode);
-
- if (unicode <= 0xFFFF) {
- *b++ = '\\';
- *b++ = 'u';
- b += write_hex16(b, unicode);
- } else {
- /* Produce a surrogate pair. */
- uint16_t uc, lc;
- assert(unicode <= 0x10FFFF);
- to_surrogate_pair(unicode, &uc, &lc);
- *b++ = '\\';
- *b++ = 'u';
- b += write_hex16(b, uc);
- *b++ = '\\';
- *b++ = 'u';
- b += write_hex16(b, lc);
- }
- } else {
- /* Write the character directly. */
- while (len--)
- *b++ = *s++;
- }
-
- break;
- }
- }
-
- /*
- * Update *out to know about the new bytes,
- * and set up b to write another encoded character.
- */
- out->cur = b;
- sb_need(out, 14);
- b = out->cur;
- }
- *b++ = '"';
-
- out->cur = b;
+ out->cur = b;
}
static void emit_number(SB *out, double num)
{
- /*
- * This isn't exactly how JavaScript renders numbers,
- * but it should produce valid JSON for reasonable numbers
- * preserve precision well enough, and avoid some oddities
- * like 0.3 -> 0.299999999999999988898 .
- */
- char buf[64];
- sprintf(buf, "%.16g", num);
-
- if (number_is_valid(buf))
- sb_puts(out, buf);
- else
- sb_puts(out, "null");
+ /*
+ * This isn't exactly how JavaScript renders numbers,
+ * but it should produce valid JSON for reasonable numbers
+ * preserve precision well enough, and avoid some oddities
+ * like 0.3 -> 0.299999999999999988898 .
+ */
+ char buf[64];
+ sprintf(buf, "%.16g", num);
+
+ if (number_is_valid(buf))
+ sb_puts(out, buf);
+ else
+ sb_puts(out, "null");
}
static bool tag_is_valid(unsigned int tag)
{
- return (/* tag >= JSON_NULL && */ tag <= JSON_OBJECT);
+ return (/* tag >= JSON_NULL && */ tag <= JSON_OBJECT);
}
static bool number_is_valid(const char *num)
{
- return (parse_number(&num, NULL) && *num == '\0');
+ return (parse_number(&num, NULL) && *num == '\0');
}
static bool expect_literal(const char **sp, const char *str)
{
- const char *s = *sp;
+ const char *s = *sp;
- while (*str != '\0')
- if (*s++ != *str++)
- return false;
+ while (*str != '\0')
+ {
+ if (*s++ != *str++)
+ return false;
+ }
- *sp = s;
- return true;
+ *sp = s;
+ return true;
}
/*
@@ -1267,31 +1349,32 @@ static bool expect_literal(const char **sp, const char *str)
*/
static bool parse_hex16(const char **sp, uint16_t *out)
{
- const char *s = *sp;
- uint16_t ret = 0;
- uint16_t i;
- uint16_t tmp;
- char c;
-
- for (i = 0; i < 4; i++) {
- c = *s++;
- if (c >= '0' && c <= '9')
- tmp = c - '0';
- else if (c >= 'A' && c <= 'F')
- tmp = c - 'A' + 10;
- else if (c >= 'a' && c <= 'f')
- tmp = c - 'a' + 10;
- else
- return false;
+ const char *s = *sp;
+ uint16_t ret = 0;
+ uint16_t i;
+ uint16_t tmp;
+ char c;
+
+ for (i = 0; i < 4; i++)
+ {
+ c = *s++;
+ if (c >= '0' && c <= '9')
+ tmp = c - '0';
+ else if (c >= 'A' && c <= 'F')
+ tmp = c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ tmp = c - 'a' + 10;
+ else
+ return false;
- ret <<= 4;
- ret += tmp;
- }
+ ret <<= 4;
+ ret += tmp;
+ }
- if (out)
- *out = ret;
- *sp = s;
- return true;
+ if (out)
+ *out = ret;
+ *sp = s;
+ return true;
}
/*
@@ -1300,82 +1383,91 @@ static bool parse_hex16(const char **sp, uint16_t *out)
*/
static int write_hex16(char *out, uint16_t val)
{
- const char *hex = "0123456789ABCDEF";
+ const char *hex = "0123456789ABCDEF";
- *out++ = hex[(val >> 12) & 0xF];
- *out++ = hex[(val >> 8) & 0xF];
- *out++ = hex[(val >> 4) & 0xF];
- *out++ = hex[ val & 0xF];
+ *out++ = hex[(val >> 12) & 0xF];
+ *out++ = hex[(val >> 8) & 0xF];
+ *out++ = hex[(val >> 4) & 0xF];
+ *out++ = hex[ val & 0xF];
- return 4;
+ return 4;
}
bool json_check(const JsonNode *node, char errmsg[256])
{
- #define problem(...) do { \
- if (errmsg != NULL) \
- snprintf(errmsg, 256, __VA_ARGS__); \
- return false; \
- } while (0)
-
- if (node->key != NULL && !utf8_validate(node->key))
- problem("key contains invalid UTF-8");
-
- if (!tag_is_valid(node->tag))
- problem("tag is invalid (%u)", node->tag);
-
- if (node->tag == JSON_BOOL) {
- if (node->bool_ != false && node->bool_ != true)
- problem("bool_ is neither false (%d) nor true (%d)", (int)false, (int)true);
- } else if (node->tag == JSON_STRING) {
- if (node->string_ == NULL)
- problem("string_ is NULL");
- if (!utf8_validate(node->string_))
- problem("string_ contains invalid UTF-8");
- } else if (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT) {
- JsonNode *head = node->children.head;
- JsonNode *tail = node->children.tail;
-
- if (head == NULL || tail == NULL) {
- if (head != NULL)
- problem("tail is NULL, but head is not");
- if (tail != NULL)
- problem("head is NULL, but tail is not");
- } else {
- JsonNode *child;
- JsonNode *last = NULL;
-
- if (head->prev != NULL)
- problem("First child's prev pointer is not NULL");
-
- for (child = head; child != NULL; last = child, child = child->next) {
- if (child == node)
- problem("node is its own child");
- if (child->next == child)
- problem("child->next == child (cycle)");
- if (child->next == head)
- problem("child->next == head (cycle)");
-
- if (child->parent != node)
- problem("child does not point back to parent");
- if (child->next != NULL && child->next->prev != child)
- problem("child->next does not point back to child");
-
- if (node->tag == JSON_ARRAY && child->key != NULL)
- problem("Array element's key is not NULL");
- if (node->tag == JSON_OBJECT && child->key == NULL)
- problem("Object member's key is NULL");
-
- if (!json_check(child, errmsg))
- return false;
- }
-
- if (last != tail)
- problem("tail does not match pointer found by starting at head and following next links");
- }
+ #define problem(...) do { \
+ if (errmsg != NULL) \
+ snprintf(errmsg, 256, __VA_ARGS__); \
+ return false; \
+ } while (0)
+
+ if (node->key != NULL && !utf8_validate(node->key))
+ problem("key contains invalid UTF-8");
+
+ if (!tag_is_valid(node->tag))
+ problem("tag is invalid (%u)", node->tag);
+
+ if (node->tag == JSON_BOOL)
+ {
+ if (node->bool_ != false && node->bool_ != true)
+ problem("bool_ is neither false (%d) nor true (%d)", (int)false, (int)true);
+ }
+ else if (node->tag == JSON_STRING)
+ {
+ if (node->string_ == NULL)
+ problem("string_ is NULL");
+ if (!utf8_validate(node->string_))
+ problem("string_ contains invalid UTF-8");
+ }
+ else if (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT)
+ {
+ JsonNode *head = node->children.head;
+ JsonNode *tail = node->children.tail;
+
+ if (head == NULL || tail == NULL)
+ {
+ if (head != NULL)
+ problem("tail is NULL, but head is not");
+ if (tail != NULL)
+ problem("head is NULL, but tail is not");
}
+ else
+ {
+ JsonNode *child;
+ JsonNode *last = NULL;
+
+ if (head->prev != NULL)
+ problem("First child's prev pointer is not NULL");
+
+ for (child = head; child != NULL; last = child, child = child->next)
+ {
+ if (child == node)
+ problem("node is its own child");
+ if (child->next == child)
+ problem("child->next == child (cycle)");
+ if (child->next == head)
+ problem("child->next == head (cycle)");
+
+ if (child->parent != node)
+ problem("child does not point back to parent");
+ if (child->next != NULL && child->next->prev != child)
+ problem("child->next does not point back to child");
+
+ if (node->tag == JSON_ARRAY && child->key != NULL)
+ problem("Array element's key is not NULL");
+ if (node->tag == JSON_OBJECT && child->key == NULL)
+ problem("Object member's key is NULL");
+
+ if (!json_check(child, errmsg))
+ return false;
+ }
+
+ if (last != tail)
+ problem("tail does not match pointer found by starting at head and following next links");
+ }
+ }
- return true;
+ return true;
- #undef problem
+ #undef problem
}
diff --git a/crawl-ref/source/l_crawl.cc b/crawl-ref/source/l_crawl.cc
index 3fa39f1155..6765ce9bb3 100644
--- a/crawl-ref/source/l_crawl.cc
+++ b/crawl-ref/source/l_crawl.cc
@@ -643,6 +643,8 @@ LUARET1(crawl_roll_dice, number,
: roll_dice(luaL_checkint(ls, 1), luaL_checkint(ls, 2)))
LUARET1(crawl_x_chance_in_y, boolean, x_chance_in_y(luaL_checkint(ls, 1),
luaL_checkint(ls, 2)))
+LUARET1(crawl_div_rand_round, number, div_rand_round(luaL_checkint(ls, 1),
+ luaL_checkint(ls, 2)))
static int crawl_is_tiles(lua_State *ls)
{
@@ -848,6 +850,7 @@ static const struct luaL_reg crawl_clib[] =
{ "x_chance_in_y", crawl_x_chance_in_y },
{ "random_range", crawl_random_range },
{ "random_element", crawl_random_element },
+ { "div_rand_round", crawl_div_rand_round },
{ "redraw_screen", crawl_redraw_screen },
{ "c_input_line", crawl_c_input_line},
{ "getch", crawl_getch },
diff --git a/crawl-ref/source/l_dgn.cc b/crawl-ref/source/l_dgn.cc
index ce751fc155..c2040fc15a 100644
--- a/crawl-ref/source/l_dgn.cc
+++ b/crawl-ref/source/l_dgn.cc
@@ -1601,14 +1601,14 @@ LUAFN(_dgn_map_parameters)
return clua_stringtable(ls, map_parameters);
}
-int dgn_push_vault_placement(lua_State *ls, const vault_placement *vp)
+static int _dgn_push_vault_placement(lua_State *ls, const vault_placement *vp)
{
return dlua_push_object_type(ls, VAULT_PLACEMENT_METATABLE, *vp);
}
LUAFN(_dgn_maps_used_here)
{
- return clua_gentable(ls, env.level_vaults, dgn_push_vault_placement);
+ return clua_gentable(ls, env.level_vaults, _dgn_push_vault_placement);
}
LUAFN(_dgn_vault_at)
@@ -1616,13 +1616,9 @@ LUAFN(_dgn_vault_at)
GETCOORD(c, 1, 2, map_bounds);
vault_placement *place = dgn_vault_at(c);
if (place)
- {
- dgn_push_vault_placement(ls, place);
- }
+ _dgn_push_vault_placement(ls, place);
else
- {
lua_pushnil(ls);
- }
return 1;
}
diff --git a/crawl-ref/source/l_item.cc b/crawl-ref/source/l_item.cc
index d741612a4b..ac04faef85 100644
--- a/crawl-ref/source/l_item.cc
+++ b/crawl-ref/source/l_item.cc
@@ -64,7 +64,7 @@ void lua_push_floor_items(lua_State *ls, int link)
}
}
-void lua_push_inv_items(lua_State *ls = NULL)
+static void _lua_push_inv_items(lua_State *ls = NULL)
{
if (!ls)
ls = clua.state();
@@ -697,7 +697,7 @@ static int l_item_do_inc_quantity (lua_State *ls)
IDEFN(inc_quantity, do_inc_quantity)
-iflags_t str_to_item_status_flags (std::string flag)
+static iflags_t _str_to_item_status_flags (std::string flag)
{
iflags_t flags = 0;
if (flag.find("curse") != std::string::npos)
@@ -736,7 +736,7 @@ static int l_item_do_identified (lua_State *ls)
else
{
const bool check_type = strip_tag(flags, "type");
- iflags_t item_flags = str_to_item_status_flags(flags);
+ iflags_t item_flags = _str_to_item_status_flags(flags);
known_status = ((item_flags || check_type)
&& (!item_flags || item_ident(*item, item_flags))
&& (!check_type || item_type_known(*item)));
@@ -807,7 +807,7 @@ IDEF(is_cursed)
// Library functions below
static int l_item_inventory(lua_State *ls)
{
- lua_push_inv_items(ls);
+ _lua_push_inv_items(ls);
return (1);
}
diff --git a/crawl-ref/source/l_moninf.cc b/crawl-ref/source/l_moninf.cc
index b98cbf5ccf..6e6a63a587 100644
--- a/crawl-ref/source/l_moninf.cc
+++ b/crawl-ref/source/l_moninf.cc
@@ -62,11 +62,76 @@ LUAFN(moninf_get_is)
return (1);
}
-LUAFN(moninf_get_is_very_stabbable)
+static bool cant_see_you(const monster_info *mi)
+{
+ if (mons_class_flag(mi->type, M_SEE_INVIS))
+ return false;
+ if (mons_class_flag(mi->type, M_SENSE_INVIS)
+ && (you.pos() - mi->pos).abs() <= 17)
+ {
+ return false;
+ }
+ if (you.in_water())
+ return false;
+ return you.invisible() || mi->is(MB_BLIND);
+}
+
+LUAFN(moninf_get_stabbability)
+{
+ MONINF(ls, 1, mi);
+ if (mi->is(MB_DORMANT) || mi->is(MB_SLEEPING) || mi->is(MB_PARALYSED))
+ lua_pushnumber(ls, 1.0);
+ else if (mi->is(MB_CAUGHT) || mi->is(MB_WEBBED) || mi->is(MB_PETRIFYING)
+ || mi->is(MB_PETRIFIED))
+ {
+ lua_pushnumber(ls, 0.5);
+ }
+ else if (mi->is(MB_CONFUSED) || mi->is(MB_FLEEING) || cant_see_you(mi))
+ lua_pushnumber(ls, 0.25);
+ else if (mi->is(MB_DISTRACTED))
+ lua_pushnumber(ls, 0.16666666);
+ else
+ lua_pushnumber(ls, 0);
+
+ return (1);
+}
+
+LUAFN(moninf_get_is_constricted)
{
MONINF(ls, 1, mi);
- lua_pushboolean(ls, mi->is(MB_DORMANT) || mi->is(MB_SLEEPING) ||
- mi->is(MB_PARALYSED));
+ lua_pushboolean(ls, !mi->constrictor_name.empty());
+ return (1);
+}
+
+LUAFN(moninf_get_is_constricting)
+{
+ MONINF(ls, 1, mi);
+ bool any = false;
+ for (int i = 0; i < MAX_CONSTRICT; i++)
+ if (!mi->constricting_name[i].empty())
+ {
+ any = true;
+ break;
+ }
+ lua_pushboolean(ls, any);
+ return (1);
+}
+
+LUAFN(moninf_get_is_constricting_you)
+{
+ MONINF(ls, 1, mi);
+ if (!you.is_constricted())
+ {
+ lua_pushboolean(ls, false);
+ return (1);
+ }
+ for (int i = 0; i < MAX_CONSTRICT; i++)
+ if (mi->constricting_name[i] == "you") // yay the interface
+ {
+ lua_pushboolean(ls, true);
+ return (1);
+ }
+ lua_pushboolean(ls, false);
return (1);
}
@@ -110,10 +175,13 @@ static const struct luaL_reg moninf_lib[] =
MIREG(is),
MIREG(is_safe),
MIREG(is_firewood),
- MIREG(is_very_stabbable),
+ MIREG(stabbability),
MIREG(holiness),
MIREG(attitude),
MIREG(threat),
+ MIREG(is_constricted),
+ MIREG(is_constricting),
+ MIREG(is_constricting_you),
MIREG(is_unique),
MIREG(damage_level),
MIREG(damage_desc),
diff --git a/crawl-ref/source/l_view.cc b/crawl-ref/source/l_view.cc
index cd518aea01..259b74b58a 100644
--- a/crawl-ref/source/l_view.cc
+++ b/crawl-ref/source/l_view.cc
@@ -61,10 +61,38 @@ LUAFN(view_is_safe_square)
return (1);
}
+LUAFN(view_can_reach)
+{
+ COORDSHOW(s, 1, 2)
+ const int x_distance = abs(s.x);
+ const int y_distance = abs(s.y);
+ if (x_distance > 2 || y_distance > 2)
+ {
+ PLUARET(boolean, false);
+ return (1);
+ }
+ if (x_distance < 2 && y_distance < 2)
+ {
+ PLUARET(boolean, true);
+ return (1);
+ }
+ const coord_def first_middle(s.x/2,s.y/2);
+ const coord_def second_middle(s.x - s.x/2, s.y - s.y/2);
+ if (!feat_is_reachable_past(grd(player2grid(first_middle)))
+ && !feat_is_reachable_past(grd(player2grid(second_middle))))
+ {
+ PLUARET(boolean, false);
+ return (1);
+ }
+ PLUARET(boolean, true);
+ return (1);
+}
+
static const struct luaL_reg view_lib[] =
{
{ "feature_at", view_feature_at },
{ "is_safe_square", view_is_safe_square },
+ { "can_reach", view_can_reach },
{ NULL, NULL }
};
diff --git a/crawl-ref/source/l_you.cc b/crawl-ref/source/l_you.cc
index 60ec14eb16..845b6e414a 100644
--- a/crawl-ref/source/l_you.cc
+++ b/crawl-ref/source/l_you.cc
@@ -127,7 +127,6 @@ LUARET1(you_confused, boolean, you.confused())
LUARET1(you_shrouded, boolean, you.duration[DUR_SHROUD_OF_GOLUBRIA])
LUARET1(you_swift, boolean, you.duration[DUR_SWIFTNESS])
LUARET1(you_paralysed, boolean, you.paralysed())
-LUARET1(you_caught, boolean, you.caught())
LUARET1(you_asleep, boolean, you.asleep())
LUARET1(you_hasted, boolean, you.duration[DUR_HASTE])
LUARET1(you_slowed, boolean, you.duration[DUR_SLOW])
@@ -169,6 +168,8 @@ LUARET1(you_see_cell_no_trans_rel, boolean,
LUARET1(you_piety_rank, number, piety_rank(you.piety) - 1)
LUARET1(you_max_burden, number, carrying_capacity(BS_UNENCUMBERED))
LUARET1(you_burden, number, you.burden)
+LUARET1(you_constricted, boolean, you.is_constricted())
+LUARET1(you_constricting, boolean, you.is_constricting())
static int l_you_genus(lua_State *ls)
{
@@ -264,6 +265,16 @@ static int you_can_consume_corpses(lua_State *ls)
return (1);
}
+LUAFN(you_caught)
+{
+ if (you.caught())
+ lua_pushstring(ls, held_status(&you));
+ else
+ lua_pushnil(ls);
+
+ return (1);
+}
+
LUAFN(you_mutation)
{
std::string mutname = luaL_checkstring(ls, 1);
@@ -367,6 +378,8 @@ static const struct luaL_reg you_clib[] =
{ "piety_rank", you_piety_rank },
{ "max_burden", you_max_burden },
{ "burden", you_burden },
+ { "constricted", you_constricted },
+ { "constricting", you_constricting },
{ "god_likes_fresh_corpses", you_god_likes_fresh_corpses },
{ "can_consume_corpses", you_can_consume_corpses },
diff --git a/crawl-ref/source/lang-fake.cc b/crawl-ref/source/lang-fake.cc
new file mode 100644
index 0000000000..a06012aac9
--- /dev/null
+++ b/crawl-ref/source/lang-fake.cc
@@ -0,0 +1,381 @@
+/**
+ * @file
+ * @brief Translation filters.
+ **/
+
+#include "AppHdr.h"
+#include "lang-fake.h"
+
+#include "debug.h"
+#include "libutil.h"
+#include "options.h"
+#include "unicode.h"
+
+#define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define LOWER "abcdefghijklmnopqrstuvwxyz"
+#define LETTERS UPPER LOWER
+
+
+// Any resemblance to the speech of a particular character from Rich Burlew's
+// work is entirely accidental. Suggestion that this table has been produced
+// by transcribing the whole corpus of that character's speech and making it
+// produce the same output from regular English must be dismissed as a rumour.
+
+// For Perl version, "apt-get install filters".
+static const char* dwarven[][4] =
+{
+ {"^yes$","aye"}, {"there","thar"}, {"eir$","ar"},
+ {"about","aboot"}, {"^he$","'e"}, {"them","'em"},
+ {"^him","'im"}, {"out of$","outta"}, {"of course","'course"},
+ {"^of$","o'"}, {"^and$","an'"}, {"to$","ta"},
+ {"tog","tag"}, {"that","tha"}, {"the","tha"},
+ {"wouldn't","wouldn'ta"}, {"cannot","cannae"}, {"can't","cannae"},
+ {"don't","dinnae"}, {"'re$","r"}, {"for$","fer"},
+ {"ver$","'er"}, {"ber$","b'r"}, {"every$","ev'ry"},
+ {"^is$","be"},
+ {"en$","'n"}, {"^if$","if'n"}, {"enl","'nl"},
+ {"eng","'ng"}, {"ing","in'"}, {"ment","mn't"},
+ {"^es","'s"}, {"^ex","'s"}, {"^not$","na"},
+ {"^no$","nay"}, {"n't have","n'tve"},
+ {"^are$","be"}, {"have","haf"}, {"abl","'bl"},
+ {"^you$","ye"}, {"^your","yer"}, {"^you'","ye'"},
+ {"noth","nuth"}, {"^this$","'tis"}, {"^here","'ere"},
+ {"doesn't","don't"}, {"at a$","atta"}, {"ith$","it'"},
+ {"ered$","'red"}, {"into$","inta"}, {"^before","'fore"},
+ {"wit' '","wit '"}, {"wit' t","wit t"}, {"wit' w","wit w"},
+ {"wit' y","wit y"}, {"get a","git a"}, {"ally$","'lly"},
+ {"^my","me"}, {"^i think$","methinks"}, {"nay w","na w"},
+ {"^one$","'un"}, {"^'un a","one a"}, {"at ta$","atta"},
+ {"ot ta$","otta"}, {"^isn't$","ain't"}, {"^so th","s'th"},
+ {"ned$","n'd"}, {"^because","'cause"},
+ {0}
+};
+
+// Resemblances to the manner of speech of Jägermonsters from "Girl Genius" by
+// Phil and Kaja Foglio are... hrm dammit, using the proper name gives it out.
+// And s/dammit/gotterdammerung/.
+static const char* jager[][4] =
+{
+ {"this","dis"},
+ {"that","dat"},
+ {"they","dey"},
+ {"their","der"},
+ {"there","dere"},
+ {"these","dese"},
+ {"those","doze"},
+ {"the$","de"},
+ {"then","den"},
+ {"them","dem"},
+ {"yes","yah"},
+ {"you","hyu"},
+ {"hyur","you"},
+ {"have","hef"},
+ {"wh","v"},
+ {"^w","v"},
+ {"w","v", "o"},
+ {"^ha","he"},
+ {"ha","he", "c"},
+ {"any","henny"},
+ {"smart","schmot"},
+ {"n't","n'"},
+ {"ain'","hain't"},
+ {"am not","hain't"},
+ {"isn'","hain't"},
+ {"is not","hain't"},
+ {"aren'","hain't"},
+ {"are not","haint't"},
+ {"good","goot"},
+ {"dad","papa"},
+ {"stuff","stoff"},
+ {"going to","gunna"},
+ {"going","gun"},
+ {"people","pipple"},
+ {"little","liddle"},
+ {"love","luv"},
+ {"nice","nize"},
+ {"bug","bog"},
+ {"let me","lemme"},
+ {"give me","gimmee"},
+ {"castle","kestle"},
+ {"clank","klenk"},
+ {"better","betta"},
+ {"darling","dollink"},
+ {"some","zum"},
+ {"ouble","ubbel"},
+ {"bble","bbel"},
+ {"exc","eks"},
+ {"ex","eks"},
+ {"accident","exident"},
+ {"once","vunce"},
+ {"id$","eed"},
+ {"^one","vun"},
+ {"kiss","kees"},
+ {"^c","k", 0, "h"},
+ {"am$","em"},
+ {"^th","t"},
+ {"th","dd", "!"LETTERS, "!"LETTERS},
+ {"unix","yoonix"},
+ {"^un","on"},
+ {"^sh","sch", 0, "e"},
+ {"^sl","schl"},
+ {"^sm","schm"},
+ {"^sn","schn"},
+ {"^sp","schp"},
+ {"^st","scht"},
+ {"of","uf"},
+ {"qu","qv"},
+ {"ing","ink"},
+ {"irl","url"},
+ {"ish","eesh"},
+ {"^i$","hy"},
+ {"ve$","ff", "!"LETTERS},
+ {"ect$","eck"},
+ {"and","und"},
+ {"^all","hall"},
+ {"mister","herr"},
+ {"mr.","herr"},
+ {"^is$","iz"},
+ {"god damn it","gotterdammerung"},
+ {"goddammit","gotterdammerung"},
+ {"goddamnit","gotterdammerung"},
+ {"damn it","gotterdammerung"},
+ {"goddam","gotterdammerung"},
+ {"god damn","gotterdammerung"},
+ {"god damn it","gotterdammerung"},
+ {"damn","dem"},
+ {"god","gott"},
+ {"okay","hokay"},
+ {"^ok$","hokay"},
+ {"just","chust"},
+ {0}
+};
+
+static const char* lisp[][4] =
+{
+ {"s", "th"},
+ {0}
+};
+
+static void _replace_cap_variants(std::string &str,
+ std::string a,
+ std::string b,
+ const char* not_after = 0,
+ const char* not_before = 0)
+{
+ ASSERT(!a.empty());
+ if (a[0] == '^')
+ {
+ a.erase(0, 1);
+ ASSERT(!not_after);
+ not_after = LETTERS;
+ }
+
+ ASSERT(!a.empty());
+ if (a[a.length() - 1] == '$')
+ {
+ a.erase(a.length() - 1);
+ ASSERT(!not_before);
+ not_before = LETTERS;
+ }
+
+ ASSERT(!a.empty());
+
+ bool yes_after = false;
+ if (not_after && *not_after == '!')
+ yes_after = true, not_after++;
+
+ bool yes_before = false;
+ if (not_before && *not_before == '!')
+ yes_before = true, not_before++;
+
+ for (int captype = 0; captype < 3; captype++)
+ {
+ std::string A;
+ switch (captype)
+ {
+ case 0: A = lowercase(a); break;
+ case 1: A = uppercase_first(a); break;
+ case 2: A = uppercase(a); break;
+ default: die("lolwut?");
+ }
+
+ size_t pos = 0;
+ while ((pos = str.find(A, pos)) != std::string::npos)
+ {
+ if (not_after && pos > 0
+ && (yes_after == !strchr(not_after, str[pos - 1])))
+ {
+ pos++;
+ continue;
+ }
+
+ size_t epos = pos + A.length();
+ if (not_before && epos < str.length()
+ && (yes_before == !strchr(not_before, str[epos])))
+ {
+ pos++;
+ continue;
+ }
+
+ std::string B;
+ switch (captype)
+ {
+ case 0: B = lowercase(b); break;
+ case 1: B = uppercase_first(b); break;
+ case 2: B = uppercase(b); break;
+ default: die("lolwut?");
+ }
+
+ str.erase(pos, A.length());
+ str.insert(pos, B);
+ pos += B.length();
+ }
+ }
+}
+
+static void _german(std::string &txt)
+{
+ /*
+ The European Commission has just announced an agreement whereby English will
+ be the official language of the European Union rather than German, which was
+ the other possibility.
+
+ As part of the negotiations with the Germans, the British Government
+ conceded that English spelling had some room for improvement and has
+ accepted a 5-year phase-in plan that would become known as "Euro-English".
+
+ In the first year, "s" will replace the soft "c". Sertainly, this will make
+ the sivil servants jump with joy.
+
+ The hard "c" will be dropped in favour of "k". This should klear up
+ konfusion, and keyboards kan have one less letter.
+ */
+ for (unsigned int i = 0; i < txt.length(); i++)
+ if (txt[i] == 'c' || txt[i] == 'C')
+ switch (tolower(txt[i+1]))
+ {
+ case 'h': case 'z':
+ break;
+ case 'e': case 'i': case 'y':
+ txt[i] = isalower(txt[i]) ? 's' : 'S';
+ break;
+ default:
+ txt[i] = isalower(txt[i]) ? 'k' : 'K';
+ }
+ /*
+ There will be growing publik enthusiasm in the sekond year when the
+ troublesome "ph" will be replaced with "f". This will make words like
+ fotograf 20% shorter.
+ */
+ _replace_cap_variants(txt, "ph", "f");
+ /*
+ In the 3rd year, publik akseptanse of the new spelling kan be expekted to
+ reach the stage where more komplikated changes are possible.
+
+ Governments will enkourage the removal of double letters which have always
+ ben a deterent to akurate speling.
+ */
+ for (int i = txt.length() - 2; i > 0; i--)
+ if (txt[i] == txt[i + 1])
+ txt.erase(i, 1);
+ /*
+ Also, al wil agre that the horibl mes of the silent "e" in the languag is
+ disgrasful and it should go away.
+ */
+ for (int i = txt.length() - 2; i > 0; i--)
+ if (txt[i]=='e' || txt[i]=='E')
+ {
+ if (i < 3)
+ continue;
+ if (isaalpha(txt[i + 1]))
+ continue;
+ if (txt[i-1]=='e' || txt[i-1]=='E')
+ continue;
+ if (!isaalpha(txt[i-1])
+ || !isaalpha(txt[i-2])
+ || !isaalpha(txt[i-3]))
+ continue;
+ txt.erase(i, 1);
+ }
+ /*
+ By the 4th yer people wil be reseptiv to steps such as replasing "th" with
+ "z" and "w" with "v".
+ */
+ _replace_cap_variants(txt, "th", "z");
+ _replace_cap_variants(txt, "w", "v");
+ /*
+ During ze fifz yer, ze unesesary "o" kan be dropd from vords containing "ou"
+ and after ziz fifz yer, ve vil hav a reil sensibl riten styl.
+ */
+ _replace_cap_variants(txt, "ou", "u");
+ /*
+ Zer vil be no mor trubl or difikultis and evrivun vil find it ezi tu
+ understand ech oza. Ze drem of a united urop vil finali kum tru.
+
+ Und efter ze fifz yer, ve vil al be speking German like zey vunted in ze
+ forst plas.
+ */
+ // TODO :p
+}
+
+static const char* german[][4] =
+{
+ {"sh", "sch"},
+ {"^is$", "ist"},
+ {"an$", "ann"},
+ {"^and$", "und"},
+ {"^one$", "ein"},
+ {0}
+};
+
+static void _wide(std::string &txt)
+{
+ std::string out;
+
+ for (size_t i = 0; i < txt.length(); i++)
+ {
+ if (txt[i] == ' ')
+ out += " "; // U+3000 rather than U+FF00
+ else if (txt[i] > 32 && txt[i] < 127)
+ {
+ char buf[4];
+ int r = wctoutf8(buf, txt[i] + 0xFF00 - 32);
+ for (int j = 0; j < r; j++)
+ out.push_back(buf[j]);
+ }
+ else
+ out.push_back(txt[i]);
+ }
+
+ txt = out;
+}
+
+void filter_lang(std::string &str)
+{
+ if (!Options.lang)
+ return;
+
+ const char* (*repl)[4];
+
+ if (!strcmp(Options.lang, "dwarven"))
+ repl = dwarven;
+ else if (!strcmp(Options.lang, "jägerkin"))
+ repl = jager;
+ else if (!strcmp(Options.lang, "lisp"))
+ repl = lisp;
+ else if (!strcmp(Options.lang, "de"))
+ _german(str), repl = german;
+ else if (!strcmp(Options.lang, "wide"))
+ return _wide(str);
+ else
+ return;
+
+ for (; **repl; repl++)
+ _replace_cap_variants(str, (*repl)[0], (*repl)[1], (*repl)[2], (*repl)[3]);
+}
+
+std::string filtered_lang(std::string str)
+{
+ filter_lang(str);
+ return str;
+}
diff --git a/crawl-ref/source/lang-fake.h b/crawl-ref/source/lang-fake.h
new file mode 100644
index 0000000000..75d99b8d07
--- /dev/null
+++ b/crawl-ref/source/lang-fake.h
@@ -0,0 +1,2 @@
+void filter_lang(std::string &str);
+std::string filtered_lang(std::string str);
diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc
index 6c1cd5b99e..b70cb58a2e 100644
--- a/crawl-ref/source/libutil.cc
+++ b/crawl-ref/source/libutil.cc
@@ -731,8 +731,26 @@ std::vector<std::string> split_string(const std::string &sep,
return segments;
}
+static const std::string _get_indent(const std::string &s)
+{
+ if (starts_with(s, "\"") // ASCII quotes
+ || starts_with(s, "“") // English quotes
+ || starts_with(s, "„") // Polish/German/... quotes
+ || starts_with(s, "«")) // French quotes
+ {
+ return " ";
+ }
+ if (starts_with(s, "「")) // Chinese/Japanese quotes
+ return " ";
+
+ size_t nspaces = s.find_first_not_of(' ');
+ if (nspaces == std::string::npos)
+ return "";
+ return s.substr(0, nspaces);
+}
+
// The provided string is consumed!
-std::string wordwrap_line(std::string &s, int width, bool tags)
+std::string wordwrap_line(std::string &s, int width, bool tags, bool indent)
{
const char *cp0 = s.c_str();
const char *cp = cp0, *space = 0;
@@ -795,6 +813,8 @@ std::string wordwrap_line(std::string &s, int width, bool tags)
cp = space;
const std::string ret = s.substr(0, cp - cp0);
+ const std::string indentation = (indent && c != '\n') ? _get_indent(s) : "";
+
// eat all trailing spaces and up to one newline
while (*cp == ' ')
cp++;
@@ -802,6 +822,10 @@ std::string wordwrap_line(std::string &s, int width, bool tags)
cp++;
s.erase(0, cp - cp0);
+ // if we had to break a line, reinsert the indendation
+ if (indent && c != '\n')
+ s = indentation + s;
+
return ret;
}
diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h
index 96e596f95a..44bf5e2688 100644
--- a/crawl-ref/source/libutil.h
+++ b/crawl-ref/source/libutil.h
@@ -78,7 +78,8 @@ int strwidth(const char *s);
int strwidth(const std::string &s);
std::string chop_string(const char *s, int width, bool spaces = true);
std::string chop_string(const std::string &s, int width, bool spaces = true);
-std::string wordwrap_line(std::string &s, int cols, bool tags = false);
+std::string wordwrap_line(std::string &s, int cols, bool tags = false,
+ bool indent = false);
bool version_is_stable(const char *ver);
@@ -178,6 +179,14 @@ std::string comma_separated_line(Z start, Z end,
std::string unwrap_desc(std::string desc);
+template <typename Z>
+void erase_any(std::vector<Z> &vec, unsigned long which)
+{
+ if (which != vec.size() - 1)
+ vec[which] = vec[vec.size() - 1];
+ vec.pop_back();
+}
+
inline int sqr(int x)
{
return x * x;
diff --git a/crawl-ref/source/libw32c.cc b/crawl-ref/source/libw32c.cc
index b7ae78f250..18ac42536d 100644
--- a/crawl-ref/source/libw32c.cc
+++ b/crawl-ref/source/libw32c.cc
@@ -617,10 +617,14 @@ void putwch(ucs_t c)
#define VKEY_MAPPINGS 11
static int vk_tr[4][VKEY_MAPPINGS] = // virtual key, unmodified, shifted, control
{
- { VK_END, VK_DOWN, VK_NEXT, VK_LEFT, VK_CLEAR, VK_RIGHT, VK_HOME, VK_UP, VK_PRIOR, VK_INSERT, VK_TAB },
- { CK_END, CK_DOWN, CK_PGDN, CK_LEFT, CK_CLEAR, CK_RIGHT, CK_HOME, CK_UP, CK_PGUP , CK_INSERT, CONTROL('I') },
- { CK_SHIFT_END, CK_SHIFT_DOWN, CK_SHIFT_PGDN, CK_SHIFT_LEFT, CK_SHIFT_CLEAR, CK_SHIFT_RIGHT, CK_SHIFT_HOME, CK_SHIFT_UP, CK_SHIFT_PGUP, CK_SHIFT_INSERT, CK_SHIFT_TAB },
- { CK_CTRL_END, CK_CTRL_DOWN, CK_CTRL_PGDN, CK_CTRL_LEFT, CK_CTRL_CLEAR, CK_CTRL_RIGHT, CK_CTRL_HOME, CK_CTRL_UP, CK_CTRL_PGUP, CK_CTRL_INSERT, CK_CTRL_TAB },
+ { VK_END, VK_DOWN, VK_NEXT, VK_LEFT, VK_CLEAR, VK_RIGHT,
+ VK_HOME, VK_UP, VK_PRIOR, VK_INSERT, VK_TAB },
+ { CK_END, CK_DOWN, CK_PGDN, CK_LEFT, CK_CLEAR, CK_RIGHT,
+ CK_HOME, CK_UP, CK_PGUP , CK_INSERT, CONTROL('I') },
+ { CK_SHIFT_END, CK_SHIFT_DOWN, CK_SHIFT_PGDN, CK_SHIFT_LEFT, CK_SHIFT_CLEAR, CK_SHIFT_RIGHT,
+ CK_SHIFT_HOME, CK_SHIFT_UP, CK_SHIFT_PGUP, CK_SHIFT_INSERT, CK_SHIFT_TAB },
+ { CK_CTRL_END, CK_CTRL_DOWN, CK_CTRL_PGDN, CK_CTRL_LEFT, CK_CTRL_CLEAR, CK_CTRL_RIGHT,
+ CK_CTRL_HOME, CK_CTRL_UP, CK_CTRL_PGUP, CK_CTRL_INSERT, CK_CTRL_TAB },
};
static int ck_tr[] =
diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc
index 6faebe1540..08f5b10d8d 100644
--- a/crawl-ref/source/main.cc
+++ b/crawl-ref/source/main.cc
@@ -606,7 +606,7 @@ static void _do_wizard_command(int wiz_command, bool silent_fail)
case CONTROL('B'): you.teleport(true, false, true); break;
case CONTROL('D'): wizard_edit_durations(); break;
case CONTROL('E'): debug_dump_levgen(); break;
- case CONTROL('F'): debug_fight_statistics(false, true); break;
+ case CONTROL('F'): wizard_fight_sim(true); break;
#ifdef DEBUG_BONES
case CONTROL('G'): debug_ghosts(); break;
#endif
@@ -642,8 +642,8 @@ static void _do_wizard_command(int wiz_command, bool silent_fail)
case 't': wizard_tweak_object(); break;
case 'T': debug_make_trap(); break;
case '\\': debug_make_shop(); break;
- case 'f': debug_fight_statistics(false); break;
- case 'F': debug_fight_statistics(true); break;
+ case 'f': wizard_quick_fsim(); break;
+ case 'F': wizard_fight_sim(false); break;
case 'm': wizard_create_spec_monster(); break;
case 'M': wizard_create_spec_monster_name(); break;
case 'R': wizard_spawn_control(); break;
@@ -1223,12 +1223,16 @@ static void _input()
{
clear_macro_process_key_delay();
+ // At this point we are guaranteed to not be in any recursion, so the
+ // Lua stack must be empty. Unless there's a leak.
+ ASSERT(lua_gettop(clua.state()) == 0);
+
if (!has_pending_input() && !kbhit())
{
if (++crawl_state.lua_calls_no_turn > 1000)
mprf(MSGCH_ERROR, "Infinite lua loop detected, aborting.");
else
- clua.callfn("ready", 0);
+ clua.callfn("ready", 0, 0);
}
// We're not in an infinite loop, reset the timer.
@@ -1347,11 +1351,15 @@ static bool _prompt_dangerous_portal(dungeon_feature_type ftype)
static bool _prompt_unique_pan_rune(dungeon_feature_type ygrd)
{
- if (ygrd != DNGN_TRANSIT_PANDEMONIUM && ygrd != DNGN_EXIT_PANDEMONIUM)
+ if (ygrd != DNGN_TRANSIT_PANDEMONIUM
+ && ygrd != DNGN_EXIT_PANDEMONIUM
+ && ygrd != DNGN_ENTER_ABYSS)
+ {
return true;
+ }
+
item_def* rune = find_floor_item(OBJ_MISCELLANY, MISC_RUNE_OF_ZOT);
- if (rune && (rune->plus == RUNE_CEREBOV || rune->plus == RUNE_LOM_LOBON
- || rune->plus == RUNE_MNOLEG || rune->plus == RUNE_GLOORX_VLOQ))
+ if (rune && item_is_unique_rune(*rune))
{
return yesno("An item of great power still resides in this realm, "
"and once you leave you can never return. "
@@ -1442,15 +1450,8 @@ static void _go_upstairs()
" This will make you lose the game!");
if (player_has_orb())
stay = !yesno("Are you sure you want to win?");
- else if (yesno(prompt.c_str(), false, 'n'))
- {
- // You did pick up the Orb but are not carrying it, this deserves
- // another warning due to automatism.
- if (you.char_direction == GDT_ASCENDING)
- stay = !yes_or_no("You're not carrying the Orb! Leave anyway");
- else
- stay = false;
- }
+ else
+ stay = !yesno(prompt.c_str(), false, 'n');
if (stay)
{
@@ -2273,7 +2274,7 @@ static void _decrement_durations()
{
int delay = you.time_taken;
- if (wearing_amulet(AMU_THE_GOURMAND))
+ if (player_effect_gourmand())
{
if (you.duration[DUR_GOURMAND] < GOURMAND_MAX && coinflip())
you.duration[DUR_GOURMAND] += delay;
@@ -2530,7 +2531,6 @@ static void _decrement_durations()
you.attribute[ATTR_DIVINE_DEATH_CHANNEL] = 0;
}
- _decrement_a_duration(DUR_SAGE, delay, "You feel less studious.");
_decrement_a_duration(DUR_STEALTH, delay, "You feel less stealthy.");
_decrement_a_duration(DUR_SLAYING, delay, "You feel less lethal.");
@@ -2890,7 +2890,7 @@ static void _regenerate_hp_and_mp(int delay)
// is only an unsigned char and is thus likely to overflow. -- bwr
int tmp = you.hit_points_regeneration;
- if (you.hp < you.hp_max && !you.disease && !you.duration[DUR_DEATHS_DOOR])
+ if (you.hp < you.hp_max && !you.duration[DUR_DEATHS_DOOR])
{
const int base_val = player_regen();
tmp += div_rand_round(base_val * delay, BASELINE_DELAY);
@@ -3070,6 +3070,10 @@ static void _player_reacts()
seen_monsters_react();
update_stat_zero();
+
+ // XOM now ticks from here, to increase his reaction time to tension.
+ if (you.religion == GOD_XOM)
+ xom_tick();
}
// Ran after monsters and clouds get to act.
@@ -3405,7 +3409,7 @@ static bool _untrap_target(const coord_def move, bool check_confused)
if (mon && player_can_hit_monster(mon))
{
if (mon->caught() && mon->friendly()
- && player_can_open_doors() && !you.confused())
+ && player_can_handle_equipment() && !you.confused())
{
const std::string prompt =
make_stringf("Do you want to try to take the net off %s?",
@@ -3431,7 +3435,7 @@ static bool _untrap_target(const coord_def move, bool check_confused)
{
if (!you.confused())
{
- if (!player_can_open_doors())
+ if (!player_can_handle_equipment())
{
mpr("You can't disarm traps in your present form.");
return (true);
@@ -4357,7 +4361,7 @@ static void _move_player(coord_def move)
apply_berserk_penalty = !attacking;
if (!attacking && you.religion == GOD_CHEIBRIADOS && one_chance_in(10)
- && player_equip_ego_type(EQ_BOOTS, SPARM_RUNNING))
+ && player_effect_running())
{
did_god_conduct(DID_HASTY, 1, true);
}
diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc
index 706593bc0e..fb3e59bcc5 100644
--- a/crawl-ref/source/makeitem.cc
+++ b/crawl-ref/source/makeitem.cc
@@ -2269,17 +2269,22 @@ bool is_armour_brand_ok(int type, int brand, bool strict)
case SPARM_LEVITATION:
if (slot == EQ_BODY_ARMOUR)
return (true);
+ // deliberate fall-through
case SPARM_RUNNING:
case SPARM_STEALTH:
return (slot == EQ_BOOTS);
case SPARM_ARCHMAGI:
- return (type == ARM_ROBE);
+ return (strict ? (type == ARM_ROBE)
+ : (slot == EQ_BODY_ARMOUR));
case SPARM_PONDEROUSNESS:
return (true);
case SPARM_PRESERVATION:
+ if (type == ARM_PLATE_ARMOUR && !strict)
+ return (true);
+ // deliberate fall-through
case SPARM_DARKNESS:
return (slot == EQ_CLOAK);
@@ -2287,9 +2292,12 @@ bool is_armour_brand_ok(int type, int brand, bool strict)
case SPARM_PROTECTION:
return (slot == EQ_SHIELD);
- case SPARM_ARCHERY:
case SPARM_STRENGTH:
case SPARM_DEXTERITY:
+ if (!strict)
+ return true;
+ // deliberate fall-through
+ case SPARM_ARCHERY:
return (slot == EQ_GLOVES);
case SPARM_SEE_INVISIBLE:
@@ -2310,15 +2318,17 @@ bool is_armour_brand_ok(int type, int brand, bool strict)
case SPARM_MAGIC_RESISTANCE:
if (type == ARM_WIZARD_HAT)
return (true);
+ // deliberate fall-through
case SPARM_POISON_RESISTANCE:
case SPARM_POSITIVE_ENERGY:
if (type == ARM_PEARL_DRAGON_ARMOUR && brand == SPARM_POSITIVE_ENERGY)
return (false); // contradictory or redundant
- return (slot == EQ_BODY_ARMOUR || slot == EQ_SHIELD || slot == EQ_CLOAK);
+ return (slot == EQ_BODY_ARMOUR || slot == EQ_SHIELD || slot == EQ_CLOAK
+ || !strict);
case SPARM_SPIRIT_SHIELD:
- return (type == ARM_CAP || slot == EQ_SHIELD);
+ return (type == ARM_CAP || slot == EQ_SHIELD || !strict);
case NUM_SPECIAL_ARMOURS:
die("invalid armour brand");
@@ -3421,17 +3431,6 @@ jewellery_type get_random_ring_type()
return (j);
}
-armour_type get_random_body_armour_type(int item_level)
-{
- for (int tries = 100; tries > 0; --tries)
- {
- const armour_type tr = _get_random_armour_type(item_level);
- if (get_armour_slot(tr) == EQ_BODY_ARMOUR)
- return (tr);
- }
- return (ARM_ROBE);
-}
-
// FIXME: Need to clean up this mess.
static armour_type _get_random_armour_type(int item_level)
{
diff --git a/crawl-ref/source/makeitem.h b/crawl-ref/source/makeitem.h
index e39565a1fe..f7ec81c1dd 100644
--- a/crawl-ref/source/makeitem.h
+++ b/crawl-ref/source/makeitem.h
@@ -32,7 +32,6 @@ void init_rod_mp(item_def &item, int ncharges = -1, int item_level = -1);
jewellery_type get_random_ring_type();
jewellery_type get_random_amulet_type();
-armour_type get_random_body_armour_type(int level);
stave_type get_random_rod_type();
void item_set_appearance(item_def &item);
void maybe_set_item_race(item_def &item, int allowed, int num_rolls = 1);
diff --git a/crawl-ref/source/map_knowledge.cc b/crawl-ref/source/map_knowledge.cc
index 606b2c2524..21d5cc47e4 100644
--- a/crawl-ref/source/map_knowledge.cc
+++ b/crawl-ref/source/map_knowledge.cc
@@ -66,7 +66,7 @@ int count_detected_mons()
return (count);
}
-void clear_map(bool clear_detected_items, bool clear_detected_monsters)
+void clear_map(bool clear_items, bool clear_mons)
{
for (rectangle_iterator ri(BOUNDARY_BORDER - 1); ri; ++ri)
{
@@ -77,11 +77,10 @@ void clear_map(bool clear_detected_items, bool clear_detected_monsters)
cell.clear_cloud();
- if (clear_detected_items || !cell.detected_item())
+ if (clear_items)
cell.clear_item();
- if ((clear_detected_monsters || !cell.detected_monster())
- && !mons_class_is_stationary(cell.monster()))
+ if (clear_mons && !mons_class_is_stationary(cell.monster()))
{
cell.clear_monster();
#ifdef USE_TILE
diff --git a/crawl-ref/source/map_knowledge.h b/crawl-ref/source/map_knowledge.h
index c0d7de4192..378c613433 100644
--- a/crawl-ref/source/map_knowledge.h
+++ b/crawl-ref/source/map_knowledge.h
@@ -320,7 +320,7 @@ void clear_terrain_visibility();
int count_detected_mons(void);
-void clear_map(bool clear_items = false, bool clear_mons = true);
+void clear_map(bool clear_items = true, bool clear_mons = true);
map_feature get_cell_map_feature(const map_cell& cell);
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index 1d234202ad..5f173a20b3 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -3746,13 +3746,16 @@ mons_list::mons_spec_slot mons_list::parse_mons_spec(std::string spec)
}
}
- std::string serpent_of_hell_flavour = strip_tag_prefix(mon_str, "serpent_of_hell_flavour:");
+ std::string serpent_of_hell_flavour =
+ strip_tag_prefix(mon_str, "serpent_of_hell_flavour:");
if (serpent_of_hell_flavour.empty())
serpent_of_hell_flavour = strip_tag_prefix(mon_str, "soh_flavour:");
if (!serpent_of_hell_flavour.empty())
{
- serpent_of_hell_flavour = uppercase_first(lowercase(serpent_of_hell_flavour)).substr(0, 3);
- mspec.props["serpent_of_hell_flavour"].get_int() = str_to_branch(serpent_of_hell_flavour, BRANCH_GEHENNA);
+ serpent_of_hell_flavour =
+ uppercase_first(lowercase(serpent_of_hell_flavour)).substr(0, 3);
+ mspec.props["serpent_of_hell_flavour"].get_int() =
+ str_to_branch(serpent_of_hell_flavour, BRANCH_GEHENNA);
}
std::string ench_str;
@@ -4384,7 +4387,7 @@ static int str_to_ego(item_spec &spec, std::string ego_str)
"archmagi",
"preservation",
"reflection",
- "spirit shield",
+ "spirit_shield",
"archery",
NULL
};
diff --git a/crawl-ref/source/mapmark.cc b/crawl-ref/source/mapmark.cc
index 4c48c95621..aa8cf1aa21 100644
--- a/crawl-ref/source/mapmark.cc
+++ b/crawl-ref/source/mapmark.cc
@@ -651,13 +651,15 @@ map_marker *map_malign_gateway_marker::read(reader &in, map_marker_type)
map_marker *map_malign_gateway_marker::clone() const
{
- map_malign_gateway_marker *mark = new map_malign_gateway_marker(pos, duration, is_player, summoner_string, behaviour, god, power);
+ map_malign_gateway_marker *mark = new map_malign_gateway_marker(pos,
+ duration, is_player, summoner_string, behaviour, god, power);
return (mark);
}
std::string map_malign_gateway_marker::debug_describe() const
{
- return make_stringf("Malign gateway (%d, %s)", duration, is_player ? "player" : "monster");
+ return make_stringf("Malign gateway (%d, %s)", duration,
+ is_player ? "player" : "monster");
}
//////////////////////////////////////////////////////////////////////////
diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc
index b91a5b0727..01141ccfb1 100644
--- a/crawl-ref/source/maps.cc
+++ b/crawl-ref/source/maps.cc
@@ -45,10 +45,14 @@ static map_section_type apply_vault_definition(
static bool resolve_map(map_def &def);
+static bool _map_safe_vault_place(const map_def &map,
+ const coord_def &c,
+ const coord_def &size);
+
// Globals: Use unwind_var to modify!
// Checks whether a map place is valid.
-map_place_check_t map_place_valid = map_safe_vault_place;
+map_place_check_t map_place_valid = _map_safe_vault_place;
// If non-empty, any floating vault's @ exit must land on these point.
point_vector map_anchor_points;
@@ -131,20 +135,20 @@ static map_section_type write_vault(map_def &mdef,
return (MAP_NONE);
}
-void dgn_flush_map_environments()
+static void _dgn_flush_map_environments()
{
// Clean up cached environments.
dlua.callfn("dgn_flush_map_environments", 0, 0);
}
-void dgn_flush_map_environment_for(const std::string &mapname)
+static void _dgn_flush_map_environment_for(const std::string &mapname)
{
dlua.callfn("dgn_flush_map_environment_for", "s", mapname.c_str());
}
static bool resolve_map_lua(map_def &map)
{
- dgn_flush_map_environment_for(map.name);
+ _dgn_flush_map_environment_for(map.name);
map.reinit();
std::string err = map.run_lua(true);
@@ -301,8 +305,10 @@ bool resolve_subvault(map_def &map)
return (true);
}
-void fit_region_into_map_bounds(coord_def &pos, const coord_def &size,
- int margin)
+// Given a rectangular region, slides it to fit into the map. size must be
+// smaller than (GXM,GYM).
+static void _fit_region_into_map_bounds(coord_def &pos, const coord_def &size,
+ int margin)
{
const int X_1(X_BOUND_1 + margin);
const int X_2(X_BOUND_2 - margin);
@@ -359,9 +365,9 @@ static bool _may_overwrite_feature(const coord_def p,
return (true);
}
-bool map_safe_vault_place(const map_def &map,
- const coord_def &c,
- const coord_def &size)
+static bool _map_safe_vault_place(const map_def &map,
+ const coord_def &c,
+ const coord_def &size)
{
if (size.zero())
return (true);
@@ -508,13 +514,13 @@ static bool apply_vault_grid(map_def &def,
if (map_bounds(place.pos))
{
start = place.pos - size / 2;
- fit_region_into_map_bounds(start, size, minivault ? MAPGEN_BORDER : 0);
+ _fit_region_into_map_bounds(start, size, minivault ? MAPGEN_BORDER : 0);
}
else if (minivault)
{
start = _find_minivault_place(place, check_place);
if (map_bounds(start))
- fit_region_into_map_bounds(start, size, MAPGEN_BORDER);
+ _fit_region_into_map_bounds(start, size, MAPGEN_BORDER);
}
else
start = def.float_place();
@@ -1065,7 +1071,7 @@ static std::set<std::string> map_files_read;
extern int yylineno;
-void reset_map_parser()
+static void _reset_map_parser()
{
lc_map.init();
lc_range.reset();
@@ -1301,7 +1307,7 @@ static void parse_maps(const std::string &s)
#endif
time_t mtime = file_modtime(dat);
- reset_map_parser();
+ _reset_map_parser();
extern int yyparse(void);
extern FILE *yyin;
@@ -1319,7 +1325,7 @@ static void parse_maps(const std::string &s)
void read_map(const std::string &file)
{
parse_maps(lc_desfile = datafile_path(file));
- dgn_flush_map_environments();
+ _dgn_flush_map_environments();
// Force GC to prevent heap from swelling unnecessarily.
dlua.gc();
}
@@ -1330,7 +1336,8 @@ void read_maps()
end(1, false, "Lua error: %s", dlua.error.c_str());
lc_loaded_maps.clear();
- sanity_check_maps();
+
+ dlua.execfile("dlua/sanity.lua", true, true);
}
// If a .dsc file has been changed under the running Crawl, discard
@@ -1396,11 +1403,6 @@ const map_def *map_by_index(int index)
return (&vdefs[index]);
}
-void sanity_check_maps()
-{
- dlua.execfile("dlua/sanity.lua", true, true);
-}
-
///////////////////////////////////////////////////////////////////////////
// Debugging code
diff --git a/crawl-ref/source/maps.h b/crawl-ref/source/maps.h
index ac678988c4..6947c61db5 100644
--- a/crawl-ref/source/maps.h
+++ b/crawl-ref/source/maps.h
@@ -19,20 +19,11 @@ struct vault_placement;
typedef std::vector<map_def> map_vector;
typedef std::vector<const map_def *> mapref_vector;
-bool map_safe_vault_place(const map_def &md,
- const coord_def &c,
- const coord_def &size);
-
map_section_type vault_main(vault_placement &vp, const map_def *vault,
bool check_place = false);
bool resolve_subvault(map_def &vault);
-// Given a rectangular region, slides it to fit into the map. size must be
-// smaller than (GXM,GYM).
-void fit_region_into_map_bounds(coord_def &pos, const coord_def &size,
- int margin = 0);
-
const map_def *map_by_index(int index);
void strip_all_maps();
int map_count();
@@ -60,11 +51,9 @@ int weight_map_vector (std::vector<map_def> maps);
void read_maps();
void reread_maps();
-void sanity_check_maps();
void read_map(const std::string &file);
void run_map_global_preludes();
void run_map_local_preludes();
-void reset_map_parser();
std::string get_descache_path(const std::string &file,
const std::string &ext);
diff --git a/crawl-ref/source/melee_attack.cc b/crawl-ref/source/melee_attack.cc
index 991f548893..9f4290d734 100644
--- a/crawl-ref/source/melee_attack.cc
+++ b/crawl-ref/source/melee_attack.cc
@@ -99,7 +99,8 @@ melee_attack::melee_attack(actor *attk, actor *defn,
effective_attack_number(effective_attack_num),
skip_chaos_message(false), special_damage_flavour(BEAM_NONE),
stab_attempt(false), stab_bonus(0),
- miscast_level(-1), miscast_type(SPTYP_NONE), miscast_target(NULL)
+ miscast_level(-1), miscast_type(SPTYP_NONE), miscast_target(NULL),
+ simu(false)
{
attack_occurred = false;
weapon = attacker->weapon(attack_number);
@@ -236,6 +237,20 @@ bool melee_attack::handle_phase_attempted()
cancel_attack = true;
return (false);
}
+ else if (cell_is_solid(defender->pos())
+ && mons_wall_shielded(defender->as_monster())
+ && you.can_see(defender)
+ && !you.confused()
+ && !crawl_state.game_is_zotdef())
+ {
+ // Don't waste a turn hitting a rock worm when you know it
+ // will do nothing.
+ mprf("The %s protects %s from harm.",
+ raw_feature_description(grd(defender->pos())).c_str(),
+ defender->name(DESC_THE).c_str());
+ cancel_attack = true;
+ return (false);
+ }
}
// Set delay now that we know the attack won't be cancelled.
if (attacker->is_player())
@@ -256,43 +271,23 @@ bool melee_attack::handle_phase_attempted()
}
else
{
- // Initial attack causes energy to be used for all attacks. No
- // additional energy is used for unarmed attacks.
- if (effective_attack_number == 0)
- attacker->lose_energy(EUT_ATTACK);
+ // Only the first attack costs any energy.
+ if (!effective_attack_number)
+ {
+ int energy = attacker->as_monster()->action_energy(EUT_ATTACK);
+ int delay = calc_attack_delay();
+ dprf("Attack delay %d, multiplier %1.1f", delay, energy * 0.1);
+ ASSERT(energy > 0);
+ ASSERT(delay > 0);
+
+ attacker->as_monster()->speed_increment
+ -= div_rand_round(energy * delay, 10);
+ }
// Statues and other special monsters which have AT_NONE need to lose
// energy, but otherwise should exit the melee attack now.
if (attk_type == AT_NONE)
return (false);
-
- // Monsters lose additional energy only for the first two weapon
- // attacks; subsequent hits are free.
- if (effective_attack_number < 1)
- {
- final_attack_delay = calc_attack_delay();
- if (damage_brand == SPWPN_SPEED)
- final_attack_delay = final_attack_delay / 2 + 1;
-
- // speed adjustment for weapon-using monsters
- if (final_attack_delay > 0)
- {
- const int atk_speed =
- attacker->as_monster()->action_energy(EUT_ATTACK);
-
- // only get one third penalty/bonus for second weapons.
- if (effective_attack_number > 0)
- {
- final_attack_delay =
- div_rand_round((2 * atk_speed + final_attack_delay), 3);
- }
-
- int delta =
- div_rand_round((final_attack_delay - 10 + (atk_speed - 10)), 2);
- if (delta > 0)
- attacker->as_monster()->speed_increment -= delta;
- }
- }
}
if (attacker != defender)
@@ -451,7 +446,7 @@ bool melee_attack::handle_phase_dodged()
* Determines damage and passes off execution to handle_phase_damaged
* Also applies weapon brands
*
- * Returns (continue combat)
+ * Returns true if combat should continue, false if it should end here.
*/
bool melee_attack::handle_phase_hit()
{
@@ -496,7 +491,7 @@ bool melee_attack::handle_phase_hit()
bool stop_hit = false;
// Check if some hit-effect killed the monster. We muse
if (attacker->is_player())
- stop_hit = player_monattk_hit_effects();
+ stop_hit = !player_monattk_hit_effects();
// check_unrand_effects is safe to call with a dead defender, so always
// call it, even if the hit effects said to stop.
@@ -656,8 +651,12 @@ bool melee_attack::handle_phase_damaged()
if (defender->is_player())
practise(EX_MONSTER_WILL_HIT);
+ // decapitate_hydra() returns true if the wound was cauterized or the
+ // last head was removed. In the former case, we shouldn't apply
+ // the brand damage (so we return here). If the monster was killed
+ // by the decapitation, we should stop the rest of the attack, too.
if (decapitate_hydra(damage_done, attacker->damage_type(attack_number)))
- return (true);
+ return (defender->alive());
special_damage = 0;
special_damage_message.clear();
@@ -737,8 +736,10 @@ bool melee_attack::handle_phase_killed()
// to possibly be called twice. Adding another entry for a single
// artefact would be overkill, so here we call it by hand:
if (unrand_entry && weapon && weapon->special == UNRAND_WYRMBANE)
+ {
unrand_entry->fight_func.melee_effects(weapon, attacker, defender,
true, special_damage);
+ }
_defender_die();
return (true);
@@ -1169,7 +1170,7 @@ void melee_attack::player_aux_setup(unarmed_attack_type atk)
case UNAT_PUNCH:
aux_attack = aux_verb = "punch";
- aux_damage = 5 + you.skill_rdiv(SK_UNARMED_COMBAT, 1, 3);
+ aux_damage = 5 + you.skill_rdiv(SK_UNARMED_COMBAT, 1, 2);
if (you.form == TRAN_BLADE_HANDS)
{
@@ -1237,49 +1238,21 @@ void melee_attack::player_aux_setup(unarmed_attack_type atk)
/* Selects the unarmed attack type given by Unarmed Combat skill
*
- * Selects at random, but then takes into accout various combinations of player
- * species, transformations, and other stuff to determine whether the randomly
- * selected unarmed attack type is appropriate (eg, no kicking for octopodes...
- * who technically lack legs).
+ * Currently the only possibility is an offhand punch. Other auxes are linked
+ * directly to mutations and just depend on stats.
*/
unarmed_attack_type melee_attack::player_aux_choose_uc_attack()
{
- unarmed_attack_type uc_attack =
- random_choose(UNAT_HEADBUTT, UNAT_KICK, UNAT_PUNCH, UNAT_PUNCH,
- -1);
-
+ unarmed_attack_type uc_attack = coinflip() ? UNAT_PUNCH : UNAT_NO_ATTACK;
+ // Octopodes get more tentacle-slaps.
+ if (you.species == SP_OCTOPODE && coinflip())
+ uc_attack = UNAT_PUNCH;
// No punching with a shield or 2-handed wpn, except staves.
// Octopodes aren't affected by this, though!
if (you.species != SP_OCTOPODE && uc_attack == UNAT_PUNCH
&& !you.has_usable_offhand())
uc_attack = UNAT_NO_ATTACK;
- // With fangs, replace head attacks with bites.
- if ((you.has_usable_fangs() || player_mutation_level(MUT_ACIDIC_BITE))
- && uc_attack == UNAT_HEADBUTT)
- {
- uc_attack = UNAT_BITE;
- }
-
- // Felids turn kicks into bites.
- if (you.species == SP_FELID && uc_attack == UNAT_KICK)
- uc_attack = UNAT_BITE;
-
- // Nagas turn kicks into headbutts.
- if (you.species == SP_NAGA && uc_attack == UNAT_KICK)
- uc_attack = UNAT_HEADBUTT;
-
- // Octopodes turn kicks into punches.
- if (you.species == SP_OCTOPODE && uc_attack == UNAT_KICK
- && (!player_mutation_level(MUT_TENTACLE_SPIKE) || coinflip()))
- {
- uc_attack = UNAT_PUNCH;
- }
-
- // Octopodes turn headbutts into punches too.
- if (you.species == SP_OCTOPODE && uc_attack == UNAT_HEADBUTT)
- uc_attack = UNAT_PUNCH;
-
if (_tran_forbid_aux_attack(uc_attack))
uc_attack = UNAT_NO_ATTACK;
@@ -2052,7 +2025,13 @@ void melee_attack::player_weapon_upsets_god()
}
}
-// Returns true if the combat round should end here.
+/* Apply player-specific effects as well as brand damage.
+ *
+ * Called after damage is calculated, but before unrand effects and before
+ * damage is dealt.
+ *
+ * Returns true if combat should continue, false if it should end here.
+ */
bool melee_attack::player_monattk_hit_effects()
{
player_weapon_upsets_god();
@@ -2075,7 +2054,7 @@ bool melee_attack::player_monattk_hit_effects()
}
if (!defender->alive())
- return (true);
+ return (false);
// These effects apply only to monsters that are still alive:
@@ -2086,13 +2065,13 @@ bool melee_attack::player_monattk_hit_effects()
// Also returns true if the hydra's last head was cut off, in which
// case nothing more should be done to the hydra.
if (decapitate_hydra(damage_done))
- return (!defender->alive());
+ return (defender->alive());
// These two (staff damage and damage brand) are mutually exclusive!
apply_staff_damage();
if (!defender->alive())
- return (true);
+ return (false);
if (special_damage || special_damage_flavour)
{
@@ -2116,7 +2095,7 @@ bool melee_attack::player_monattk_hit_effects()
}
}
- return (false);
+ return (true);
}
void melee_attack::_defender_die()
@@ -2220,6 +2199,9 @@ bool melee_attack::distortion_affects_defender()
return (false);
}
+ if (simu)
+ return (false);
+
if (one_chance_in(3))
{
if (defender_visible)
@@ -3037,6 +3019,8 @@ bool melee_attack::apply_damage_brand()
|| !defender->is_player()
&& defender->as_monster()->is_summoned()
|| attacker->is_player() && you.duration[DUR_DEATHS_DOOR]
+ || !attacker->is_player()
+ && attacker->as_monster()->has_ench(ENCH_DEATHS_DOOR)
|| one_chance_in(5))
{
break;
@@ -3226,77 +3210,85 @@ bool melee_attack::chop_hydra_head(int dam,
if (attacker->is_monster() && !one_chance_in(4))
return (false);
- if ((dam_type == DVORP_SLICING || dam_type == DVORP_CHOPPING
- || dam_type == DVORP_CLAWING)
- && dam > 0
- && (dam >= 4 || wpn_brand == SPWPN_VORPAL || coinflip()))
+ // Only cutting implements.
+ if (dam_type != DVORP_SLICING && dam_type != DVORP_CHOPPING
+ && dam_type != DVORP_CLAWING || dam <= 0)
{
- const char *verb = NULL;
+ return false;
+ }
- if (dam_type == DVORP_CLAWING)
- {
- static const char *claw_verbs[] = { "rip", "tear", "claw" };
- verb = RANDOM_ELEMENT(claw_verbs);
- }
- else
+ if (dam < 4 && wpn_brand != SPWPN_VORPAL && coinflip())
+ return false;
+
+ // Small claws are not big enough.
+ if (dam_type == DVORP_CLAWING && attacker->has_claws() < 3)
+ return false;
+
+ const char *verb = NULL;
+
+ if (dam_type == DVORP_CLAWING)
+ {
+ static const char *claw_verbs[] = { "rip", "tear", "claw" };
+ verb = RANDOM_ELEMENT(claw_verbs);
+ }
+ else
+ {
+ static const char *slice_verbs[] =
{
- static const char *slice_verbs[] =
- {
- "slice", "lop", "chop", "hack"
- };
- verb = RANDOM_ELEMENT(slice_verbs);
- }
+ "slice", "lop", "chop", "hack"
+ };
+ verb = RANDOM_ELEMENT(slice_verbs);
+ }
- if (defender->as_monster()->number == 1) // will be zero afterwards
+ if (defender->as_monster()->number == 1) // will be zero afterwards
+ {
+ if (defender_visible)
{
- if (defender_visible)
- {
- mprf("%s %s %s's last head off!",
- atk_name(DESC_THE).c_str(),
- attacker->conj_verb(verb).c_str(),
- def_name(DESC_THE).c_str());
- }
- defender->as_monster()->number--;
+ mprf("%s %s %s's last head off!",
+ atk_name(DESC_THE).c_str(),
+ attacker->conj_verb(verb).c_str(),
+ def_name(DESC_THE).c_str());
+ }
+ defender->as_monster()->number--;
- if (!defender->is_summoned())
- bleed_onto_floor(defender->pos(), defender->type,
- defender->as_monster()->hit_points, true);
+ if (!defender->is_summoned())
+ bleed_onto_floor(defender->pos(), defender->type,
+ defender->as_monster()->hit_points, true);
- defender->hurt(attacker, INSTANT_DEATH);
+ defender->hurt(attacker, INSTANT_DEATH);
- return (true);
+ return (true);
+ }
+ else
+ {
+ if (defender_visible)
+ {
+ mprf("%s %s one of %s's heads off!",
+ atk_name(DESC_THE).c_str(),
+ attacker->conj_verb(verb).c_str(),
+ def_name(DESC_THE).c_str());
}
- else
+ defender->as_monster()->number--;
+
+ // Only living hydras get to regenerate heads.
+ if (defender->holiness() == MH_NATURAL)
{
- if (defender_visible)
+ unsigned int limit = 20;
+ if (defender->type == MONS_LERNAEAN_HYDRA)
+ limit = 27;
+
+ if (wpn_brand == SPWPN_FLAMING)
{
- mprf("%s %s one of %s's heads off!",
- atk_name(DESC_THE).c_str(),
- attacker->conj_verb(verb).c_str(),
- def_name(DESC_THE).c_str());
+ if (defender_visible)
+ mpr("The flame cauterises the wound!");
+ return (true);
}
- defender->as_monster()->number--;
-
- // Only living hydras get to regenerate heads.
- if (defender->holiness() == MH_NATURAL)
+ else if (defender->as_monster()->number < limit - 1)
{
- unsigned int limit = 20;
- if (defender->type == MONS_LERNAEAN_HYDRA)
- limit = 27;
-
- if (wpn_brand == SPWPN_FLAMING)
- {
- if (defender_visible)
- mpr("The flame cauterises the wound!");
- return (true);
- }
- else if (defender->as_monster()->number < limit - 1)
- {
- simple_monster_message(defender->as_monster(),
- " grows two more!");
- defender->as_monster()->number += 2;
- defender->heal(8 + random2(8), true);
- }
+ simple_monster_message(defender->as_monster(),
+ " grows two more!");
+ defender->as_monster()->number += 2;
+ defender->heal(8 + random2(8), true);
}
}
}
@@ -3503,12 +3495,7 @@ int melee_attack::calc_to_hit(bool random)
// player_to_hit methods.
if (attacker->is_player())
{
- if (wearing_amulet(AMU_INACCURACY))
- mhit -= 5;
-
- // If you can't see yourself, you're a little less accurate. Maybe
- // monsters should get this penalty too? (would nerf orc wizards a bit)
- if (!you.visible_to(&you))
+ if (player_effect_inaccuracy())
mhit -= 5;
// fighting contribution
@@ -3633,13 +3620,8 @@ int melee_attack::calc_to_hit(bool random)
break;
}
}
-
- // If no defender, we're calculating to-hit for debug-display
- // purposes, so don't drop down to defender code below
- if (defender == NULL)
- return (mhit);
}
- else
+ else // Monster to-hit.
{
if (weapon
&& (weapon->base_type == OBJ_WEAPONS
@@ -3651,12 +3633,22 @@ int melee_attack::calc_to_hit(bool random)
if (weapon && item_is_rod(*weapon))
mhit += (short)weapon->props["rod_enchantment"];
-
- // Probably players should get this penalty too.
- if (attacker->confused())
- mhit -= 5;
}
+ // Penalties for both players and monsters:
+
+ // If you can't see yourself, you're a little less accurate.
+ if (!attacker->visible_to(attacker))
+ mhit -= 5;
+
+ if (attacker->confused())
+ mhit -= 5;
+
+ // If no defender, we're calculating to-hit for debug-display
+ // purposes, so don't drop down to defender code below
+ if (defender == NULL)
+ return (mhit);
+
if (!defender->visible_to(attacker))
if (attacker->is_player())
mhit -= 6;
@@ -3740,7 +3732,13 @@ int melee_attack::calc_attack_delay(bool random, bool scaled)
}
else
{
- return (weapon ? property(*weapon, PWPN_SPEED) : 0);
+ if (!weapon)
+ return 10;
+
+ int delay = property(*weapon, PWPN_SPEED);
+ if (damage_brand == SPWPN_SPEED)
+ delay = (delay + 1) / 2;
+ return random ? div_rand_round(10 + delay, 2) : (10 + delay) / 2;
}
return (0);
@@ -4432,33 +4430,18 @@ void melee_attack::mons_apply_attack_flavour()
if (!defender->is_player())
break;
- const bool stolen = expose_player_to_element(BEAM_DEVOUR_FOOD, 10);
+ // The expose_ message doesn't convey the agent.
+ if (needs_message)
+ mprf("%s lunges at you hungrily!", atk_name(DESC_THE).c_str());
+
+ expose_player_to_element(BEAM_DEVOUR_FOOD, 10);
const bool ground = expose_items_to_element(BEAM_DEVOUR_FOOD, you.pos(),
10);
- if (needs_message)
- {
- if (stolen)
- {
- mprf("%s devours some of your food!",
- atk_name(DESC_THE).c_str());
- }
- else if (ground)
- {
- mprf("%s devours some of the food beneath you!",
- atk_name(DESC_THE).c_str());
- }
- }
- break;
- }
- case AF_CRUSH:
- /*
- mprf("%s %s being crushed%s",
- def_name(DESC_THE).c_str(),
- defender->conj_verb("are").c_str(),
- special_attack_punctuation().c_str());
- */
+ if (needs_message && ground)
+ mpr("Some of the food beneath you is devoured!");
break;
+ }
case AF_HOLY:
if (defender->is_evil() || defender->is_unholy())
@@ -4651,8 +4634,12 @@ void melee_attack::emit_foul_stench()
void melee_attack::do_minotaur_retaliation()
{
- if (defender->cannot_act() || !attacker->alive())
+ if (defender->cannot_act()
+ || defender->confused()
+ || !attacker->alive())
+ {
return;
+ }
if (!defender->is_player())
{
@@ -4892,7 +4879,7 @@ int melee_attack::calc_your_to_hit_unarmed(int uattack, bool vampiric)
+ you.skill(SK_FIGHTING, 30);
your_to_hit /= 100;
- if (wearing_amulet(AMU_INACCURACY))
+ if (player_effect_inaccuracy())
your_to_hit -= 5;
if (player_mutation_level(MUT_EYEBALLS))
@@ -5384,14 +5371,6 @@ int melee_attack::inflict_damage(int dam, beam_type flavour, bool clean)
return defender->hurt(attacker, dam, flavour, clean);
}
-// Avoid warnings for unread variables. Used with variable declarations,
-// so unparenthesised: use only as a statement!
-#ifdef DEBUG_DIAGNOSTICS
-# define DIAG_ONLY(x) x
-#else
-# define DIAG_ONLY(x) (void)0
-#endif
-
bool melee_attack::handle_constriction()
{
// see what is grabbed already
@@ -5414,7 +5393,9 @@ bool melee_attack::handle_constriction()
// if a new constriction is possible, try it
if (!defender_grabbed
&& (!any_grabbed || attacker->has_usable_tentacle())
- && defender->constricted_by == NON_ENTITY)
+ && defender->constricted_by == NON_ENTITY
+ && attacker->can_see(defender)
+ && !attacker->confused())
{
// calculate to_hit
size_type asize = attacker->body_size(PSIZE_BODY);
@@ -5479,4 +5460,3 @@ bool melee_attack::handle_constriction()
attacker->has_constricted_this_turn = true;
return true;
}
-#undef DIAG_ONLY
diff --git a/crawl-ref/source/melee_attack.h b/crawl-ref/source/melee_attack.h
index 2553e9689a..cef5492799 100644
--- a/crawl-ref/source/melee_attack.h
+++ b/crawl-ref/source/melee_attack.h
@@ -49,6 +49,8 @@ public:
int miscast_type;
actor* miscast_target;
+ bool simu;
+
public:
melee_attack(actor *attacker, actor *defender,
int attack_num = -1, int effective_attack_num = -1);
diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc
index f700521227..c63600fd24 100644
--- a/crawl-ref/source/message.cc
+++ b/crawl-ref/source/message.cc
@@ -1104,20 +1104,13 @@ void mpr(std::string text, msg_channel_type channel, int param, bool nojoin, boo
std::string col = colour_to_str(colour_msg(colour));
text = "<" + col + ">" + text + "</" + col + ">"; // XXX
+ formatted_string fs = formatted_string::parse_string(text);
if (you.duration[DUR_QUAD_DAMAGE])
- {
- // No sound, so we simulate the reverb with all caps.
- formatted_string fs = formatted_string::parse_string(text);
- fs.all_caps();
- text = fs.to_colour_string();
- }
+ fs.all_caps(); // No sound, so we simulate the reverb with all caps.
else if (cap)
- {
- // Hate, hate, hate tagged strings.
- formatted_string fs = formatted_string::parse_string(text);
fs.capitalize();
- text = fs.to_colour_string();
- }
+ fs.filter_lang();
+ text = fs.to_colour_string();
message_item msg = message_item(text, channel, param, join);
messages.add(msg);
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index dfff5f1ae8..056b37c78a 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -1061,8 +1061,12 @@ bool maybe_bloodify_square(const coord_def& where)
*
* @param where Coordinates of the wall where there is a blood splat.
* @param from Coordinates of the source of the blood.
+ * @param old_blood blood splats created at level generation are old and can
+ * have some blood inscriptions. Only for south facing splats, so you don't
+ * have to turn your head to read the inscriptions.
*/
-static void _orient_wall_blood(const coord_def& where, coord_def from)
+static void _orient_wall_blood(const coord_def& where, coord_def from,
+ bool old_blood)
{
if (!feat_is_wall(env.grid(where)))
return;
@@ -1101,12 +1105,15 @@ static void _orient_wall_blood(const coord_def& where, coord_def from)
env.pgrid(where) |= FPROP_BLOOD_NORTH;
else if (diff == coord_def(-1, 0))
env.pgrid(where) |= FPROP_BLOOD_EAST;
+ else if (old_blood && one_chance_in(10))
+ env.pgrid(where) |= FPROP_OLD_BLOOD;
}
static void _maybe_bloodify_square(const coord_def& where, int amount,
bool spatter = false,
bool smell_alert = true,
- const coord_def& from = INVALID_COORD)
+ const coord_def& from = INVALID_COORD,
+ const bool old_blood = false)
{
if (amount < 1)
return;
@@ -1128,7 +1135,7 @@ static void _maybe_bloodify_square(const coord_def& where, int amount,
if (may_bleed)
{
env.pgrid(where) |= FPROP_BLOODY;
- _orient_wall_blood(where, from);
+ _orient_wall_blood(where, from, old_blood);
if (smell_alert && in_bounds(where))
blood_smell(12, where);
@@ -1145,7 +1152,10 @@ static void _maybe_bloodify_square(const coord_def& where, int amount,
{
// Smaller chance of spattering surrounding squares.
for (adjacent_iterator ai(where); ai; ++ai)
- _maybe_bloodify_square(*ai, amount/15, false, true, from);
+ {
+ _maybe_bloodify_square(*ai, amount/15, false, true, from,
+ old_blood);
+ }
}
}
}
@@ -1155,7 +1165,7 @@ static void _maybe_bloodify_square(const coord_def& where, int amount,
// or, for sacrifices, on the number of chunks possible to get out of a corpse.
void bleed_onto_floor(const coord_def& where, monster_type montype,
int damage, bool spatter, bool smell_alert,
- const coord_def& from)
+ const coord_def& from, const bool old_blood)
{
ASSERT(in_bounds(where));
@@ -1170,7 +1180,8 @@ void bleed_onto_floor(const coord_def& where, monster_type montype,
return;
}
- _maybe_bloodify_square(where, damage, spatter, smell_alert, from);
+ _maybe_bloodify_square(where, damage, spatter, smell_alert, from,
+ old_blood);
}
void blood_spray(const coord_def& origin, monster_type montype, int level)
@@ -1214,7 +1225,7 @@ static void _spatter_neighbours(const coord_def& where, int chance,
if (one_chance_in(chance))
{
env.pgrid(*ai) |= FPROP_BLOODY;
- _orient_wall_blood(where, from);
+ _orient_wall_blood(where, from, true);
_spatter_neighbours(*ai, chance+1, from);
}
}
@@ -2536,21 +2547,24 @@ void wear_id_type(item_def &item)
item.name(DESC_INVENTORY_EQUIP).c_str());
}
-// AutoID an equipped ring of teleport.
-// Code copied from fire/ice in spl-cast.cc
-void maybe_id_ring_TC()
+static void _maybe_id_jewel(jewellery_type ring_type = NUM_JEWELLERY,
+ jewellery_type amulet_type = NUM_JEWELLERY,
+ artefact_prop_type artp = ARTP_NUM_PROPERTIES)
{
- if (you.duration[DUR_CONTROL_TELEPORT]
- || player_mutation_level(MUT_TELEPORT_CONTROL))
- {
- return;
- }
-
int num_unknown = 0;
for (int i = EQ_LEFT_RING; i < NUM_EQUIP; ++i)
{
- if (i == EQ_AMULET)
+ if (i == EQ_AMULET && amulet_type == NUM_JEWELLERY
+ && artp == ARTP_NUM_PROPERTIES)
+ {
+ continue;
+ }
+
+ if (i != EQ_AMULET && ring_type == NUM_JEWELLERY
+ && artp == ARTP_NUM_PROPERTIES)
+ {
continue;
+ }
if (player_wearing_slot(i)
&& !item_ident(you.inv[you.equip[i]], ISFLAG_KNOW_PROPERTIES))
@@ -2559,23 +2573,89 @@ void maybe_id_ring_TC()
}
}
- if (num_unknown == 0)
+ if (num_unknown != 1)
return;
for (int i = EQ_LEFT_RING; i < NUM_EQUIP; ++i)
{
- if (i == EQ_AMULET)
- continue;
-
if (player_wearing_slot(i))
{
- item_def& ring = you.inv[you.equip[i]];
- if (ring.sub_type == RING_TELEPORT_CONTROL)
- wear_id_type(ring);
+ item_def& item = you.inv[you.equip[i]];
+ if (item.sub_type == ring_type || item.sub_type == amulet_type)
+ wear_id_type(item);
+ bool known;
+ if (artp != ARTP_NUM_PROPERTIES && is_artefact(item)
+ && artefact_wpn_property(item, artp, known)
+ && !known)
+ {
+ artefact_wpn_learn_prop(item, artp);
+ mprf("You are wearing: %s",
+ item.name(DESC_INVENTORY_EQUIP).c_str());
+ }
}
}
}
+// AutoID an equipped ring of teleport.
+void maybe_id_ring_TC()
+{
+ if (you.duration[DUR_CONTROL_TELEPORT]
+ || player_mutation_level(MUT_TELEPORT_CONTROL))
+ {
+ return;
+ }
+
+ _maybe_id_jewel(RING_TELEPORT_CONTROL);
+}
+
+void maybe_id_resist(beam_type flavour)
+{
+ switch (flavour)
+ {
+ case BEAM_FIRE:
+ case BEAM_LAVA:
+ if (player_res_fire(false))
+ return;
+ _maybe_id_jewel(RING_PROTECTION_FROM_FIRE, NUM_JEWELLERY, ARTP_FIRE);
+ break;
+
+ case BEAM_COLD:
+ case BEAM_ICE:
+ if (player_res_cold(false))
+ return;
+ _maybe_id_jewel(RING_PROTECTION_FROM_COLD, NUM_JEWELLERY, ARTP_COLD);
+ break;
+
+ case BEAM_ELECTRICITY:
+ if (player_res_electricity(false))
+ return;
+ _maybe_id_jewel(NUM_JEWELLERY, NUM_JEWELLERY, ARTP_ELECTRICITY);
+ break;
+
+ case BEAM_POISON:
+ case BEAM_POISON_ARROW:
+ if (player_res_poison(false))
+ return;
+ _maybe_id_jewel(RING_POISON_RESISTANCE, NUM_JEWELLERY, ARTP_POISON);
+ break;
+
+ case BEAM_NEG:
+ if (player_prot_life(false))
+ return;
+ _maybe_id_jewel(RING_LIFE_PROTECTION, AMU_WARDING, ARTP_NEGATIVE_ENERGY);
+ break;
+
+ case BEAM_STEAM:
+ if (player_res_steam(false))
+ return;
+ // rF+ grants rSteam, all possibly unidentified sources of rSteam are rF
+ _maybe_id_jewel(RING_PROTECTION_FROM_FIRE, NUM_JEWELLERY, ARTP_FIRE);
+ break;
+
+ default: ;
+ }
+}
+
// Reduce damage by AC.
// In most cases, we want AC to mostly stop weak attacks completely but affect
// strong ones less, but the regular formula is too hard to apply well to cases
@@ -2601,7 +2681,10 @@ int apply_chunked_AC(int dam, int ac)
void entered_malign_portal(actor* act)
{
if (you.can_see(act))
- mprf("The portal repels %s, its terrible forces doing untold damage!", (act->is_player()) ? "you" : act->name(DESC_THE).c_str());
+ {
+ mprf("The portal repels %s, its terrible forces doing untold damage!",
+ act->is_player() ? "you" : act->name(DESC_THE).c_str());
+ }
act->blink(false);
if (act->is_player())
diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h
index cf47434107..0eaa64f79f 100644
--- a/crawl-ref/source/misc.h
+++ b/crawl-ref/source/misc.h
@@ -48,7 +48,8 @@ void turn_corpse_into_skeleton_and_blood_potions(item_def &item);
void bleed_onto_floor(const coord_def& where, monster_type mon, int damage,
bool spatter = false, bool smell_alert = true,
- const coord_def& from = INVALID_COORD);
+ const coord_def& from = INVALID_COORD,
+ const bool old_blood = false);
void blood_spray(const coord_def& where, monster_type mon, int level);
void generate_random_blood_spatter_on_level(
const map_mask *susceptible_area = NULL);
@@ -125,6 +126,7 @@ void swap_with_monster(monster* mon_to_swap);
void wear_id_type(item_def &item);
void maybe_id_ring_TC();
+void maybe_id_resist(beam_type flavour);
int apply_chunked_AC(int dam, int ac);
diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc
index c3c4e75786..88e1f2e704 100644
--- a/crawl-ref/source/mon-abil.cc
+++ b/crawl-ref/source/mon-abil.cc
@@ -12,6 +12,7 @@
#include "beam.h"
#include "colour.h"
#include "coordit.h"
+#include "delay.h"
#include "directn.h"
#include "fprop.h"
#include "ghost.h"
@@ -22,6 +23,7 @@
#include "mon-cast.h"
#include "mon-iter.h"
#include "mon-place.h"
+#include "mon-project.h"
#include "terrain.h"
#include "mgen_data.h"
#include "cloud.h"
@@ -308,7 +310,8 @@ static void _merge_ench_durations(monster* initial, monster* merge_to, bool useh
{
// Does the other creature have this enchantment as well?
mon_enchant temp = merge_to->get_ench(i->first);
- bool no_initial = temp.ench == ENCH_NONE; // If not, use duration 0 for their part of the average.
+ // If not, use duration 0 for their part of the average.
+ bool no_initial = temp.ench == ENCH_NONE;
int duration = no_initial ? 0 : temp.duration;
i->second.duration = (i->second.duration * initial_count
@@ -1833,12 +1836,12 @@ bool valid_kraken_connection(const monster* mons)
}
-bool valid_kraken_segment(monster * mons)
+static bool _valid_kraken_segment(monster * mons)
{
return (mons->type == MONS_KRAKEN_TENTACLE_SEGMENT);
}
-bool valid_demonic_connection(monster* mons)
+static bool _valid_demonic_connection(monster* mons)
{
return (mons->mons_species() == MONS_ELDRITCH_TENTACLE_SEGMENT);
}
@@ -1937,13 +1940,13 @@ void move_demon_tentacle(monster* tentacle)
std::map<coord_def, std::set<int> > connection_data;
int visited_count = _collect_connection_data(tentacle,
- valid_demonic_connection,
+ _valid_demonic_connection,
connection_data,
retract_pos);
//bool retract_found = retract_pos.x == -1 && retract_pos.y == -1;
- _purge_connectors(tentacle->mindex(), valid_demonic_connection);
+ _purge_connectors(tentacle->mindex(), _valid_demonic_connection);
if (severed)
{
@@ -2068,8 +2071,10 @@ void move_demon_tentacle(monster* tentacle)
{
// This should really never fail for demonic tentacles (they don't
// have the whole shifting base problem). -cao
- mprf("tentacle connect failed! What the heck! severed status %d", tentacle->has_ench(ENCH_SEVERED));
- mprf("pathed to %d %d from %d %d mid %d count %d", new_pos.x, new_pos.y, old_pos.x, old_pos.y, tentacle->mindex(), visited_count);
+ mprf("tentacle connect failed! What the heck! severed status %d",
+ tentacle->has_ench(ENCH_SEVERED));
+ mprf("pathed to %d %d from %d %d mid %d count %d", new_pos.x, new_pos.y,
+ old_pos.x, old_pos.y, tentacle->mindex(), visited_count);
// mgrd(tentacle->pos()) = tentacle->mindex();
@@ -2162,7 +2167,7 @@ void move_kraken_tentacles(monster* kraken)
int tentacle_idx = tentacle->mindex();
- _purge_connectors(tentacle_idx, valid_kraken_segment);
+ _purge_connectors(tentacle_idx, _valid_kraken_segment);
if (no_foe
&& grid_distance(tentacle->pos(), kraken->pos()) == 1)
@@ -2591,6 +2596,30 @@ bool mon_special_ability(monster* mons, bolt & beem)
}
break;
+ case MONS_BOULDER_BEETLE:
+ if (mons->has_ench(ENCH_CONFUSION))
+ break;
+
+ if (!mons->has_ench(ENCH_ROLLING))
+ {
+ // Fleeing check
+ if (mons_is_fleeing(mons))
+ {
+ if (coinflip())
+ {
+ // behaviour_event(mons, ME_CORNERED);
+ boulder_flee(mons, &beem);
+ }
+ }
+ // Normal check - don't roll at adjacent targets
+ else if (one_chance_in(3) &&
+ !adjacent(mons->pos(), beem.target))
+ {
+ boulder_start(mons, &beem);
+ }
+ }
+ break;
+
case MONS_MANTICORE:
if (mons->has_ench(ENCH_CONFUSION))
break;
@@ -2897,7 +2926,10 @@ void mon_nearby_ability(monster* mons)
int confuse_power = 2 + random2(3);
if (foe->is_player() && !can_see)
+ {
mpr("You feel you are being watched by something.");
+ interrupt_activity(AI_MONSTER_ATTACKS, mons);
+ }
int res_margin = foe->check_res_magic((mons->hit_dice * 5)
* confuse_power);
@@ -2945,6 +2977,8 @@ void mon_nearby_ability(monster* mons)
else
mpr("You feel you are being watched by something.");
+ interrupt_activity(AI_MONSTER_ATTACKS, mons);
+
int mp = std::min(5 + random2avg(13, 3), you.magic_points);
dec_mp(mp);
@@ -2976,7 +3010,7 @@ void ballisto_on_move(monster* mons, const coord_def & position)
{
dungeon_feature_type ftype = env.grid(mons->pos());
- if (ftype >= DNGN_FLOOR_MIN && ftype <= DNGN_FLOOR_MAX)
+ if (ftype == DNGN_FLOOR)
env.pgrid(mons->pos()) |= FPROP_MOLD;
// The number field is used as a cooldown timer for this behavior.
diff --git a/crawl-ref/source/mon-abil.h b/crawl-ref/source/mon-abil.h
index be76913a43..9620beb863 100644
--- a/crawl-ref/source/mon-abil.h
+++ b/crawl-ref/source/mon-abil.h
@@ -23,7 +23,6 @@ void activate_ballistomycetes(monster* mons, const coord_def & origin,
bool valid_kraken_connection(const monster* mons);
void move_kraken_tentacles(monster * kraken);
-bool valid_demonic_connection(monster* mons);
void move_demon_tentacle(monster * tentacle);
#endif
diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc
index 114541e21a..df2482f5a9 100644
--- a/crawl-ref/source/mon-act.cc
+++ b/crawl-ref/source/mon-act.cc
@@ -808,7 +808,7 @@ static bool _handle_reaching(monster* mons)
&& delta.abs() <= reach_range(range)
// And with no dungeon furniture in the way of the reaching
// attack; if the middle square is empty, skip the LOS check.
- && (grd(middle) > DNGN_MAX_NONREACH
+ && (feat_is_reachable_past(grd(middle))
|| mons->see_cell_no_trans(foepos))
// The foe should be on the map (not stepped from time).
&& in_bounds(foepos))
@@ -1940,7 +1940,13 @@ void handle_noattack_constrictions(actor *attacker)
{
// Constriction should have stopped the moment the actors
// became non-adjacent.
- ASSERT(adjacent(attacker->pos(), defender->pos()));
+ if (!adjacent(attacker->pos(), defender->pos()))
+ {
+ // Yet disabling constriction by hand in every single place
+ // is too error-prone.
+ attacker->stop_constricting(defender->mindex(), false);
+ continue;
+ }
int damage;
@@ -1948,18 +1954,18 @@ void handle_noattack_constrictions(actor *attacker)
damage = roll_dice(2, div_rand_round(you.strength(), 5));
else
damage = (attacker->as_monster()->hit_dice + 1) / 2;
- DIAG_ONLY(int basedam = damage);
+ DIAG_ONLY(const int basedam = damage);
damage += div_rand_round(attacker->dur_has_constricted[i], BASELINE_DELAY);
if (attacker->is_player())
damage = div_rand_round(damage * (27 + 2 * you.experience_level), 81);
- DIAG_ONLY(int durdam = damage);
+ DIAG_ONLY(const int durdam = damage);
damage -= random2(1 + (defender->armour_class() / 2));
- DIAG_ONLY(int acdam = damage);
+ DIAG_ONLY(const int acdam = damage);
damage = timescale_damage(attacker, damage);
- DIAG_ONLY(int timescale_dam = damage);
+ DIAG_ONLY(const int timescale_dam = damage);
damage = defender->hurt(attacker, damage, BEAM_MISSILE, false);
- DIAG_ONLY(int infdam = damage);
+ DIAG_ONLY(const int infdam = damage);
std::string exclams;
if (damage <= 0 && attacker->is_player()
@@ -2193,6 +2199,14 @@ void handle_monster_move(monster* mons)
continue;
}
+ if (mons_is_boulder(mons))
+ {
+ if (boulder_act(*mons))
+ return;
+ mons->lose_energy(EUT_MOVE);
+ continue;
+ }
+
mons->shield_blocks = 0;
const int cloud_num = env.cgrid(mons->pos());
@@ -2269,10 +2283,11 @@ void handle_monster_move(monster* mons)
&& (mons_itemuse(mons) >= MONUSE_WEAPONS_ARMOUR
|| mons_itemeat(mons) != MONEAT_NOTHING))
{
- // Keep neutral and charmed monsters from picking up stuff.
+ // Keep neutral, charmed, summoned monsters from picking up stuff.
// Same for friendlies if friendly_pickup is set to "none".
- if (!mons->neutral() && !mons->has_ench(ENCH_CHARM)
- || (you.religion == GOD_JIYVA && mons_is_slime(mons))
+ if ((!mons->neutral() && !mons->has_ench(ENCH_CHARM)
+ || (you.religion == GOD_JIYVA && mons_is_slime(mons)))
+ && !mons->is_summoned()
&& (!mons->friendly()
|| you.friendly_pickup != FRIENDLY_PICKUP_NONE))
{
diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc
index 759ad1adba..fbc3c2c861 100644
--- a/crawl-ref/source/mon-cast.cc
+++ b/crawl-ref/source/mon-cast.cc
@@ -894,6 +894,10 @@ bolt mons_spells(monster* mons, spell_type spell_cast, int power,
case SPELL_IOOD: // tracer only
beam.flavour = BEAM_NUKE;
beam.is_beam = true;
+ // Doesn't take distance into account, but this is just a tracer so
+ // we'll ignore that. We need some damage on the tracer so the monster
+ // doesn't think the spell is useless against other monsters.
+ beam.damage = dice_def(9, stepdown_value(power, 30, 30, 200, -1) / 4);
break;
case SPELL_SUNRAY:
@@ -2151,9 +2155,9 @@ void mons_cast_spectral_orcs(monster* mons)
static bool _mons_vampiric_drain(monster *mons)
{
actor *target = mons->get_foe();
- if (grid_distance(mons->pos(), target->pos()) > 1)
+ if (!target)
return (false);
- if (target->undead_or_demonic())
+ if (grid_distance(mons->pos(), target->pos()) > 1)
return (false);
int fnum = 5;
@@ -2165,8 +2169,16 @@ static bool _mons_vampiric_drain(monster *mons)
hp_cost = std::min(hp_cost, target->stat_hp());
hp_cost = std::min(hp_cost, mons->max_hit_points - mons->hit_points);
+ if (target->res_negative_energy() > 0)
+ hp_cost -= hp_cost * target->res_negative_energy() / 3;
+
if (!hp_cost)
+ {
+ simple_monster_message(mons,
+ " is infused with unholy energy, but nothing happens.",
+ MSGCH_MONSTER_SPELL);
return (false);
+ }
dprf("vamp draining: %d damage, %d healing", hp_cost, hp_cost/2);
@@ -2182,19 +2194,25 @@ static bool _mons_vampiric_drain(monster *mons)
if (target->is_player())
{
ouch(hp_cost, mons->mindex(), KILLED_BY_BEAM, mons->name(DESC_A).c_str());
- simple_monster_message(mons,
- " draws life force from you and is healed!");
+ if (mons->heal(hp_cost / 2))
+ {
+ simple_monster_message(mons,
+ " draws life force from you and is healed!");
+ }
}
else
{
monster* mtarget = target->as_monster();
const std::string targname = mtarget->name(DESC_THE);
mtarget->hurt(mons, hp_cost);
- simple_monster_message(mons,
- make_stringf(" draws life force from %s and is healed!", targname.c_str()).c_str());
+ if (mons->heal(hp_cost / 2))
+ {
+ simple_monster_message(mons,
+ make_stringf(" draws life force from %s and is healed!",
+ targname.c_str()).c_str());
+ }
if (mtarget->alive())
print_wounds(mtarget);
- mons->heal(hp_cost / 2);
}
return (true);
@@ -2668,7 +2686,8 @@ void mons_cast(monster* mons, bolt &pbolt, spell_type spell_cast,
case SPELL_TROGS_HAND:
{
simple_monster_message(mons,
- make_stringf(" invokes %s's protection!", god_name(mons->god).c_str()).c_str(),
+ make_stringf(" invokes %s's protection!",
+ god_name(mons->god).c_str()).c_str(),
MSGCH_MONSTER_SPELL);
const int dur = BASELINE_DELAY
* std::min(5 + roll_dice(2, (mons->hit_dice * 10) / 3 + 1), 100);
@@ -3101,7 +3120,11 @@ void mons_cast(monster* mons, bolt &pbolt, spell_type spell_cast,
case SPELL_MALIGN_GATEWAY:
if (!can_cast_malign_gateway())
- dprf("ERROR: %s can't cast malign gateway, but is casting anyway! Counted %d gateways.", mons->name(DESC_THE).c_str(), count_malign_gateways());
+ {
+ dprf("ERROR: %s can't cast malign gateway, but is casting anyway! "
+ "Counted %d gateways.", mons->name(DESC_THE).c_str(),
+ count_malign_gateways());
+ }
cast_malign_gateway(mons, 200);
return;
@@ -3456,7 +3479,7 @@ void mons_cast(monster* mons, bolt &pbolt, spell_type spell_cast,
if (grd(*ai) == safe_tiles[i] || feat_is_trap(grd(*ai)))
proceed = true;
- if (!proceed && grd(*ai) > DNGN_MAX_NONREACH)
+ if (!proceed && feat_is_reachable_past(grd(*ai)))
sumcount++;
}
@@ -4146,6 +4169,9 @@ bool ms_useful_fleeing_out_of_sight(const monster* mon, spell_type monspell)
bool ms_low_hitpoint_cast(const monster* mon, spell_type monspell)
{
+ if (ms_waste_of_time(mon, monspell))
+ return (false);
+
bool targ_adj = false;
bool targ_sanct = false;
bool targ_friendly = false;
@@ -4178,9 +4204,6 @@ bool ms_low_hitpoint_cast(const monster* mon, spell_type monspell)
{
case SPELL_TELEPORT_OTHER:
return !targ_sanct && !targ_friendly;
- case SPELL_TELEPORT_SELF:
- // Don't cast again if already about to teleport.
- return !mon->has_ench(ENCH_TP);
case SPELL_MINOR_HEALING:
case SPELL_MAJOR_HEALING:
return true;
@@ -4200,10 +4223,6 @@ bool ms_low_hitpoint_cast(const monster* mon, spell_type monspell)
case SPELL_INK_CLOUD:
if (mon->type == MONS_KRAKEN)
return true;
- case SPELL_DEATHS_DOOR:
- return !mon->has_ench(ENCH_DEATHS_DOOR);
- case SPELL_INVISIBILITY:
- return !mon->has_ench(ENCH_INVIS);
default:
return !targ_adj && spell_typematch(monspell, SPTYP_SUMMONING);
}
@@ -4298,10 +4317,18 @@ bool ms_waste_of_time(const monster* mon, spell_type monspell)
ret = (!foe || !foe->is_player());
break;
+ case SPELL_VAMPIRIC_DRAINING:
+ if (mon->hit_points + 1 >= mon->max_hit_points
+ || grid_distance(mon->pos(), foe->pos()) > 1)
+ {
+ ret = true;
+ }
+ // fall through
case SPELL_BOLT_OF_DRAINING:
case SPELL_AGONY:
case SPELL_SYMBOL_OF_TORMENT:
- ret = (!foe || _foe_should_res_negative_energy(foe));
+ if (!foe || _foe_should_res_negative_energy(foe))
+ ret = true;
break;
case SPELL_MIASMA:
ret = (!foe || foe->res_rotting());
@@ -4337,8 +4364,11 @@ bool ms_waste_of_time(const monster* mon, spell_type monspell)
break;
case SPELL_REGENERATION:
- if (mon->has_ench(ENCH_REGENERATION) || mon->has_ench(ENCH_DEATHS_DOOR))
+ if (mon->has_ench(ENCH_REGENERATION) || mon->has_ench(ENCH_DEATHS_DOOR)
+ || mon->holiness() == MH_UNDEAD)
+ {
ret = true;
+ }
break;
case SPELL_MIRROR_DAMAGE:
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 116dfc1c04..bf6877dad3 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -62,8 +62,9 @@
Further explanations copied from mon-util.h:
hpdice[4]: [0]=HD [1]=min_hp [2]=rand_hp [3]=add_hp
- min hp = [0]*[1]+[3]
- max hp = [0]*times_do*{ [1]+random2([2])}, *then* + [3]
+ min hp = [0]*[1] + [3]
+ max hp = [0]*([1]+[2]) + [3]
+ hp = [0] *times_do* { [1] + random2(1+[2]) }, *then* + [3]
example: the Iron Golem, hpdice={15,7,4,0}
15*7 < hp < 15*(7+4),
105 < hp < 165
@@ -1927,12 +1928,12 @@ static monsterentry mondata[] = {
{
MONS_EMPEROR_SCORPION, 's', LIGHTGREY, "emperor scorpion",
M_NO_SKELETON,
- MR_VUL_POISON,
+ MR_RES_POISON,
900, 9, MONS_SCORPION, MONS_EMPEROR_SCORPION, MH_NATURAL, -3,
- { {AT_STING, AF_POISON_MEDIUM, 30}, {AT_HIT, AF_PLAIN, 11},
- {AT_HIT, AF_PLAIN, 11}, AT_NO_ATK },
- { 14, 4, 5, 0 },
- 18, 8, MST_NO_SPELLS, CE_POISON_CONTAM, Z_BIG, S_SILENT,
+ { {AT_STING, AF_POISON_NASTY, 30}, {AT_CLAW, AF_PLAIN, 15},
+ {AT_CLAW, AF_PLAIN, 15}, AT_NO_ATK },
+ { 14, 6, 5, 0 },
+ 20, 12, MST_NO_SPELLS, CE_POISON_CONTAM, Z_BIG, S_SILENT,
I_INSECT, HT_LAND, FL_NONE, 10, DEFAULT_ENERGY,
MONUSE_NOTHING, MONEAT_NOTHING, SIZE_LARGE
},
@@ -2609,9 +2610,9 @@ static monsterentry mondata[] = {
MR_VUL_POISON,
2050, 8, MONS_GOLIATH_BEETLE, MONS_BOULDER_BEETLE, MH_NATURAL, -3,
{ {AT_BITE, AF_PLAIN, 45}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
- { 9, 3, 5, 0 },
+ { 9, 6, 5, 0 },
20, 2, MST_NO_SPELLS, CE_POISONOUS, Z_BIG, S_SILENT,
- I_INSECT, HT_LAND, FL_NONE, 3, DEFAULT_ENERGY,
+ I_INSECT, HT_LAND, FL_NONE, 6, DEFAULT_ENERGY,
MONUSE_NOTHING, MONEAT_NOTHING, SIZE_BIG
},
@@ -3592,8 +3593,7 @@ static monsterentry mondata[] = {
{
MONS_OKLOB_SAPLING, 'P', LIGHTCYAN, "oklob sapling",
- // if we decide to allow this for normal games, please remove M_NO_POLY_TO
- M_STATIONARY | M_NO_POLY_TO,
+ M_STATIONARY,
MR_RES_POISON | MR_RES_ACID,
0, 10, MONS_PLANT, MONS_OKLOB_PLANT, MH_PLANT, -3,
{ AT_NO_ATK, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
@@ -5280,13 +5280,12 @@ static monsterentry mondata[] = {
// explodey things / orb of fire ('*')
{
MONS_BALL_LIGHTNING, '*', LIGHTCYAN, "ball lightning",
- M_CONFUSED | M_SPELLCASTER | M_INSUBSTANTIAL
- | M_GLOWS_LIGHT | M_FAKE_SPELLS,
+ M_CONFUSED | M_INSUBSTANTIAL | M_GLOWS_LIGHT,
mrd(MR_RES_ELEC | MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD, 3),
0, 20, MONS_BALL_LIGHTNING, MONS_BALL_LIGHTNING, MH_NONLIVING, MAG_IMMUNE,
{ {AT_HIT, AF_PLAIN, 5}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
{ 12, 0, 0, 1 },
- 0, 10, MST_STORM_DRAGON, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT,
+ 0, 10, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT,
I_PLANT, HT_LAND, FL_LEVITATE, 20, DEFAULT_ENERGY,
MONUSE_NOTHING, MONEAT_NOTHING, SIZE_LITTLE
},
diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc
index 889488ef4d..1b605863e2 100644
--- a/crawl-ref/source/mon-death.cc
+++ b/crawl-ref/source/mon-death.cc
@@ -521,7 +521,8 @@ void spirit_fades(monster *spirit)
/**
* Determine if a monster is a phoenix.
*
- * Monsters that were previously phoenixes are not considered phoenixes for phoenix resurrection purposes, I suppose.
+ * Monsters that were previously phoenixes are not considered phoenixes for
+ * phoenix resurrection purposes, I suppose.
*
* @param mons The monster to check.
* @returns True if Phoenix, False otherwise.
@@ -592,9 +593,9 @@ void timeout_phoenix_markers(int duration)
if (mmark->duration < 0)
{
// Now, look for the corpse
- bool found_body;
+ bool found_body = false;
coord_def place_at;
- bool from_inventory;
+ bool from_inventory = false;
for (radius_iterator ri(mmark->corpse_pos, LOS_RADIUS, C_ROUND, NULL, false); ri; ++ri)
{
diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc
index 5528f032bf..37a17c01f2 100644
--- a/crawl-ref/source/mon-ench.cc
+++ b/crawl-ref/source/mon-ench.cc
@@ -259,6 +259,10 @@ void monster::add_enchantment_effect(const mon_enchant &ench, bool quiet)
invalidate_agrid(true);
break;
+ case ENCH_ROLLING:
+ calc_speed();
+ break;
+
default:
break;
}
@@ -695,6 +699,12 @@ void monster::remove_enchantment_effect(const mon_enchant &me, bool quiet)
simple_monster_message(this, "'s inner flame fades away.");
break;
+ case ENCH_ROLLING:
+ calc_speed();
+ if (!quiet && alive())
+ simple_monster_message(this, " stops rolling.");
+ break;
+
//The following should never happen, but just in case...
case ENCH_MUTE:
@@ -850,6 +860,7 @@ void monster::timeout_enchantments(int levels)
case ENCH_INSANE:
case ENCH_BERSERK:
case ENCH_INNER_FLAME:
+ case ENCH_ROLLING:
del_ench(i->first);
break;
@@ -1044,6 +1055,7 @@ void monster::apply_enchantment(const mon_enchant &me)
case ENCH_MAD:
case ENCH_BREATH_WEAPON:
case ENCH_DEATHS_DOOR:
+ // case ENCH_ROLLING:
decay_enchantment(me);
break;
@@ -1248,7 +1260,10 @@ void monster::apply_enchantment(const mon_enchant &me)
if (!monster_can_submerge(this, grid))
del_ench(ENCH_SUBMERGED); // forced to surface
else if (mons_landlubbers_in_reach(this))
+ {
del_ench(ENCH_SUBMERGED);
+ make_mons_stop_fleeing(this);
+ }
break;
}
case ENCH_POISON:
@@ -1745,7 +1760,7 @@ static const char *enchant_names[] =
#endif
"liquefying", "tornado", "fake_abjuration",
"dazed", "mute", "blind", "dumb", "mad", "silver_corona", "recite timer",
- "inner_flame", "roused", "breath timer", "deaths_door", "buggy",
+ "inner_flame", "roused", "breath timer", "deaths_door", "rolling", "buggy",
};
static const char *_mons_enchantment_name(enchant_type ench)
@@ -1974,6 +1989,14 @@ int mon_enchant::calc_duration(const monster* mons,
case ENCH_FAKE_ABJURATION:
case ENCH_ABJ:
+ // The duration is:
+ // deg = 1 90 aut
+ // deg = 2 180 aut
+ // deg = 3 270 aut
+ // deg = 4 360 aut
+ // deg = 5 810 aut
+ // deg = 6 1710 aut
+ // with a large fuzz
if (deg >= 6)
cturn = 1000 / _mod_speed(10, mons->speed);
if (deg >= 5)
@@ -1995,6 +2018,9 @@ int mon_enchant::calc_duration(const monster* mons,
return (random_range(75, 125) * 10);
case ENCH_BERSERK:
return (16 + random2avg(13, 2)) * 10;
+ case ENCH_ROLLING:
+ cturn = 10000 / _mod_speed(25, mons->speed);
+ break;
default:
break;
}
@@ -2002,6 +2028,8 @@ int mon_enchant::calc_duration(const monster* mons,
cturn = std::max(2, cturn);
int raw_duration = (cturn * speed_to_duration(mons->speed));
+ // Note: this fuzzing is _not_ symmetric, resulting in 90% of input
+ // on the average.
raw_duration = std::max(15, fuzz_value(raw_duration, 60, 40));
dprf("cturn: %d, raw_duration: %d", cturn, raw_duration);
diff --git a/crawl-ref/source/mon-gear.cc b/crawl-ref/source/mon-gear.cc
index 18b440d83a..724d756053 100644
--- a/crawl-ref/source/mon-gear.cc
+++ b/crawl-ref/source/mon-gear.cc
@@ -1563,7 +1563,7 @@ static bool make_item_for_monster(
return (true);
}
-void give_shield(monster* mon, int level)
+static void _give_shield(monster* mon, int level)
{
const item_def *main_weap = mon->mslot_item(MSLOT_WEAPON);
const item_def *alt_weap = mon->mslot_item(MSLOT_ALT_WEAPON);
@@ -1703,7 +1703,7 @@ void give_shield(monster* mon, int level)
}
}
-void give_armour(monster* mon, int level, bool spectral_orcs)
+static void _give_armour(monster* mon, int level, bool spectral_orcs)
{
item_def item;
item_make_species_type item_race = MAKE_ITEM_RANDOM_RACE;
@@ -1764,22 +1764,19 @@ void give_armour(monster* mon, int level, bool spectral_orcs)
break;
case MONS_ERICA:
- case MONS_HAROLD:
case MONS_JOSEPHINE:
- case MONS_JOZEF:
case MONS_PSYCHE:
- if (x_chance_in_y(2, 5))
- {
- item.base_type = OBJ_ARMOUR;
- item.sub_type = random_choose_weighted(10, ARM_LEATHER_ARMOUR,
- 3, ARM_RING_MAIL,
- 1, ARM_TROLL_LEATHER_ARMOUR,
- 1, ARM_STEAM_DRAGON_ARMOUR,
- 1, ARM_MOTTLED_DRAGON_ARMOUR,
- 0);
- }
- else
- return;
+ if (one_chance_in(5))
+ level = MAKE_GOOD_ITEM;
+ item.base_type = OBJ_ARMOUR;
+ item.sub_type = ARM_ROBE;
+ item_race = MAKE_ITEM_NO_RACE;
+ break;
+
+ case MONS_HAROLD:
+ item.base_type = OBJ_ARMOUR;
+ item.sub_type = ARM_RING_MAIL;
+ item_race = MAKE_ITEM_NO_RACE;
break;
case MONS_GNOLL_SHAMAN:
@@ -1795,6 +1792,7 @@ void give_armour(monster* mon, int level, bool spectral_orcs)
break;
case MONS_JOSEPH:
+ case MONS_JOZEF:
item.base_type = OBJ_ARMOUR;
item.sub_type = random_choose_weighted(3, ARM_LEATHER_ARMOUR,
2, ARM_RING_MAIL,
@@ -1853,7 +1851,6 @@ void give_armour(monster* mon, int level, bool spectral_orcs)
// deliberate fall through {dlb}
case MONS_PALADIN:
- case MONS_FREDERICK:
case MONS_HELL_KNIGHT:
case MONS_LOUISE:
case MONS_DONALD:
@@ -1866,6 +1863,12 @@ void give_armour(monster* mon, int level, bool spectral_orcs)
ARM_PLATE_ARMOUR, -1);
break;
+ case MONS_FREDERICK:
+ item.base_type = OBJ_ARMOUR;
+ item.sub_type = random_choose(ARM_SCALE_MAIL, ARM_CHAIN_MAIL,
+ ARM_SPLINT_MAIL, -1);
+ break;
+
case MONS_MARGERY:
item.base_type = OBJ_ARMOUR;
item.sub_type = random_choose_weighted(3, ARM_MOTTLED_DRAGON_ARMOUR,
@@ -2169,6 +2172,6 @@ void give_item(monster *mons, int level_number, bool mons_summoned, bool spectra
_give_ammo(mons, level_number, item_race, mons_summoned);
- give_armour(mons, 1 + level_number / 2, spectral_orcs);
- give_shield(mons, 1 + level_number / 2);
+ _give_armour(mons, 1 + level_number / 2, spectral_orcs);
+ _give_shield(mons, 1 + level_number / 2);
}
diff --git a/crawl-ref/source/mon-info.cc b/crawl-ref/source/mon-info.cc
index 9fe0be9990..648289edba 100644
--- a/crawl-ref/source/mon-info.cc
+++ b/crawl-ref/source/mon-info.cc
@@ -144,6 +144,8 @@ static monster_info_flags ench_to_mb(const monster& mons, enchant_type ench)
return MB_BREATH_WEAPON;
case ENCH_DEATHS_DOOR:
return MB_DEATHS_DOOR;
+ case ENCH_ROLLING:
+ return MB_ROLLING;
default:
return NUM_MB_FLAGS;
}
@@ -835,7 +837,8 @@ std::string monster_info::_core_name() const
return s;
}
-std::string monster_info::_apply_adjusted_description(description_level_type desc, const std::string& s) const
+std::string monster_info::_apply_adjusted_description(description_level_type desc,
+ const std::string& s) const
{
if (desc == DESC_ITS)
desc = DESC_THE;
@@ -961,6 +964,8 @@ std::string monster_info::mimic_name() const
{
s = "rune";
}
+ else if (item->base_type == OBJ_ORBS)
+ s = "orb";
else
s = item->name(DESC_BASENAME);
}
@@ -1338,6 +1343,8 @@ std::vector<std::string> monster_info::attributes() const
v.push_back("standing in death's doorway");
if (is(MB_REGENERATION))
v.push_back("regenerating");
+ if (is(MB_ROLLING))
+ v.push_back("rolling");
return v;
}
diff --git a/crawl-ref/source/mon-info.h b/crawl-ref/source/mon-info.h
index 22e1f02078..58e7ec9edf 100644
--- a/crawl-ref/source/mon-info.h
+++ b/crawl-ref/source/mon-info.h
@@ -83,6 +83,7 @@ enum monster_info_flags
MB_TWO_WEAPONS,
MB_NO_REGEN,
MB_SUPPRESSED,
+ MB_ROLLING,
NUM_MB_FLAGS
};
diff --git a/crawl-ref/source/mon-pick.cc b/crawl-ref/source/mon-pick.cc
index bb03335d6e..db8952c284 100644
--- a/crawl-ref/source/mon-pick.cc
+++ b/crawl-ref/source/mon-pick.cc
@@ -17,7 +17,8 @@
// NOTE: The lower the level the earlier a monster may appear.
int mons_level(monster_type mcls, const level_id &place)
{
- return branches[place.branch].mons_level_function(mcls);
+ return branches[place.branch].mons_level_function(mcls)
+ + absdungeon_depth(place.branch, 0);
}
// NOTE: Higher values returned means the monster is "more common".
@@ -401,35 +402,34 @@ int mons_standard_level(monster_type mcls)
{
case MONS_GOBLIN:
case MONS_GIANT_NEWT:
- return 1;
+ return 2;
case MONS_GIANT_COCKROACH:
case MONS_OOZE:
case MONS_BALL_PYTHON:
- return 2;
+ return 3;
case MONS_BAT:
case MONS_KOBOLD:
case MONS_RAT:
- return 4;
+ return 5;
case MONS_GIANT_GECKO:
case MONS_GIANT_MITE:
case MONS_GNOLL:
case MONS_HOBGOBLIN:
case MONS_JACKAL:
- case MONS_KILLER_BEE_LARVA:
- return 5;
+ return 6;
case MONS_WORM:
case MONS_ADDER:
case MONS_QUOKKA:
case MONS_GNOLL_SHAMAN:
- return 6;
+ return 7;
case MONS_ORC:
case MONS_ORC_PRIEST:
- return 7;
+ return 8;
case MONS_FUNGUS:
case MONS_WORKER_ANT:
@@ -442,7 +442,7 @@ int mons_standard_level(monster_type mcls)
case MONS_SCORPION:
case MONS_SKELETON_SMALL:
case MONS_GNOLL_SERGEANT:
- return 8;
+ return 9;
case MONS_WATER_MOCCASIN:
case MONS_CENTAUR:
@@ -453,7 +453,7 @@ int mons_standard_level(monster_type mcls)
case MONS_QUASIT:
case MONS_ZOMBIE_SMALL:
case MONS_SKY_BEAST:
- return 9;
+ return 10;
case MONS_DEEP_ELF_SOLDIER:
case MONS_GOLIATH_BEETLE:
@@ -463,7 +463,7 @@ int mons_standard_level(monster_type mcls)
case MONS_ORC_WARRIOR:
case MONS_STEAM_DRAGON:
case MONS_WIGHT:
- return 10;
+ return 11;
case MONS_CROCODILE:
case MONS_HIPPOGRIFF:
@@ -471,13 +471,13 @@ int mons_standard_level(monster_type mcls)
case MONS_KILLER_BEE:
case MONS_SHADOW:
case MONS_YELLOW_WASP:
- return 11;
+ return 12;
case MONS_EYE_OF_DRAINING:
case MONS_MANTICORE:
case MONS_PLANT:
case MONS_WYVERN:
- return 12;
+ return 13;
case MONS_BIG_KOBOLD:
case MONS_GIANT_CENTIPEDE:
@@ -486,7 +486,7 @@ int mons_standard_level(monster_type mcls)
case MONS_TWO_HEADED_OGRE:
case MONS_WOOD_GOLEM:
case MONS_YAK:
- return 13;
+ return 14;
case MONS_HILL_GIANT:
case MONS_KOMODO_DRAGON:
@@ -494,7 +494,7 @@ int mons_standard_level(monster_type mcls)
case MONS_WRAITH:
case MONS_UNSEEN_HORROR:
case MONS_TRAPDOOR_SPIDER:
- return 14;
+ return 15;
case MONS_BASILISK:
case MONS_BRAIN_WORM:
@@ -505,7 +505,7 @@ int mons_standard_level(monster_type mcls)
case MONS_MOTTLED_DRAGON:
case MONS_SKELETAL_WARRIOR:
case MONS_CATOBLEPAS:
- return 15;
+ return 16;
case MONS_BLINK_FROG:
case MONS_BUTTERFLY:
@@ -517,7 +517,7 @@ int mons_standard_level(monster_type mcls)
case MONS_VAMPIRE:
case MONS_WANDERING_MUSHROOM:
case MONS_ZOMBIE_LARGE:
- return 16;
+ return 17;
case MONS_BOGGART:
case MONS_CENTAUR_WARRIOR:
@@ -529,14 +529,15 @@ int mons_standard_level(monster_type mcls)
case MONS_SIMULACRUM_SMALL:
case MONS_SIMULACRUM_LARGE:
case MONS_ROCK_WORM:
- return 17;
+ return 18;
case MONS_DRAGON:
case MONS_GARGOYLE:
case MONS_GIANT_AMOEBA:
case MONS_KOBOLD_DEMONOLOGIST:
- case MONS_SKELETON_LARGE: // Higher than actual threat level so that they will still show up in The Vaults
- return 18;
+ // Higher than actual threat level so that they will still show up in The Vaults
+ case MONS_SKELETON_LARGE:
+ return 19;
case MONS_GIANT_SLUG:
case MONS_IRON_GOLEM:
@@ -545,7 +546,7 @@ int mons_standard_level(monster_type mcls)
case MONS_TOENAIL_GOLEM:
case MONS_YAKTAUR:
case MONS_WOLF_SPIDER:
- return 19;
+ return 20;
case MONS_AIR_ELEMENTAL:
case MONS_DEEP_ELF_FIGHTER:
@@ -569,12 +570,12 @@ int mons_standard_level(monster_type mcls)
case MONS_VERY_UGLY_THING:
case MONS_HARPY:
case MONS_FIRE_CRAB:
- return 20;
+ return 21;
case MONS_BOULDER_BEETLE:
case MONS_ORC_HIGH_PRIEST:
case MONS_PULSATING_LUMP:
- return 21;
+ return 22;
case MONS_BORING_BEETLE:
case MONS_CRYSTAL_GOLEM:
@@ -583,17 +584,17 @@ int mons_standard_level(monster_type mcls)
case MONS_REDBACK:
case MONS_SPHINX:
case MONS_VAPOUR:
- return 22;
+ return 23;
case MONS_ORC_SORCERER:
case MONS_SHINING_EYE:
- return 23;
+ return 24;
case MONS_BUMBLEBEE:
case MONS_ORC_WARLORD:
case MONS_IRON_TROLL:
case MONS_YAKTAUR_CAPTAIN:
- return 24;
+ return 25;
case MONS_DANCING_WEAPON:
case MONS_DEEP_TROLL:
@@ -603,17 +604,17 @@ int mons_standard_level(monster_type mcls)
case MONS_LICH:
case MONS_STONE_GIANT:
case MONS_ETTIN:
- return 25;
+ return 26;
case MONS_DEEP_ELF_CONJURER:
case MONS_PHANTASMAL_WARRIOR:
case MONS_STORM_DRAGON:
- return 26;
+ return 27;
case MONS_DEEP_ELF_PRIEST:
case MONS_GLOWING_SHAPESHIFTER:
case MONS_TENTACLED_MONSTROSITY:
- return 27;
+ return 28;
case MONS_ANCIENT_LICH:
case MONS_BONE_DRAGON:
@@ -627,11 +628,11 @@ int mons_standard_level(monster_type mcls)
case MONS_QUICKSILVER_DRAGON:
case MONS_SHADOW_DRAGON:
case MONS_TITAN:
- return 30;
+ return 31;
case MONS_DEEP_ELF_BLADEMASTER:
case MONS_DEEP_ELF_MASTER_ARCHER:
- return 33;
+ return 34;
case MONS_BIG_FISH:
case MONS_ELECTRIC_EEL:
@@ -926,12 +927,10 @@ int mons_standard_rare(monster_type mcls)
// The Dwarven Hall
int mons_dwarf_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_DWARVEN_HALL, 1);
-
if (!mons_dwarf_rare(mcls))
- return mlev + 99;
+ return 99;
// Depths are irrelevant for a depth-1 branch.
- return mlev + 1;
+ return 1;
}
int mons_dwarf_rare(monster_type mcls)
@@ -971,23 +970,19 @@ int mons_dwarf_rare(monster_type mcls)
// The Orcish Mines
int mons_mineorc_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_ORCISH_MINES, 1);
-
switch (mcls)
{
case MONS_HOBGOBLIN:
case MONS_ORC_PRIEST:
case MONS_ORC_WARRIOR:
- mlev++;
- break;
+ return 2;
case MONS_GNOLL:
case MONS_OGRE:
case MONS_WARG:
case MONS_ORC_KNIGHT:
case MONS_ORC_WIZARD:
- mlev += 2;
- break;
+ return 3;
case MONS_CYCLOPS:
case MONS_IRON_TROLL:
@@ -1002,20 +997,16 @@ int mons_mineorc_level(monster_type mcls)
case MONS_ETTIN:
case MONS_GNOLL_SHAMAN:
case MONS_GNOLL_SERGEANT:
- mlev += 3;
- break;
+ return 4;
case MONS_FUNGUS:
case MONS_GOBLIN:
case MONS_ORC:
- mlev += 0;
- break;
+ return 1;
default:
return 99;
}
-
- return (mlev);
}
int mons_mineorc_rare(monster_type mcls)
@@ -1072,8 +1063,6 @@ int mons_mineorc_rare(monster_type mcls)
// The Elven Halls
int mons_hallelf_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_ELVEN_HALLS, 1);
-
switch (mcls)
{
case MONS_DEEP_ELF_SOLDIER:
@@ -1087,8 +1076,7 @@ int mons_hallelf_level(monster_type mcls)
case MONS_DEEP_ELF_CONJURER:
case MONS_SHAPESHIFTER:
case MONS_ORC_KNIGHT:
- mlev += 1;
- break;
+ return 2;
case MONS_ORC_SORCERER:
case MONS_DEEP_ELF_PRIEST:
@@ -1096,28 +1084,22 @@ int mons_hallelf_level(monster_type mcls)
case MONS_DEEP_ELF_KNIGHT:
case MONS_ORC_PRIEST:
case MONS_ORC_HIGH_PRIEST:
- mlev += 2;
- break;
+ return 3;
case MONS_DEEP_ELF_HIGH_PRIEST:
case MONS_DEEP_ELF_DEMONOLOGIST:
case MONS_DEEP_ELF_ANNIHILATOR:
case MONS_DEEP_ELF_SORCERER:
case MONS_DEEP_ELF_DEATH_MAGE:
- mlev += 3;
- break;
+ return 4;
case MONS_DEEP_ELF_BLADEMASTER:
case MONS_DEEP_ELF_MASTER_ARCHER:
- mlev += 5;
- break;
+ return 7;
default:
- mlev += 99;
- break;
+ return 99;
}
-
- return (mlev);
}
int mons_hallelf_rare(monster_type mcls)
@@ -1174,7 +1156,7 @@ int mons_hallelf_rare(monster_type mcls)
case MONS_DEEP_ELF_BLADEMASTER:
case MONS_DEEP_ELF_MASTER_ARCHER:
- return 1;
+ return 3;
default:
return 0;
@@ -1184,8 +1166,6 @@ int mons_hallelf_rare(monster_type mcls)
// The Lair
int mons_lair_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_LAIR, 1);
-
switch (mcls)
{
case MONS_GIANT_GECKO:
@@ -1196,8 +1176,7 @@ int mons_lair_level(monster_type mcls)
case MONS_QUOKKA:
case MONS_GIANT_CENTIPEDE:
case MONS_IGUANA:
- mlev += 0;
- break;
+ return 1;
case MONS_GIANT_FROG:
case MONS_PORCUPINE:
@@ -1205,8 +1184,7 @@ int mons_lair_level(monster_type mcls)
case MONS_BLACK_BEAR:
case MONS_WORM:
case MONS_WOLF:
- mlev++;
- break;
+ return 2;
case MONS_FUNGUS:
case MONS_CROCODILE:
@@ -1214,8 +1192,7 @@ int mons_lair_level(monster_type mcls)
case MONS_GREEN_RAT:
case MONS_SCORPION:
case MONS_ADDER:
- mlev += 2;
- break;
+ return 3;
case MONS_WATER_MOCCASIN:
case MONS_BUTTERFLY:
@@ -1227,8 +1204,7 @@ int mons_lair_level(monster_type mcls)
case MONS_WAR_DOG:
case MONS_YELLOW_WASP:
case MONS_BASILISK:
- mlev += 3;
- break;
+ return 4;
case MONS_BLINK_FROG:
case MONS_AGATE_SNAIL:
@@ -1239,8 +1215,7 @@ int mons_lair_level(monster_type mcls)
case MONS_STEAM_DRAGON:
case MONS_YAK:
case MONS_GRIZZLY_BEAR:
- mlev += 4;
- break;
+ return 5;
case MONS_BLACK_MAMBA:
case MONS_BRAIN_WORM:
@@ -1252,8 +1227,7 @@ int mons_lair_level(monster_type mcls)
case MONS_TRAPDOOR_SPIDER:
case MONS_ROCK_WORM:
case MONS_CATOBLEPAS:
- mlev += 5;
- break;
+ return 6;
case MONS_ELEPHANT_SLUG:
case MONS_POLAR_BEAR:
@@ -1263,22 +1237,18 @@ int mons_lair_level(monster_type mcls)
case MONS_WANDERING_MUSHROOM:
case MONS_ELEPHANT:
case MONS_WOLF_SPIDER:
- mlev += 6;
- break;
+ return 7;
case MONS_BORING_BEETLE:
case MONS_BOULDER_BEETLE:
case MONS_DEATH_YAK:
case MONS_SPINY_WORM:
case MONS_FIRE_CRAB:
- mlev += 7;
- break;
+ return 8;
default:
return 99;
}
-
- return (mlev);
}
int mons_lair_rare(monster_type mcls)
@@ -1409,8 +1379,6 @@ int mons_lair_rare(monster_type mcls)
// The Swamp
int mons_swamp_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_SWAMP, 1);
-
switch (mcls)
{
case MONS_BAT:
@@ -1425,8 +1393,7 @@ int mons_swamp_level(monster_type mcls)
case MONS_SWAMP_WORM:
case MONS_GIANT_LEECH:
case MONS_ALLIGATOR:
- mlev++;
- break;
+ return 2;
case MONS_FUNGUS:
case MONS_NECROPHAGE:
@@ -1438,8 +1405,7 @@ int mons_swamp_level(monster_type mcls)
case MONS_AGATE_SNAIL:
case MONS_HYDRA:
case MONS_BOG_MUMMY:
- mlev += 2;
- break;
+ return 3;
case MONS_WATER_MOCCASIN:
case MONS_HUNGRY_GHOST:
@@ -1451,22 +1417,18 @@ int mons_swamp_level(monster_type mcls)
case MONS_SPINY_FROG:
case MONS_SWAMP_DRAGON:
case MONS_UGLY_THING:
- mlev += 3;
- break;
+ return 4;
case MONS_BLINK_FROG:
case MONS_SLIME_CREATURE:
case MONS_VERY_UGLY_THING:
case MONS_VAPOUR:
case MONS_TENTACLED_MONSTROSITY:
- mlev += 4;
- break;
+ return 5;
default:
- mlev += 99;
+ return 99;
}
-
- return (mlev);
}
int mons_swamp_rare(monster_type mcls)
@@ -1554,46 +1516,40 @@ int mons_swamp_rare(monster_type mcls)
// The Shoals
int mons_shoals_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_SHOALS, 1);
switch (mcls)
{
case MONS_BUTTERFLY:
case MONS_BAT:
- break;
+ return 1;
case MONS_MERFOLK:
case MONS_MERMAID:
case MONS_HIPPOGRIFF:
case MONS_CENTAUR:
case MONS_SEA_SNAKE:
- mlev++;
- break;
+ return 2;
case MONS_MANTICORE:
case MONS_SNAPPING_TURTLE:
case MONS_HARPY:
- mlev += 2;
- break;
+ return 3;
case MONS_CYCLOPS: // will have a sheep band
case MONS_SIREN:
case MONS_OKLOB_PLANT:
case MONS_SHARK:
case MONS_KRAKEN:
- mlev += 3;
- break;
+ return 4;
case MONS_ALLIGATOR_SNAPPING_TURTLE:
case MONS_MERFOLK_JAVELINEER:
case MONS_MERFOLK_IMPALER:
case MONS_MERFOLK_AQUAMANCER:
- mlev += 4;
- break;
+ return 5;
default:
- mlev += 99;
+ return 99;
}
- return mlev;
}
int mons_shoals_rare(monster_type mcls)
@@ -1645,40 +1601,31 @@ int mons_shoals_rare(monster_type mcls)
// The Snake Pit
int mons_pitsnake_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_SNAKE_PIT, 1);
-
switch (mcls)
{
case MONS_BALL_PYTHON:
case MONS_ADDER:
- mlev++;
- break;
+ return 2;
case MONS_WATER_MOCCASIN:
case MONS_BLACK_MAMBA:
case MONS_ANACONDA:
case MONS_NAGA:
- mlev += 2;
- break;
+ return 3;
case MONS_NAGA_WARRIOR:
case MONS_NAGA_MAGE:
- mlev += 3;
- break;
+ return 4;
case MONS_GUARDIAN_SERPENT:
- mlev += 4;
- break;
+ return 5;
case MONS_GREATER_NAGA:
- mlev += 5;
- break;
+ return 6;
default:
- mlev += 99;
+ return 99;
}
-
- return (mlev);
}
int mons_pitsnake_rare(monster_type mcls)
@@ -1715,8 +1662,6 @@ int mons_pitsnake_rare(monster_type mcls)
// The Spider Nest
int mons_spidernest_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_SPIDER_NEST, 1);
-
switch (mcls)
{
case MONS_GIANT_COCKROACH:
@@ -1725,16 +1670,14 @@ int mons_spidernest_level(monster_type mcls)
case MONS_SPIDER:
case MONS_GIANT_CENTIPEDE:
case MONS_WORM:
- mlev++;
- break;
+ return 2;
case MONS_YELLOW_WASP:
case MONS_REDBACK:
case MONS_TRAPDOOR_SPIDER:
case MONS_GOLIATH_BEETLE:
case MONS_ROCK_WORM:
- mlev += 2;
- break;
+ return 3;
case MONS_BORING_BEETLE:
case MONS_BOULDER_BEETLE:
@@ -1742,26 +1685,21 @@ int mons_spidernest_level(monster_type mcls)
case MONS_SPINY_WORM:
case MONS_ORB_SPIDER:
case MONS_JUMPING_SPIDER:
- mlev += 3;
- break;
+ return 4;
case MONS_EMPEROR_SCORPION:
case MONS_DEMONIC_CRAWLER:
case MONS_RED_WASP:
case MONS_WOLF_SPIDER:
- mlev += 4;
- break;
+ return 5;
case MONS_GHOST_MOTH:
case MONS_MOTH_OF_WRATH:
- mlev += 5;
- break;
+ return 6;
default:
- mlev += 99;
+ return 99;
}
-
- return (mlev);
}
int mons_spidernest_rare(monster_type mcls)
@@ -1819,50 +1757,40 @@ int mons_spidernest_rare(monster_type mcls)
// The Slime Pits
int mons_pitslime_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_SLIME_PITS, 1);
-
switch (mcls)
{
case MONS_JELLY:
case MONS_OOZE:
case MONS_ACID_BLOB:
case MONS_GIANT_EYEBALL:
- mlev++;
- break;
+ return 2;
case MONS_BROWN_OOZE:
case MONS_SLIME_CREATURE:
case MONS_EYE_OF_DRAINING:
- mlev += 2;
- break;
+ return 3;
case MONS_GIANT_AMOEBA:
case MONS_AZURE_JELLY:
case MONS_SHINING_EYE:
case MONS_GOLDEN_EYE:
- mlev += 3;
- break;
+ return 4;
case MONS_PULSATING_LUMP:
case MONS_GREAT_ORB_OF_EYES:
case MONS_EYE_OF_DEVASTATION:
- mlev += 4;
- break;
+ return 5;
case MONS_DEATH_OOZE:
case MONS_GIANT_ORANGE_BRAIN:
- mlev += 5;
- break;
+ return 6;
case MONS_ROYAL_JELLY:
- mlev += 6;
- break;
+ return 7;
default:
return 99;
}
-
- return (mlev);
}
int mons_pitslime_rare(monster_type mcls)
@@ -1907,24 +1835,18 @@ int mons_pitslime_rare(monster_type mcls)
// The Hive
int mons_hive_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_HIVE, 1);
-
switch (mcls)
{
case MONS_PLANT:
case MONS_KILLER_BEE:
- mlev += 0;
- break;
+ return 1;
case MONS_KILLER_BEE_LARVA:
- mlev++;
- break;
+ return 2;
default:
return 99;
}
-
- return (mlev);
}
int mons_hive_rare(monster_type mcls)
@@ -1948,7 +1870,9 @@ int mons_hive_rare(monster_type mcls)
// The Vaults
int mons_vaults_level(monster_type mcls)
{
- return mons_standard_level(mcls);
+ return mons_standard_level(mcls)
+ + absdungeon_depth(BRANCH_VAULTS, 1)
+ - absdungeon_depth(BRANCH_MAIN_DUNGEON, 1);
}
int mons_vaults_rare(monster_type mcls)
@@ -1960,9 +1884,9 @@ int mons_vaults_rare(monster_type mcls)
int mons_hallblade_level(monster_type mcls)
{
if (mcls == MONS_DANCING_WEAPON)
- return absdungeon_depth(BRANCH_HALL_OF_BLADES, 1);
+ return 1;
else
- return 0;
+ return 99;
}
int mons_hallblade_rare(monster_type mcls)
@@ -1973,21 +1897,17 @@ int mons_hallblade_rare(monster_type mcls)
// The Crypt
int mons_crypt_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_CRYPT, 1);
-
switch (mcls)
{
case MONS_ZOMBIE_SMALL:
- mlev += 0;
- break;
+ return 1;
case MONS_PHANTOM:
case MONS_SKELETON_SMALL:
case MONS_SKELETON_LARGE:
case MONS_ZOMBIE_LARGE:
case MONS_WIGHT:
- mlev++;
- break;
+ return 2;
case MONS_SHADOW:
case MONS_HUNGRY_GHOST:
@@ -1995,8 +1915,7 @@ int mons_crypt_level(monster_type mcls)
case MONS_SKELETAL_WARRIOR:
case MONS_SIMULACRUM_SMALL:
case MONS_SIMULACRUM_LARGE:
- mlev += 2;
- break;
+ return 3;
case MONS_NECROMANCER:
case MONS_PULSATING_LUMP:
@@ -2007,8 +1926,7 @@ int mons_crypt_level(monster_type mcls)
case MONS_WRAITH:
case MONS_FLYING_SKULL:
case MONS_SILENT_SPECTRE:
- mlev += 3;
- break;
+ return 4;
case MONS_BONE_DRAGON:
case MONS_FLAMING_CORPSE:
@@ -2020,21 +1938,17 @@ int mons_crypt_level(monster_type mcls)
case MONS_MUMMY:
case MONS_VAMPIRE:
case MONS_ABOMINATION_LARGE:
- mlev += 4;
- break;
+ return 5;
case MONS_REAPER:
case MONS_ANCIENT_LICH:
case MONS_LICH:
case MONS_CURSE_SKULL:
- mlev += 5;
- break;
+ return 6;
default:
- mlev += 99;
+ return 99;
}
-
- return (mlev);
}
int mons_crypt_rare(monster_type mcls)
@@ -2123,44 +2037,35 @@ int mons_crypt_rare(monster_type mcls)
// The Tomb
int mons_tomb_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_TOMB, 1);
-
switch (mcls)
{
case MONS_ZOMBIE_SMALL:
- mlev += 0;
- break;
+ return 1;
case MONS_MUMMY:
case MONS_ZOMBIE_LARGE:
case MONS_SKELETON_SMALL:
case MONS_SKELETON_LARGE:
case MONS_TRAPDOOR_SPIDER:
- mlev++;
- break;
+ return 2;
case MONS_GUARDIAN_MUMMY:
case MONS_FLYING_SKULL:
case MONS_SIMULACRUM_SMALL:
case MONS_SIMULACRUM_LARGE:
- mlev += 2;
- break;
+ return 3;
case MONS_LICH:
case MONS_ANCIENT_LICH:
case MONS_MUMMY_PRIEST:
- mlev += 3;
- break;
+ return 4;
case MONS_GREATER_MUMMY:
- mlev += 4;
- break;
+ return 5;
default:
- mlev += 99;
+ return 99;
}
-
- return (mlev);
}
int mons_tomb_rare(monster_type mcls)
@@ -2209,8 +2114,6 @@ int mons_tomb_rare(monster_type mcls)
// The Enchanted Forest
int mons_forest_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_FOREST, 1);
-
switch (mcls)
{
case MONS_SPRIGGAN:
@@ -2218,26 +2121,21 @@ int mons_forest_level(monster_type mcls)
case MONS_GRIZZLY_BEAR:
case MONS_BLACK_BEAR:
case MONS_WOLF:
- mlev++;
- break;
+ return 2;
case MONS_SPRIGGAN_RIDER:
- mlev += 2;
- break;
+ return 3;
case MONS_SPRIGGAN_AIR_MAGE:
case MONS_SPRIGGAN_BERSERKER:
- mlev += 3;
+ return 4;
case MONS_SPRIGGAN_DEFENDER:
- mlev += 5;
- break;
+ return 6;
default:
- mlev += 99;
+ return 99;
}
-
- return (mlev);
}
int mons_forest_rare(monster_type mcls)
@@ -2271,14 +2169,11 @@ int mons_forest_rare(monster_type mcls)
// The Halls of Zot
int mons_hallzot_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_HALL_OF_ZOT, 0);
-
switch (mcls)
{
case MONS_GOLDEN_DRAGON:
case MONS_GUARDIAN_MUMMY:
- mlev += 6;
- break;
+ return 6;
case MONS_BONE_DRAGON:
case MONS_KILLER_KLOWN:
case MONS_SHADOW_DRAGON:
@@ -2286,13 +2181,11 @@ int mons_hallzot_level(monster_type mcls)
case MONS_CURSE_TOE:
case MONS_ORB_GUARDIAN:
case MONS_GHOST_MOTH:
- mlev += 5;
- break;
+ return 5;
case MONS_DEATH_COB:
case MONS_DRAGON:
case MONS_ICE_DRAGON:
- mlev += 4;
- break;
+ return 4;
case MONS_MOTTLED_DRACONIAN:
case MONS_YELLOW_DRACONIAN:
case MONS_BLACK_DRACONIAN:
@@ -2310,21 +2203,15 @@ int mons_hallzot_level(monster_type mcls)
case MONS_DRACONIAN_ZEALOT:
case MONS_DRACONIAN_SHIFTER:
case MONS_TENTACLED_MONSTROSITY:
- mlev += 3;
- break;
+ return 3;
case MONS_MOTH_OF_WRATH:
- mlev += 2;
- break;
+ return 2;
case MONS_ORB_OF_FIRE:
case MONS_ELECTRIC_GOLEM:
- mlev += 1;
- break;
+ return 1;
default:
- mlev += 99; // I think this won't be a problem {dlb}
- break;
+ return 99;
}
-
- return (mlev);
}
int mons_hallzot_rare(monster_type mcls)
@@ -2384,12 +2271,10 @@ int mons_hallzot_rare(monster_type mcls)
// The Vestibule of Hell
int mons_vestibule_level(monster_type mcls)
{
- int mlev = absdungeon_depth(BRANCH_VESTIBULE_OF_HELL, 1);
-
if (!mons_vestibule_rare(mcls))
- return mlev + 99;
+ return 99;
// Depths are irrelevant for a depth-1 branch.
- return mlev + 1;
+ return 1;
}
int mons_vestibule_rare(monster_type mcls)
@@ -2436,8 +2321,6 @@ int mons_vestibule_rare(monster_type mcls)
// The Iron City of Dis
int mons_dis_level(monster_type mcls)
{
- int mlev = 26;
-
switch (mcls)
{
case MONS_CLAY_GOLEM:
@@ -2446,8 +2329,7 @@ int mons_dis_level(monster_type mcls)
case MONS_RED_DEVIL:
case MONS_SKELETAL_WARRIOR:
case MONS_ZOMBIE_LARGE:
- mlev++;
- break;
+ return 0;
case MONS_HELL_HOUND:
case MONS_HELL_KNIGHT:
@@ -2460,8 +2342,7 @@ int mons_dis_level(monster_type mcls)
case MONS_TORMENTOR:
case MONS_WIGHT:
case MONS_ZOMBIE_SMALL:
- mlev += 2;
- break;
+ return 1;
case MONS_EFREET:
case MONS_FLYING_SKULL:
@@ -2469,8 +2350,7 @@ int mons_dis_level(monster_type mcls)
case MONS_HELL_HOG:
case MONS_IRON_GOLEM:
case MONS_MUMMY:
- mlev += 3;
- break;
+ return 2;
case MONS_FLAYED_GHOST:
case MONS_FREEZING_WRAITH:
@@ -2479,8 +2359,7 @@ int mons_dis_level(monster_type mcls)
case MONS_IRON_IMP:
case MONS_VAMPIRE:
case MONS_WRAITH:
- mlev += 4;
- break;
+ return 3;
case MONS_BLUE_DEVIL:
case MONS_DANCING_WEAPON:
@@ -2491,21 +2370,17 @@ int mons_dis_level(monster_type mcls)
case MONS_PHANTASMAL_WARRIOR:
case MONS_REAPER:
case MONS_SOUL_EATER:
- mlev += 5;
- break;
+ return 4;
case MONS_ANCIENT_LICH:
case MONS_BONE_DRAGON:
case MONS_BRIMSTONE_FIEND:
case MONS_IRON_DRAGON:
- mlev += 6;
- break;
+ return 5;
default:
- return 0;
+ return 99;
}
-
- return (mlev);
}
int mons_dis_rare(monster_type mcls)
@@ -2597,8 +2472,6 @@ int mons_dis_rare(monster_type mcls)
// Gehenna - the fire hell
int mons_gehenna_level(monster_type mcls)
{
- int mlev = 26;
-
switch (mcls)
{
case MONS_CLAY_GOLEM:
@@ -2607,16 +2480,14 @@ int mons_gehenna_level(monster_type mcls)
case MONS_SKELETON_SMALL:
case MONS_ZOMBIE_LARGE:
case MONS_ZOMBIE_SMALL:
- mlev++;
- break;
+ return 0;
case MONS_HELL_HOG:
case MONS_HELL_HOUND:
case MONS_CRIMSON_IMP:
case MONS_NECROPHAGE:
case MONS_STONE_GOLEM:
- mlev += 2;
- break;
+ return 1;
case MONS_FLYING_SKULL:
case MONS_IRON_GOLEM:
@@ -2625,14 +2496,12 @@ int mons_gehenna_level(monster_type mcls)
case MONS_ROTTING_DEVIL:
case MONS_SHADOW:
case MONS_WIGHT:
- mlev += 3;
- break;
+ return 2;
case MONS_HELL_KNIGHT:
case MONS_VAMPIRE:
case MONS_WRAITH:
- mlev += 4;
- break;
+ return 3;
case MONS_EFREET:
case MONS_FLAMING_CORPSE:
@@ -2641,8 +2510,7 @@ int mons_gehenna_level(monster_type mcls)
case MONS_TORMENTOR:
case MONS_FIRE_CRAB:
case MONS_BALRUG:
- mlev += 5;
- break;
+ return 4;
case MONS_ANCIENT_LICH:
case MONS_BONE_DRAGON:
@@ -2652,14 +2520,11 @@ int mons_gehenna_level(monster_type mcls)
case MONS_HELL_SENTINEL:
case MONS_REAPER:
case MONS_SOUL_EATER:
- mlev += 6;
- break;
+ return 5;
default:
- return 0;
+ return 99;
}
-
- return (mlev);
}
int mons_gehenna_rare(monster_type mcls)
@@ -2753,8 +2618,6 @@ int mons_gehenna_rare(monster_type mcls)
// Cocytus - the ice hell
int mons_cocytus_level(monster_type mcls)
{
- int mlev = 26;
-
switch (mcls)
{
case MONS_SKELETON_LARGE:
@@ -2765,52 +2628,44 @@ int mons_cocytus_level(monster_type mcls)
case MONS_ZOMBIE_SMALL:
case MONS_SIMULACRUM_LARGE:
case MONS_SIMULACRUM_SMALL:
- mlev++;
- break;
+ return 0;
case MONS_BLUE_DEVIL:
case MONS_ICE_BEAST:
case MONS_PHANTOM:
case MONS_SHADOW:
- mlev += 2;
- break;
+ return 1;
case MONS_FLYING_SKULL:
case MONS_ROTTING_DEVIL:
case MONS_VAMPIRE:
case MONS_WIGHT:
- mlev += 3;
- break;
+ return 2;
case MONS_FREEZING_WRAITH:
case MONS_HUNGRY_GHOST:
case MONS_MUMMY:
case MONS_PHANTASMAL_WARRIOR:
case MONS_WRAITH:
- mlev += 4;
- break;
+ return 3;
case MONS_ICE_DEVIL:
case MONS_ICE_DRAGON:
case MONS_TORMENTOR:
case MONS_WHITE_IMP:
case MONS_BLIZZARD_DEMON:
- mlev += 5;
- break;
+ return 4;
case MONS_ANCIENT_LICH:
case MONS_BONE_DRAGON:
case MONS_LICH:
case MONS_REAPER:
case MONS_SOUL_EATER:
- mlev += 6;
- break;
+ return 5;
default:
- return 0;
+ return 99;
}
-
- return (mlev);
}
int mons_cocytus_rare(monster_type mcls)
@@ -2894,8 +2749,6 @@ int mons_cocytus_rare(monster_type mcls)
// Tartarus - the undead hell
int mons_tartarus_level(monster_type mcls)
{
- int mlev = 26;
-
switch (mcls)
{
case MONS_CRIMSON_IMP:
@@ -2904,8 +2757,7 @@ int mons_tartarus_level(monster_type mcls)
case MONS_SHADOW_IMP:
case MONS_SKELETAL_WARRIOR:
case MONS_SKELETON_SMALL:
- mlev++;
- break;
+ return 0;
case MONS_HELL_KNIGHT:
case MONS_NECROPHAGE:
@@ -2913,8 +2765,7 @@ int mons_tartarus_level(monster_type mcls)
case MONS_WIGHT:
case MONS_ZOMBIE_LARGE:
case MONS_ZOMBIE_SMALL:
- mlev += 2;
- break;
+ return 1;
case MONS_FREEZING_WRAITH:
case MONS_HELL_HOUND:
@@ -2922,8 +2773,7 @@ int mons_tartarus_level(monster_type mcls)
case MONS_SHADOW:
case MONS_WRAITH:
case MONS_SILENT_SPECTRE:
- mlev += 3;
- break;
+ return 2;
case MONS_BLUE_DEVIL:
case MONS_BONE_DRAGON:
@@ -2935,8 +2785,7 @@ int mons_tartarus_level(monster_type mcls)
case MONS_TORMENTOR:
case MONS_SIMULACRUM_LARGE:
case MONS_SIMULACRUM_SMALL:
- mlev += 4;
- break;
+ return 3;
case MONS_FLYING_SKULL:
case MONS_HELLION:
@@ -2945,20 +2794,16 @@ int mons_tartarus_level(monster_type mcls)
case MONS_ROTTING_DEVIL:
case MONS_SHADOW_DRAGON:
case MONS_VAMPIRE:
- mlev += 5;
- break;
+ return 4;
case MONS_ANCIENT_LICH:
case MONS_LICH:
case MONS_SOUL_EATER:
- mlev += 6;
- break;
+ return 5;
default:
- return 0;
+ return 99;
}
-
- return (mlev);
}
int mons_tartarus_rare(monster_type mcls)
diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc
index 25bf36e990..6bf1a88acb 100644
--- a/crawl-ref/source/mon-place.cc
+++ b/crawl-ref/source/mon-place.cc
@@ -165,6 +165,10 @@ bool monster_habitable_grid(monster_type mt,
if (actual_grid == DNGN_OPEN_SEA || actual_grid == DNGN_LAVA_SEA)
return (false);
+ // Monsters can't use teleporters, and standing there would look just wrong.
+ if (actual_grid == DNGN_TELEPORTER)
+ return (false);
+
const dungeon_feature_type feat_preferred =
habitat2grid(mons_class_primary_habitat(mt));
const dungeon_feature_type feat_nonpreferred =
@@ -235,7 +239,7 @@ bool monster_can_submerge(const monster* mon, dungeon_feature_type feat)
return (feat == DNGN_LAVA);
case HT_LAND:
// Currently, trapdoor spider and air elemental only.
- return (feat_is_floor(feat));
+ return (feat == DNGN_FLOOR);
default:
return (false);
}
@@ -521,9 +525,6 @@ monster_type pick_random_monster(const level_id &place, int power,
lev_mons = power;
- if (place == BRANCH_MAIN_DUNGEON && one_chance_in(4))
- lev_mons = random2(power);
-
const int original_level = lev_mons;
// OODs do not apply to the Abyss, Pan, etc.
@@ -858,23 +859,6 @@ monster_type pick_random_monster_for_place(const level_id &place,
return (chosen);
}
-// Given a monster_type that includes meta-monster types such as
-// RANDOM_MONSTER, converts them into a level-appropriate monster.
-monster_type resolve_monster_type(monster_type mon_type,
- dungeon_feature_type feat)
-{
- monster_type base = MONS_NO_MONSTER;
- coord_def dummy(GXM - 1, GYM - 1);
- unwind_var<dungeon_feature_type> dummgrid(grd(dummy), feat);
- dungeon_char_type stair_type = NUM_DCHAR_TYPES;
- int level = env.absdepth0;
- bool chose_ood = false;
-
- return _resolve_monster_type(mon_type, PROX_ANYWHERE, base,
- dummy, 0, &stair_type, &level,
- &chose_ood);
-}
-
// A short function to check the results of near_stairs().
// Returns 0 if the point is not near stairs.
// Returns 1 if the point is near unoccupied stairs.
@@ -1728,8 +1712,7 @@ static monster* _place_monster_aux(const mgen_data &mg,
blame_prefix = "summoned by ";
if (mg.summoner != NULL && mg.summoner->alive()
- && mg.summoner->is_monster()
- && static_cast<const monster* >(mg.summoner)->type == MONS_MARA)
+ && mg.summoner->type == MONS_MARA)
{
blame_prefix = "woven by ";
}
@@ -1738,16 +1721,13 @@ static monster* _place_monster_aux(const mgen_data &mg,
blame_prefix = "animated by ";
else if (mg.summon_type == SPELL_STICKS_TO_SNAKES)
blame_prefix = "transmuted by ";
- else
+ else if (mg.cls == MONS_ELDRITCH_TENTACLE
+ || mg.cls == MONS_ELDRITCH_TENTACLE_SEGMENT)
{
- blame_prefix = "created by ";
-
- if (mg.cls == MONS_ELDRITCH_TENTACLE
- || mg.cls == MONS_ELDRITCH_TENTACLE_SEGMENT)
- {
- blame_prefix = "called by ";
- }
+ blame_prefix = "called by ";
}
+ else
+ blame_prefix = "created by ";
if (!mg.non_actor_summoner.empty())
mons_add_blame(mon, blame_prefix + mg.non_actor_summoner);
diff --git a/crawl-ref/source/mon-place.h b/crawl-ref/source/mon-place.h
index c463a9d979..47b8333c7b 100644
--- a/crawl-ref/source/mon-place.h
+++ b/crawl-ref/source/mon-place.h
@@ -56,11 +56,6 @@ void define_zombie(monster* mon, monster_type ztype, monster_type cs);
bool downgrade_zombie_to_skeleton(monster* mon);
-// Converts a monster_type involving RANDOM_MONSTER and similar into an
-// explicit monster type usable on the current level.
-monster_type resolve_monster_type(monster_type mon_type,
- dungeon_feature_type feat);
-
// Picks a monster eligible for random generation at the given place,
// optionally picking monsters that can be zombified into the target zombie,
// and optionally increasing monster level by the provided OOD factors.
diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc
index 4fb3531462..df76091c1e 100644
--- a/crawl-ref/source/mon-project.cc
+++ b/crawl-ref/source/mon-project.cc
@@ -165,7 +165,7 @@ static void _fuzz_direction(monster& mon, int pow)
const float off = (coinflip() ? -1 : 1) * 0.25;
float tan = (random2(31) - 15) * 0.019; // approx from degrees
tan *= 75.0 / pow;
- if (wearing_amulet(AMU_INACCURACY))
+ if (player_effect_inaccuracy())
tan *= 2;
// Cast either from left or right hand.
@@ -538,3 +538,306 @@ void iood_catchup(monster* mons, int pturns)
if (_iood_catchup_move(mon))
return;
}
+
+bool boulder_start(monster *mon, bolt *beam)
+{
+ mon->add_ench(ENCH_ROLLING);
+ simple_monster_message(mon, " curls into a ball and starts rolling!");
+ // Work out x/y/vx/vy from beam
+ beam->choose_ray();
+ mon->props["boulder_x"].get_float() = beam->ray.r.start.x - 0.5;
+ mon->props["boulder_y"].get_float() = beam->ray.r.start.y - 0.5;
+ mon->props["boulder_vx"].get_float() = beam->ray.r.dir.x;
+ mon->props["boulder_vy"].get_float() = beam->ray.r.dir.y;
+ boulder_act(*mon);
+ return true;
+}
+bool boulder_flee(monster *mon, bolt *beam)
+{
+ mon->add_ench(ENCH_ROLLING);
+ simple_monster_message(mon, " curls into a ball and rolls away!");
+ // Work out x/y/vx/vy from beam
+ beam->choose_ray();
+ mon->props["boulder_x"].get_float() = beam->ray.r.start.x - 0.5;
+ mon->props["boulder_y"].get_float() = beam->ray.r.start.y - 0.5;
+ mon->props["boulder_vx"].get_float() = -beam->ray.r.dir.x;
+ mon->props["boulder_vy"].get_float() = -beam->ray.r.dir.y;
+ boulder_act(*mon);
+ return true;
+}
+
+static void _boulder_stop(monster& mon, bool msg = true)
+{
+ if (mon.type==MONS_BOULDER_BEETLE)
+ {
+ /*
+ if (msg)
+ simple_monster_message(&mon, " comes to a halt.");
+ */
+
+ mon.del_ench(ENCH_ROLLING,!msg);
+ }
+}
+
+// Alas, too much differs to reuse beam shield blocks :(
+static bool _boulder_shielded(monster& mon, actor &victim)
+{
+ if (!victim.shield() || victim.incapacitated())
+ return (false);
+
+ const int to_hit = 15 + mon.hit_dice/2;
+ const int con_block = random2(to_hit + victim.shield_block_penalty());
+ const int pro_block = victim.shield_bonus();
+ dprf("boulder shield: pro %d, con %d", pro_block, con_block);
+ return (pro_block >= con_block);
+}
+
+static bool _boulder_hit(monster& mon, const coord_def &pos)
+{
+ bolt beam;
+ beam.name = "rolling boulder";
+ beam.flavour = BEAM_MISSILE;
+ beam.attitude = mon.attitude;
+
+ actor *caster = &mon;
+ beam.set_agent(caster);
+ beam.colour = WHITE;
+ beam.glyph = dchar_glyph(DCHAR_FIRED_BURST);
+ beam.range = 1;
+ beam.source = pos;
+ beam.target = pos;
+ beam.hit = AUTOMATIC_HIT;
+ beam.source_name = mon.name(DESC_PLAIN, true);
+
+ beam.damage = dice_def(3, 20);
+
+ beam.ex_size = 1;
+ beam.loudness = 5;
+
+ beam.fire();
+
+ return (true);
+}
+
+bool boulder_act(monster& mon)
+{
+ // Handles Boulder Beetle in Rolling form
+ // returns true if stopped rolling
+
+ float x = mon.props["boulder_x"];
+ float y = mon.props["boulder_y"];
+ float vx = mon.props["boulder_vx"];
+ float vy = mon.props["boulder_vy"];
+
+ dprf("boulder_act: pos=(%d,%d) rpos=(%f,%f) v=(%f,%f) foe=%d",
+ mon.pos().x, mon.pos().y,
+ x, y, vx, vy, mon.foe);
+
+ if (!vx && !vy) // not initialized
+ {
+ _boulder_stop(mon);
+ return (true);
+ }
+
+ _normalize(vx, vy);
+ /* IOOD swerving code, could reinstigate if it make boulders more fun
+ const actor *foe = mon.get_foe();
+ // If the target is gone, the orb continues on a ballistic course since
+ // picking a new one would require intelligence.
+
+ if (foe)
+ {
+ const coord_def target = foe->pos();
+ float dx = target.x - x;
+ float dy = target.y - y;
+ _normalize(dx, dy);
+
+ // Special case:
+ // Moving diagonally when the orb is just about to hit you
+ // 2
+ // ->*1
+ // (from 1 to 2) would be a guaranteed escape. This may be
+ // realistic (strafing!), but since the game has no non-cheesy
+ // means of waiting a small fraction of a turn, we don't want it.
+ const int old_t_pos = mon.props["iood_tpos"].get_short();
+ const coord_def rpos(static_cast<int>(round(x)), static_cast<int>(round(y)));
+ if (old_t_pos && old_t_pos != (256 * target.x + target.y)
+ && (rpos - target).rdist() <= 1
+ // ... but following an orb is ok.
+ && _in_front(vx, vy, dx, dy, 1.5)) // ~97 degrees
+ {
+ vx = dx;
+ vy = dy;
+ }
+ mon.props["iood_tpos"].get_short() = 256 * target.x + target.y;
+
+ if (!_in_front(vx, vy, dx, dy, 0.3)) // ~17 degrees
+ {
+ float ax, ay;
+ if (dy*vx < dx*vy)
+ ax = vy, ay = -vx, dprf("iood: veering left");
+ else
+ ax = -vy, ay = vx, dprf("iood: veering right");
+ vx += ax * 0.3;
+ vy += ay * 0.3;
+ }
+ else
+ dprf("iood: keeping course");
+
+ _normalize(vx, vy);
+ mon.props["iood_vx"] = vx;
+ mon.props["iood_vy"] = vy;
+ }
+ */
+move_again:
+
+ x += vx;
+ y += vy;
+
+ mon.props["boulder_x"] = x;
+ mon.props["boulder_y"] = y;
+// mon.props["iood_distance"].get_int()++;
+
+ const coord_def pos(static_cast<int>(round(x)), static_cast<int>(round(y)));
+ if (!in_bounds(pos))
+ {
+ _boulder_stop(mon);
+ return (true);
+ }
+
+ if (pos == mon.pos())
+ return (false);
+
+ // Place a dust trail (so we can see which way it's rolling)
+ place_cloud(CLOUD_DUST_TRAIL, mon.pos(), 2 + random2(3), &mon);
+
+ actor *victim = actor_at(pos);
+ if (cell_is_solid(pos) || victim)
+ {
+ if (cell_is_solid(pos))
+ {
+ if (you.see_cell(pos))
+ {
+ mprf("%s hits %s", mon.name(DESC_THE, true).c_str(),
+ feature_description(pos, false, DESC_A).c_str());
+ }
+ _boulder_stop(mon,you.see_cell(pos));
+ }
+
+ monster* mons = (victim && victim->atype() == ACT_MONSTER) ?
+ (monster*) victim : 0;
+
+ if (mons && mons_is_boulder(mons))
+ {
+ if (mon.observable())
+ mpr("The boulders collide with a stupendous crash!");
+ else
+ noisy(20, pos, "You hear a loud crashing sound!");
+
+ // Remove ROLLING and add DAZED
+ mon.del_ench(ENCH_ROLLING,true);
+ mons->del_ench(ENCH_ROLLING,true);
+ mon.add_ench(ENCH_CONFUSION);
+ mons->add_ench(ENCH_CONFUSION);
+ return (true);
+ }
+
+ if (mons && mons->submerged())
+ {
+ // Try to swap with the submerged creature.
+ if (mons->is_habitable(mon.pos()))
+ {
+ dprf("boulder: Swapping with a submerged monster.");
+ mons->set_position(mon.pos());
+ mon.set_position(pos);
+ mgrd(mons->pos()) = mons->mindex();
+ mgrd(pos) = mon.mindex();
+
+ return (false);
+ }
+ else // if swap fails, move ahead
+ {
+ dprf("boulder: Boosting above a submerged monster (can't swap).");
+ mon.lose_energy(EUT_MOVE);
+ goto move_again;
+ }
+ }
+
+ if (victim && _boulder_shielded(mon, *victim))
+ {
+ item_def *shield = victim->shield();
+ if (!shield_reflects(*shield))
+ {
+ if (victim->atype() == ACT_PLAYER)
+ {
+ mprf("You block %s.", mon.name(DESC_THE, true).c_str());
+ }
+ else
+ {
+ simple_monster_message(mons, (" blocks "
+ + mon.name(DESC_THE, true) + ".").c_str());
+ }
+ victim->shield_block_succeeded(&mon);
+ _boulder_stop(mon);
+ return (true);
+ }
+
+ if (victim->atype() == ACT_PLAYER)
+ {
+ mprf("Your %s reflects %s!",
+ shield->name(DESC_PLAIN).c_str(),
+ mon.name(DESC_THE, true).c_str());
+ ident_reflector(shield);
+ }
+ else if (you.see_cell(pos))
+ {
+ if (victim->observable())
+ {
+ mprf("%s reflects %s with %s %s!",
+ victim->name(DESC_THE, true).c_str(),
+ mon.name(DESC_THE, true).c_str(),
+ mon.pronoun(PRONOUN_POSSESSIVE).c_str(),
+ shield->name(DESC_PLAIN).c_str());
+ ident_reflector(shield);
+ }
+ else
+ {
+ mprf("%s bounces off thin air!",
+ mon.name(DESC_THE, true).c_str());
+ }
+ }
+ victim->shield_block_succeeded(&mon);
+
+ mon.props["boulder_vx"] = vx = -vx;
+ mon.props["boulder_vy"] = vy = -vy;
+
+ // Need to get out of the victim's square.
+
+ mon.lose_energy(EUT_MOVE);
+ goto move_again;
+ }
+
+ // Yay for inconsistencies in beam-vs-player and beam-vs-monsters.
+ if (victim == &you)
+ mprf("%s hits you!", mon.name(DESC_THE, true).c_str());
+
+ if (_boulder_hit(mon, pos))
+ {
+ if (victim && victim->alive())
+ _boulder_stop(mon);
+ return (true);
+ }
+ }
+
+ if (!mon.move_to_pos(pos))
+ {
+ _boulder_stop(mon);
+ return (true);
+ }
+
+ // move_to_pos() just trashed the coords, set them again
+ mon.props["boulder_x"] = x;
+ mon.props["boulder_y"] = y;
+
+ return (false);
+}
diff --git a/crawl-ref/source/mon-project.h b/crawl-ref/source/mon-project.h
index 0b953be357..f03666022f 100644
--- a/crawl-ref/source/mon-project.h
+++ b/crawl-ref/source/mon-project.h
@@ -15,5 +15,8 @@ spret_type cast_iood(actor *caster, int pow, bolt *beam,
void cast_iood_burst(int pow, coord_def target);
bool iood_act(monster& mon, bool no_trail = false);
void iood_catchup(monster* mon, int turns);
+bool boulder_start(monster *mon, bolt *beam);
+bool boulder_flee(monster *mon, bolt *beam);
+bool boulder_act(monster& mon);
#endif
diff --git a/crawl-ref/source/mon-speak.cc b/crawl-ref/source/mon-speak.cc
index 56e9098397..623376e976 100644
--- a/crawl-ref/source/mon-speak.cc
+++ b/crawl-ref/source/mon-speak.cc
@@ -429,6 +429,10 @@ bool mons_speaks(monster* mons)
if (mons->berserk())
return (false);
+ // Rolling beetles shouldn't twitch antennae
+ if (mons->rolling())
+ return (false);
+
// Monsters in a battle frenzy are likewise occupied.
// But roused holy creatures are not.
if (mons->has_ench(ENCH_BATTLE_FRENZY) && !one_chance_in(3))
diff --git a/crawl-ref/source/mon-spll.h b/crawl-ref/source/mon-spll.h
index 73038813ef..0cb588e6f8 100644
--- a/crawl-ref/source/mon-spll.h
+++ b/crawl-ref/source/mon-spll.h
@@ -390,7 +390,7 @@
SPELL_CANTRIP,
SPELL_SMITING,
SPELL_NO_SPELL,
- SPELL_MINOR_HEALING
+ SPELL_HEAL_OTHER
}
},
@@ -401,7 +401,7 @@
SPELL_SUMMON_DEMON,
SPELL_SMITING,
SPELL_ANIMATE_DEAD,
- SPELL_MINOR_HEALING
+ SPELL_HEAL_OTHER
}
},
@@ -1467,7 +1467,7 @@
SPELL_ISKENDERUNS_MYSTIC_BLAST,
SPELL_BOLT_OF_COLD,
SPELL_INVISIBILITY,
- SPELL_ANIMATE_DEAD,
+ SPELL_NO_SPELL,
SPELL_IRON_SHOT,
SPELL_INVISIBILITY
}
diff --git a/crawl-ref/source/mon-stuff.cc b/crawl-ref/source/mon-stuff.cc
index 0813463fa5..69f5b65b00 100644
--- a/crawl-ref/source/mon-stuff.cc
+++ b/crawl-ref/source/mon-stuff.cc
@@ -562,13 +562,11 @@ void record_monster_defeat(monster* mons, killer_type killer)
#if TAG_MAJOR_VERSION <= 33
void note_montiers()
{
-#if 0
char buf[128];
snprintf(buf, sizeof(buf), "Killed monsters: %d trivial, %d easy, "
"%d tough, %d nasty; %d corpses", you.montiers[0], you.montiers[1],
you.montiers[2], you.montiers[3], you.montiers[4]);
take_note(Note(NOTE_MESSAGE, 0, 0, buf));
-#endif
for (unsigned int i = 0; i < ARRAYSZ(you.montiers); i++)
you.montiers[i] = 0;
}
@@ -1627,7 +1625,9 @@ int monster_die(monster* mons, killer_type killer,
mpr("You feel the power of Trog in you as your rage grows.",
MSGCH_GOD, GOD_TROG);
}
- else if (wearing_amulet(AMU_RAGE) && one_chance_in(30))
+ else if (!you.suppressed()
+ && wearing_amulet(AMU_RAGE)
+ && one_chance_in(30))
{
const int bonus = (2 + random2(4)) / 2;
@@ -2320,7 +2320,10 @@ int monster_die(monster* mons, killer_type killer,
// Make sure that the monster looks dead.
if (mons->alive() && !in_transit && (!summoned || duration > 0))
mons->hit_points = -1;
- mons_speaks(mons);
+ // Hack: with cleanup_dead=false, a tentacle [segment] of a dead
+ // [malign] kraken has no valid head reference.
+ if (!mons_is_tentacle(mons->type))
+ mons_speaks(mons);
}
if (mons->type == MONS_BORIS && !in_transit)
@@ -2424,10 +2427,14 @@ int monster_die(monster* mons, killer_type killer,
}
if (!wizard && !submerged && !was_banished)
- _monster_die_cloud(mons, !mons_reset && !fake_abjuration && !unsummoned && !timeout, silent, summoned);
+ {
+ _monster_die_cloud(mons, !mons_reset && !fake_abjuration && !unsummoned
+ && !timeout, silent, summoned);
+ }
int corpse = -1;
- if (!mons_reset && !summoned && !fake_abjuration && !unsummoned && !timeout && !was_banished)
+ if (!mons_reset && !summoned && !fake_abjuration && !unsummoned
+ && !timeout && !was_banished)
{
// Have to add case for disintegration effect here? {dlb}
int corpse2 = -1;
@@ -3581,6 +3588,13 @@ monster* choose_random_monster_on_level(int weight,
for (; ri; ++ri)
{
+ if (in_sight)
+ {
+ // Seeing through glass/trees is not enough.
+ if (!you.see_cell_no_trans(*ri))
+ continue;
+ }
+
if (monster* mon = monster_at(*ri))
{
if (suitable(mon))
@@ -4299,8 +4313,8 @@ bool monster_space_valid(const monster* mons, coord_def target,
return monster_habitable_grid(mons, grd(target));
}
-bool monster_random_space(const monster* mons, coord_def& target,
- bool forbid_sanctuary)
+static bool _monster_random_space(const monster* mons, coord_def& target,
+ bool forbid_sanctuary)
{
int tries = 0;
while (tries++ < 1000)
@@ -4313,15 +4327,6 @@ bool monster_random_space(const monster* mons, coord_def& target,
return (false);
}
-bool monster_random_space(monster_type mon, coord_def& target,
- bool forbid_sanctuary)
-{
- monster dummy;
- dummy.type = mon;
-
- return (monster_random_space(&dummy, target, forbid_sanctuary));
-}
-
void monster_teleport(monster* mons, bool instan, bool silent)
{
if (!instan)
@@ -4373,7 +4378,7 @@ void monster_teleport(monster* mons, bool instan, bool silent)
}
if (newpos.origin())
- monster_random_space(mons, newpos, !mons->wont_attack());
+ _monster_random_space(mons, newpos, !mons->wont_attack());
// XXX: If the above function didn't find a good spot, return now
// rather than continue by slotting the monster (presumably)
diff --git a/crawl-ref/source/mon-stuff.h b/crawl-ref/source/mon-stuff.h
index 05d74061f8..245e8e2d19 100644
--- a/crawl-ref/source/mon-stuff.h
+++ b/crawl-ref/source/mon-stuff.h
@@ -183,10 +183,6 @@ bool is_item_jelly_edible(const item_def &item);
bool monster_space_valid(const monster* mons, coord_def target,
bool forbid_sanctuary);
-bool monster_random_space(const monster* mons, coord_def& target,
- bool forbid_sanctuary = false);
-bool monster_random_space(monster_type mon, coord_def& target,
- bool forbid_sanctuary = false);
void monster_teleport(monster* mons, bool instan, bool silent = false);
void mons_clear_trapping_net(monster* mon);
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 41010fdb01..484c6b02c6 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -41,6 +41,7 @@
#include "mon-stuff.h"
#include "notes.h"
#include "options.h"
+#include "orb.h"
#include "random.h"
#include "religion.h"
#include "showsymb.h"
@@ -86,7 +87,7 @@ static int _mons_exp_mod(monster_type mclass);
/* ******************** BEGIN PUBLIC FUNCTIONS ******************** */
-habitat_type grid2habitat(dungeon_feature_type grid)
+static habitat_type _grid2habitat(dungeon_feature_type grid)
{
if (feat_is_watery(grid))
return (HT_WATER);
@@ -149,7 +150,7 @@ monster_type random_monster_at_grid(dungeon_feature_type grid)
if (!initialised_randmons)
_initialise_randmons();
- const habitat_type ht = grid2habitat(grid);
+ const habitat_type ht = _grid2habitat(grid);
const std::vector<monster_type> &valid_mons = monsters_by_habitat[ht];
ASSERT(!valid_mons.empty());
@@ -535,6 +536,11 @@ bool mons_is_projectile(monster_type mc)
return (mc == MONS_ORB_OF_DESTRUCTION);
}
+bool mons_is_boulder(const monster* mon)
+{
+ return (mon->type == MONS_BOULDER_BEETLE && mon->rolling());
+}
+
// Conjuration or Hexes. Summoning and Necromancy make the monster a creature
// at least in some degree, golems have a chem granting them that.
bool mons_is_object(monster_type mc)
@@ -878,6 +884,14 @@ void discover_mimic(const coord_def& pos, bool wake)
mimic->seen_context = SC_JUST_SEEN;
}
+ // Orb mimics shriek.
+ if (item && item->base_type == OBJ_ORBS)
+ {
+ orb_pickup_noise(pos, 30,
+ "The orb mimic lets out a hideous shriek!",
+ "The orb mimic lets out a furious burst of light!");
+ }
+
// Just in case there's another one.
if (mimic_at(pos))
discover_mimic(pos);
@@ -1382,7 +1396,7 @@ mon_attack_def mons_attack_spec(const monster* mon, int attk_number)
const bool zombified = mons_is_zombified(mon);
- if (attk_number < 0 || attk_number > 3 || mon->has_hydra_multi_attack())
+ if (attk_number < 0 || attk_number >= MAX_NUM_ATTACKS || mon->has_hydra_multi_attack())
attk_number = 0;
if (mons_is_ghost_demon(mc))
@@ -4185,6 +4199,14 @@ int get_dist_to_nearest_monster()
return (minRange);
}
+bool monster_nearby()
+{
+ for (radius_iterator ri(you.get_los()); ri; ++ri)
+ if (monster_at(*ri))
+ return true;
+ return false;
+}
+
actor *actor_by_mid(mid_t m)
{
if (m == MID_PLAYER)
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 960398667d..31e1e2ab8e 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -124,7 +124,7 @@ struct monsterentry
short resist_magic; // (positive is ??)
// max damage in a turn is total of these four?
- mon_attack_def attack[4];
+ mon_attack_def attack[MAX_NUM_ATTACKS];
// hpdice[4]: [0]=HD [1]=min_hp [2]=rand_hp [3]=add_hp
// min hp = [0]*[1]+[3] & max hp = [0]*([1]+[2])+[3])
@@ -159,7 +159,6 @@ enum mon_threat_level_type
MTHRT_UNDEF,
};
-habitat_type grid2habitat(dungeon_feature_type grid);
dungeon_feature_type habitat2grid(habitat_type ht);
monsterentry *get_monster_data(monster_type mc);
@@ -365,6 +364,7 @@ bool herd_monster(const monster* mon);
int cheibriados_monster_player_speed_delta(const monster* mon);
bool cheibriados_thinks_mons_is_fast(const monster* mon);
bool mons_is_projectile(monster_type mc);
+bool mons_is_boulder(const monster * mon);
bool mons_is_object(monster_type mc);
bool mons_has_blood(monster_type mc);
bool mons_is_sensed(monster_type mc);
@@ -421,6 +421,7 @@ bool player_or_mon_in_sanct(const monster* mons);
bool mons_is_immotile(const monster* mons);
int get_dist_to_nearest_monster();
+bool monster_nearby();
actor *actor_by_mid(mid_t m);
monster *monster_by_mid(mid_t m);
diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc
index d8a0f6d470..e861e0ae5d 100644
--- a/crawl-ref/source/monster.cc
+++ b/crawl-ref/source/monster.cc
@@ -474,6 +474,23 @@ int monster::damage_type(int which_attack)
return (get_vorpal_type(*mweap));
}
+int monster::has_claws(bool allow_tran) const
+{
+ for (int i = 0; i < MAX_NUM_ATTACKS; i++)
+ {
+ const mon_attack_def atk = mons_attack_spec(this, i);
+ if (atk.type == AT_CLAW)
+ {
+ // Some better criteria would be better.
+ if (body_size() < SIZE_LARGE || atk.damage < 15)
+ return 1;
+ return 3;
+ }
+ }
+
+ return 0;
+}
+
item_def *monster::missiles()
{
return (inv[MSLOT_MISSILE] != NON_ITEM ? &mitm[inv[MSLOT_MISSILE]] : NULL);
@@ -2974,7 +2991,7 @@ int monster::warding() const
{
const item_def *w = primary_weapon();
if (w && w->base_type == OBJ_STAVES && w->sub_type == STAFF_SUMMONING)
- return 30;
+ return 60;
return 0;
}
@@ -4289,6 +4306,10 @@ void monster::calc_speed()
break;
case MONS_HELL_BEAST:
speed = 10 + random2(8);
+ case MONS_BOULDER_BEETLE:
+ // Boost boulder beetle speed when rolling
+ if (has_ench(ENCH_ROLLING))
+ speed = 14;
default:
break;
}
@@ -5065,7 +5086,7 @@ void monster::react_to_damage(const actor *oppressor, int damage,
if (monster *mons = mons_place(
mgen_data(jelly, beha, this, 0, 0,
- jpos, foe, 0, god)))
+ jpos, foe, MG_DONT_COME, god)))
{
// Don't allow milking the royal jelly.
mons->flags |= MF_NO_REWARD;
diff --git a/crawl-ref/source/monster.h b/crawl-ref/source/monster.h
index 1a47a7f885..f8af36eda8 100644
--- a/crawl-ref/source/monster.h
+++ b/crawl-ref/source/monster.h
@@ -217,6 +217,7 @@ public:
int total_weight() const;
brand_type damage_brand(int which_attack = -1);
int damage_type(int which_attack = -1);
+ int has_claws(bool allow_tran = true) const;
item_def *slot_item(equipment_type eq, bool include_melded=false);
item_def *mslot_item(mon_inv_type sl) const;
@@ -373,6 +374,7 @@ public:
bool withdrawn() const {return has_ench(ENCH_WITHDRAWN);};
int warding() const;
+ bool rolling() const { return has_ench(ENCH_ROLLING); } ;
bool has_spells() const;
bool has_spell(spell_type spell) const;
bool has_unholy_spell() const;
diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc
index f82a475a4a..6f65ac793f 100644
--- a/crawl-ref/source/mutation.cc
+++ b/crawl-ref/source/mutation.cc
@@ -403,9 +403,9 @@ std::string describe_mutations()
std::string msg = "You can fly";
if (you.experience_level > 14)
msg += " continuously";
- msg += ".";
+ msg += ".\n";
- result += _annotate_form_based(msg, player_is_shapechanged());
+ result += msg;
have_any = true;
}
break;
@@ -527,7 +527,9 @@ std::string describe_mutations()
case SP_OCTOPODE:
result += "You cannot wear most types of armour.\n";
- result += "You can wear up to eight rings at the same time.\n";
+ result += _annotate_form_based(
+ "You can wear up to eight rings at the same time.",
+ !form_keeps_mutations() && you.form != TRAN_SPIDER);
result += "You are amphibious.\n";
result += _annotate_form_based(
"You can use your tentacles to constrict many enemies at once.",
@@ -1218,8 +1220,8 @@ bool mutate(mutation_type which_mutation, const std::string &reason,
// resistance mutation.
if (!god_gift)
{
- if ((wearing_amulet(AMU_RESIST_MUTATION)
- && !one_chance_in(10) && !stat_gain_potion)
+ if ((player_res_mutation()
+ && !one_chance_in(10) && !stat_gain_potion)
|| player_mutation_level(MUT_MUTATION_RESISTANCE) == 3
|| (player_mutation_level(MUT_MUTATION_RESISTANCE)
&& !one_chance_in(3)))
@@ -1626,6 +1628,10 @@ bool delete_mutation(mutation_type which_mutation, const std::string &reason,
if (you.innate_mutations[mutat] >= you.mutation[mutat])
continue;
+ // MUT_ANTENNAE is 0, and you.attribute[] is initialized to 0.
+ if (mutat && mutat == you.attribute[ATTR_APPENDAGE])
+ continue;
+
const mutation_def& mdef = get_mutation_def(mutat);
if (random2(10) >= mdef.rarity && !_is_slime_mutation(mutat))
diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc
index ec0bef42c6..15d7ceb5e9 100644
--- a/crawl-ref/source/ng-init.cc
+++ b/crawl-ref/source/ng-init.cc
@@ -81,6 +81,7 @@ void initialise_branch_depths()
startdepth[branch] = random_range(b->mindepth, b->maxdepth);
}
+#if 0
// You will get one of Shoals/Swamp and one of Spider/Snake.
// This way you get one "water" branch and one "poison" branch.
const branch_type disabled_branch[] =
@@ -88,6 +89,13 @@ void initialise_branch_depths()
random_choose(BRANCH_SWAMP, BRANCH_SHOALS, -1),
random_choose(BRANCH_SNAKE_PIT, BRANCH_SPIDER_NEST, -1),
};
+#else
+ // For the time being, let's make Spider guaranteed.
+ branch_type disabled_branch[2];
+ disabled_branch[0] = random_choose(BRANCH_SWAMP, BRANCH_SHOALS, BRANCH_SNAKE_PIT, -1);
+ do disabled_branch[1] = random_choose(BRANCH_SWAMP, BRANCH_SHOALS, BRANCH_SNAKE_PIT, -1);
+ while (disabled_branch[0] == disabled_branch[1]);
+#endif
for (unsigned int i = 0; i < ARRAYSZ(disabled_branch); ++i)
{
diff --git a/crawl-ref/source/ng-setup.cc b/crawl-ref/source/ng-setup.cc
index 7901c76127..53b0062202 100644
--- a/crawl-ref/source/ng-setup.cc
+++ b/crawl-ref/source/ng-setup.cc
@@ -540,9 +540,9 @@ static void _give_items_skills(const newgame_def& ng)
you.skills[SK_FIGHTING] = 2;
you.skills[SK_THROWING] = 2;
you.skills[SK_DODGING] = 2;
- you.skills[SK_SHIELDS] = 1;
- // Gladiators with weapons also get some unarmed skill for offhand attacks.
- if (you.weapon())
+ if (ng.weapon != WPN_QUARTERSTAFF)
+ you.skills[SK_SHIELDS] = 1;
+ else // Staff gladiators get some unarmed skill instead for punches.
you.skills[SK_UNARMED_COMBAT] = 2;
weap_skill = 3;
break;
diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h
index 8465b9d094..51eda64293 100644
--- a/crawl-ref/source/options.h
+++ b/crawl-ref/source/options.h
@@ -318,10 +318,10 @@ public:
#ifdef WIZARD
// Parameters for fight simulations.
+ std::string fsim_mode;
int fsim_rounds;
- int fsim_str, fsim_int, fsim_dex;
- int fsim_xl;
std::string fsim_mons;
+ std::vector<std::string> fsim_scale;
std::vector<std::string> fsim_kit;
#endif // WIZARD
diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc
index 8c8c66f95d..38cdcb6367 100644
--- a/crawl-ref/source/ouch.cc
+++ b/crawl-ref/source/ouch.cc
@@ -182,10 +182,10 @@ int check_your_resists(int hurted, beam_type flavour, std::string source,
{
resist = poison_player(coinflip() ? 2 : 1, source, kaux) ? 0 : 1;
- hurted = resist_adjust_damage(&you, flavour, resist,
- hurted, true);
+ hurted = resist_adjust_damage(&you, flavour, resist,
+ hurted, true);
if (resist > 0)
- canned_msg(MSG_YOU_RESIST);
+ canned_msg(MSG_YOU_RESIST);
}
else
{
@@ -317,7 +317,8 @@ int check_your_resists(int hurted, beam_type flavour, std::string source,
if (one_chance_in(3)
// delete_mutation() handles MUT_MUTATION_RESISTANCE but not the amulet
- && (!wearing_amulet(AMU_RESIST_MUTATION) || one_chance_in(10)))
+ && (!player_res_mutation()
+ || one_chance_in(10)))
{
// silver stars only, if this ever changes we may want to give
// aux as well
@@ -351,10 +352,14 @@ int check_your_resists(int hurted, beam_type flavour, std::string source,
hurted += hurted / 2;
break;
}
+
default:
break;
} // end switch
+ if (doEffects && hurted != original)
+ maybe_id_resist(flavour);
+
return (hurted);
}
@@ -434,7 +439,7 @@ static void _item_corrode(int slot)
return;
// Anti-corrosion items protect against 90% of corrosion.
- if (wearing_amulet(AMU_RESIST_CORROSION) && !one_chance_in(10))
+ if (player_res_corr() && !one_chance_in(10))
{
dprf("Amulet protects.");
return;
@@ -655,24 +660,23 @@ static bool _expose_invent_to_element(beam_type flavour, int strength)
item_name.c_str(),
(num_dest == 1) ? "s" : "",
(num_dest == 1) ? "s" : "");
- break;
+ break;
case OBJ_FOOD:
- // Message handled elsewhere.
- if (flavour == BEAM_DEVOUR_FOOD)
- break;
- mprf("%s %s %s covered with spores!",
+ mprf("%s %s %s %s!",
part_stack_string(num_dest, quantity).c_str(),
item_name.c_str(),
- (num_dest == 1) ? "is" : "are");
- break;
+ (num_dest == 1) ? "is" : "are",
+ (flavour == BEAM_DEVOUR_FOOD) ?
+ "devoured" : "covered with spores");
+ break;
default:
mprf("%s %s %s destroyed!",
part_stack_string(num_dest, quantity).c_str(),
item_name.c_str(),
(num_dest == 1) ? "is" : "are");
- break;
+ break;
}
total_dest += num_dest;
@@ -1102,6 +1106,8 @@ static void _place_player_corpse(bool explode)
#if defined(WIZARD) || defined(DEBUG)
static void _wizard_restore_life()
{
+ if (you.hp_max <= 0)
+ unrot_hp(9999);
if (you.hp <= 0)
set_hp(you.hp_max);
for (int i = 0; i < NUM_STATS; ++i)
diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc
index e7c8b95fac..f936c969f8 100644
--- a/crawl-ref/source/output.cc
+++ b/crawl-ref/source/output.cc
@@ -29,6 +29,7 @@
#include "initfile.h"
#include "itemname.h"
#include "item_use.h"
+#include "lang-fake.h"
#include "menu.h"
#include "message.h"
#include "misc.h"
@@ -587,7 +588,7 @@ static void _get_status_lights(std::vector<status_light>& out)
DUR_SILENCE,
DUR_CONFUSING_TOUCH,
DUR_BARGAIN,
- DUR_SAGE,
+ STATUS_SAGE,
DUR_FIRE_SHIELD,
DUR_SLIMIFY,
DUR_SURE_BLADE,
@@ -807,7 +808,7 @@ void print_stats(void)
if (you.redraw_title)
{
you.redraw_title = false;
- _redraw_title(you.your_name, player_title());
+ _redraw_title(you.your_name, filtered_lang(player_title()));
}
if (you.redraw_hit_points) { you.redraw_hit_points = false; _print_stats_hp (1, 3); }
@@ -1693,8 +1694,8 @@ static std::vector<formatted_string> _get_overview_resistances(
{
char buf[1000];
- // 3 columns, splits at columns 21, 39
- column_composer cols(3, 21, 39);
+ // 3 columns, splits at columns 21, 38
+ column_composer cols(3, 21, 38);
// Don't show unreliable resistances granted by the cloak. We could mark
// them somehow, but for now this will do.
@@ -1710,7 +1711,7 @@ static std::vector<formatted_string> _get_overview_resistances(
const int rpois = player_res_poison(calc_unid);
const int relec = player_res_electricity(calc_unid);
const int rsust = player_sust_abil(calc_unid);
- const int rmuta = (wearing_amulet(AMU_RESIST_MUTATION, calc_unid)
+ const int rmuta = (player_res_mutation()
|| player_mutation_level(MUT_MUTATION_RESISTANCE) == 3
|| you.religion == GOD_ZIN && you.piety >= 150);
const int rrott = (you.res_rotting()
@@ -1741,7 +1742,7 @@ static std::vector<formatted_string> _get_overview_resistances(
const char* pregourmand;
const char* postgourmand;
- if (wearing_amulet(AMU_THE_GOURMAND, calc_unid))
+ if (player_effect_gourmand())
{
pregourmand = "Gourmand : ";
postgourmand = _itosym1(1);
@@ -1772,16 +1773,17 @@ static std::vector<formatted_string> _get_overview_resistances(
"%sSpirit.Shd : %s\n"
,
_determine_colour_string(rinvi, 1), _itosym1(rinvi),
- _determine_colour_string(rward, 2), _itosym2(rward),
+ _determine_colour_string(rward, 1), _itosym1(rward),
_determine_colour_string(rcons, 1), _itosym1(rcons),
_determine_colour_string(rcorr, 1), _itosym1(rcorr),
_determine_colour_string(rclar, 1), _itosym1(rclar),
_determine_colour_string(rspir, 1), _itosym1(rspir));
cols.add_formatted(1, buf, false);
- const int stasis = wearing_amulet(AMU_STASIS, calc_unid);
- const int notele = scan_artefacts(ARTP_PREVENT_TELEPORTATION, calc_unid)
- || crawl_state.game_is_zotdef() && orb_haloed(you.pos());
+ const int stasis = player_effect_stasis(calc_unid);
+ const int notele = player_effect_notele(calc_unid)
+ || crawl_state.game_is_zotdef()
+ && orb_haloed(you.pos());
const int rrtel = !!player_teleport(calc_unid);
if (notele && !stasis)
{
@@ -1804,7 +1806,7 @@ static std::vector<formatted_string> _get_overview_resistances(
int rctel = player_control_teleport(calc_unid);
rctel = allow_control_teleport(true) ? rctel : -1;
const int rlevi = you.airborne();
- const int rcfli = wearing_amulet(AMU_CONTROLLED_FLIGHT, calc_unid);
+ const int rcfli = player_effect_cfly(calc_unid);
snprintf(buf, sizeof buf,
"%sCtrl.Telep.: %s\n"
"%sLevitation : %s\n"
@@ -2008,7 +2010,7 @@ static std::string _status_mut_abilities(int sw)
DUR_BARGAIN,
DUR_SLAYING,
STATUS_MANUAL,
- DUR_SAGE,
+ STATUS_SAGE,
DUR_MAGIC_SHIELD,
DUR_FIRE_SHIELD,
DUR_POISONING,
@@ -2115,8 +2117,7 @@ static std::string _status_mut_abilities(int sw)
std::string help = "able to fly";
if (you.experience_level > 14)
help += " continuously";
- mutations.push_back(_annotate_form_based(help,
- player_is_shapechanged()));
+ mutations.push_back(help);
}
break;
@@ -2210,6 +2211,9 @@ static std::string _status_mut_abilities(int sw)
if (you.species == SP_OCTOPODE)
{
mutations.push_back("almost no armour");
+ mutations.push_back(_annotate_form_based(
+ "8 rings",
+ !form_keeps_mutations() && you.form != TRAN_SPIDER));
mutations.push_back("amphibious");
mutations.push_back(_annotate_form_based(
make_stringf("constrict %d", std::min(MAX_CONSTRICT, 8)),
diff --git a/crawl-ref/source/player-act.cc b/crawl-ref/source/player-act.cc
index 98a3b06504..e1c38d0660 100644
--- a/crawl-ref/source/player-act.cc
+++ b/crawl-ref/source/player-act.cc
@@ -257,7 +257,7 @@ brand_type player::damage_brand(int)
}
// Returns the item in the given equipment slot, NULL if the slot is empty.
-// eq must be in [EQ_WEAPON, EQ_AMULET], or bad things will happen.
+// eq must be in [EQ_WEAPON, EQ_RING_EIGHT], or bad things will happen.
item_def *player::slot_item(equipment_type eq, bool include_melded)
{
ASSERT(eq >= EQ_WEAPON && eq < NUM_EQUIP);
@@ -636,7 +636,7 @@ bool player::can_go_berserk(bool intentional, bool potion) const
// trigger when the player attempts to activate berserk,
// auto-iding at that point, but also killing the berserk and
// wasting a turn.
- if (wearing_amulet(AMU_STASIS, false))
+ if (player_effect_stasis(false))
{
if (verbose)
{
diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc
index 80f5289831..8e38e41c8f 100644
--- a/crawl-ref/source/player-equip.cc
+++ b/crawl-ref/source/player-equip.cc
@@ -161,9 +161,7 @@ static void _unequip_effect(equipment_type slot, int item_slot, bool meld,
else if (slot >= EQ_LEFT_RING && slot < NUM_EQUIP)
_unequip_jewellery_effect(item, msg, meld);
- if (slot == EQ_BODY_ARMOUR && !meld)
- you.stop_train.insert(SK_ARMOUR);
- else if (slot == EQ_SHIELD && !meld)
+ if (slot == EQ_SHIELD && !meld)
you.stop_train.insert(SK_SHIELDS);
}
diff --git a/crawl-ref/source/player-stats.cc b/crawl-ref/source/player-stats.cc
index 18de7a1849..f97c2d689a 100644
--- a/crawl-ref/source/player-stats.cc
+++ b/crawl-ref/source/player-stats.cc
@@ -324,14 +324,17 @@ static int _strength_modifier()
result += che_stat_boost();
- // ego items of strength
- result += 3 * count_worn_ego(SPARM_STRENGTH);
+ if (!you.suppressed())
+ {
+ // ego items of strength
+ result += 3 * count_worn_ego(SPARM_STRENGTH);
- // rings of strength
- result += player_equip(EQ_RINGS_PLUS, RING_STRENGTH);
+ // rings of strength
+ result += player_equip(EQ_RINGS_PLUS, RING_STRENGTH);
- // randarts of strength
- result += scan_artefacts(ARTP_STRENGTH);
+ // randarts of strength
+ result += scan_artefacts(ARTP_STRENGTH);
+ }
// mutations
result += player_mutation_level(MUT_STRONG)
@@ -365,14 +368,17 @@ static int _int_modifier()
result += che_stat_boost();
- // ego items of intelligence
- result += 3 * count_worn_ego(SPARM_INTELLIGENCE);
+ if (!you.suppressed())
+ {
+ // ego items of intelligence
+ result += 3 * count_worn_ego(SPARM_INTELLIGENCE);
- // rings of intelligence
- result += player_equip(EQ_RINGS_PLUS, RING_INTELLIGENCE);
+ // rings of intelligence
+ result += player_equip(EQ_RINGS_PLUS, RING_INTELLIGENCE);
- // randarts of intelligence
- result += scan_artefacts(ARTP_INTELLIGENCE);
+ // randarts of intelligence
+ result += scan_artefacts(ARTP_INTELLIGENCE);
+ }
// mutations
result += player_mutation_level(MUT_CLEVER)
@@ -393,14 +399,17 @@ static int _dex_modifier()
result += che_stat_boost();
- // ego items of dexterity
- result += 3 * count_worn_ego(SPARM_DEXTERITY);
+ if (!you.suppressed())
+ {
+ // ego items of dexterity
+ result += 3 * count_worn_ego(SPARM_DEXTERITY);
- // rings of dexterity
- result += player_equip(EQ_RINGS_PLUS, RING_DEXTERITY);
+ // rings of dexterity
+ result += player_equip(EQ_RINGS_PLUS, RING_DEXTERITY);
- // randarts of dexterity
- result += scan_artefacts(ARTP_DEXTERITY);
+ // randarts of dexterity
+ result += scan_artefacts(ARTP_DEXTERITY);
+ }
// mutations
result += player_mutation_level(MUT_AGILE)
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index a594cba68d..1950da4ac1 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -492,9 +492,16 @@ bool player_in_bat_form()
bool player_can_open_doors()
{
- // Bats and pigs can't open/close doors.
- return (you.form != TRAN_BAT
- && you.form != TRAN_PIG);
+ return (you.form != TRAN_BAT);
+}
+
+bool player_can_handle_equipment()
+{
+ return you.form != TRAN_BAT
+ && you.form != TRAN_PIG
+ && you.form != TRAN_SPIDER
+ && you.form != TRAN_ICE_BEAST
+ && you.form != TRAN_BLADE_HANDS;
}
bool player_can_reach_floor(std::string feat, bool quiet)
@@ -781,7 +788,7 @@ bool you_tran_can_wear(const item_def &item)
case OBJ_JEWELLERY:
return you_tran_can_wear(jewellery_is_amulet(item) ? EQ_AMULET
- : EQ_LEFT_RING);
+ : EQ_RINGS);
case OBJ_ARMOUR:
if (item.sub_type == ARM_NAGA_BARDING)
return (you.species == SP_NAGA && you_tran_can_wear(EQ_BOOTS));
@@ -805,10 +812,8 @@ bool you_tran_can_wear(int eq, bool check_mutation)
if (eq == EQ_STAFF)
eq = EQ_WEAPON;
- else if (eq >= EQ_RINGS && eq <= EQ_RINGS_PLUS2 && you.species != SP_OCTOPODE)
- eq = EQ_LEFT_RING;
- else if (eq >= EQ_RINGS && eq <= EQ_RINGS_PLUS2 && you.species == SP_OCTOPODE)
- eq = EQ_RING_ONE;
+ else if (eq >= EQ_RINGS && eq <= EQ_RINGS_PLUS2)
+ eq = EQ_RINGS;
// Everybody can wear at least some type of armour.
if (eq == EQ_ALL_ARMOUR)
@@ -847,9 +852,20 @@ bool you_tran_can_wear(int eq, bool check_mutation)
if ((you.form == TRAN_BAT || you.form == TRAN_PIG) && eq != EQ_AMULET)
return (false);
- // Everyone else can wear jewellery, at least.
- if (eq == EQ_LEFT_RING || eq == EQ_RIGHT_RING || eq == EQ_AMULET || eq == EQ_RING_ONE)
+ // Everyone else can wear jewellery . . .
+ if (eq == EQ_AMULET || eq == EQ_RINGS
+ || eq == EQ_LEFT_RING || eq == EQ_RIGHT_RING
+ || eq == EQ_RING_ONE || eq == EQ_RING_TWO)
+ {
return (true);
+ }
+
+ // . . . but not necessarily in all slots.
+ if (eq >= EQ_RING_THREE && eq <= EQ_RING_EIGHT)
+ {
+ return (you.species == SP_OCTOPODE
+ && (form_keeps_mutations() || you.form == TRAN_SPIDER));
+ }
// These cannot use anything but jewellery.
if (you.form == TRAN_SPIDER || you.form == TRAN_DRAGON)
@@ -965,7 +981,7 @@ int player_equip(equipment_type slot, int sub_type, bool calc_unid)
if (slots == EQ_AMULET)
continue;
- if ((item = you.slot_item(static_cast<equipment_type>(slots), true))
+ if ((item = you.slot_item(static_cast<equipment_type>(slots)))
&& item->sub_type == sub_type
&& (calc_unid
|| item_type_known(*item)))
@@ -981,7 +997,7 @@ int player_equip(equipment_type slot, int sub_type, bool calc_unid)
if (slots == EQ_AMULET)
continue;
- if ((item = you.slot_item(static_cast<equipment_type>(slots), true))
+ if ((item = you.slot_item(static_cast<equipment_type>(slots)))
&& item->sub_type == sub_type
&& (calc_unid
|| item_type_known(*item)))
@@ -997,7 +1013,7 @@ int player_equip(equipment_type slot, int sub_type, bool calc_unid)
if (slots == EQ_AMULET)
continue;
- if ((item = you.slot_item(static_cast<equipment_type>(slots), true))
+ if ((item = you.slot_item(static_cast<equipment_type>(slots)))
&& item->sub_type == sub_type
&& (calc_unid
|| item_type_known(*item)))
@@ -1162,7 +1178,7 @@ int player_evokable_levitation()
int player_evokable_invis()
{
return (player_equip(EQ_RINGS, RING_INVISIBILITY)
- + player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_DARKNESS)
+ + player_equip_ego_type(EQ_CLOAK, SPARM_DARKNESS)
+ scan_artefacts(ARTP_INVISIBLE));
}
@@ -1198,20 +1214,24 @@ int player_teleport(bool calc_unid)
int tp = 0;
- // rings (keep in sync with _equip_jewellery_effect)
- tp += 8 * player_equip(EQ_RINGS, RING_TELEPORTATION, calc_unid);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // rings (keep in sync with _equip_jewellery_effect)
+ tp += 8 * player_equip(EQ_RINGS, RING_TELEPORTATION, calc_unid);
+
+ // randart weapons only
+ if (you.weapon()
+ && you.weapon()->base_type == OBJ_WEAPONS
+ && is_artefact(*you.weapon()))
+ {
+ tp += scan_artefacts(ARTP_CAUSE_TELEPORTATION, calc_unid);
+ }
+ }
// mutations
tp += player_mutation_level(MUT_TELEPORT) * 3;
- // randart weapons only
- if (you.weapon()
- && you.weapon()->base_type == OBJ_WEAPONS
- && is_artefact(*you.weapon()))
- {
- tp += scan_artefacts(ARTP_CAUSE_TELEPORTATION, calc_unid);
- }
-
return tp;
}
@@ -1229,15 +1249,19 @@ static int _player_bonus_regen()
rr += 100;
}
- // Rings.
- rr += 40 * player_equip(EQ_RINGS, RING_REGENERATION);
-
- // Troll leather (except for trolls).
- if ((player_equip(EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR)
- || player_equip(EQ_BODY_ARMOUR, ARM_TROLL_HIDE))
- && you.species != SP_TROLL)
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
{
- rr += 30;
+ // Rings.
+ rr += 40 * player_equip(EQ_RINGS, RING_REGENERATION);
+
+ // Troll leather (except for trolls).
+ if ((player_equip(EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR)
+ || player_equip(EQ_BODY_ARMOUR, ARM_TROLL_HIDE))
+ && you.species != SP_TROLL)
+ {
+ rr += 30;
+ }
}
// Fast heal mutation.
@@ -1296,6 +1320,9 @@ int player_regen()
if (you.stat_zero[STAT_STR])
rr /= 4;
+ if (you.disease)
+ rr = 0;
+
// Trog's Hand. This circumvents the slow healing effect.
if (you.attribute[ATTR_DIVINE_REGENERATION])
rr += 100;
@@ -1370,35 +1397,39 @@ int player_hunger_rate(bool temp)
hunger--;
}
- // rings
- if (you.hp < you.hp_max
- && player_mutation_level(MUT_SLOW_HEALING) < 3)
- {
- hunger += 3 * player_equip(EQ_RINGS, RING_REGENERATION);
- }
-
- hunger += 4 * player_equip(EQ_RINGS, RING_HUNGER);
+ // burden
+ if (temp)
+ hunger += you.burden_state;
- // troll leather armour
- if (you.species != SP_TROLL && you.hp < you.hp_max)
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
{
- if (player_equip(EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR)
- || player_equip(EQ_BODY_ARMOUR, ARM_TROLL_HIDE))
+ // rings
+ if (you.hp < you.hp_max
+ && player_mutation_level(MUT_SLOW_HEALING) < 3)
{
- hunger += coinflip() ? 2 : 1;
+ hunger += 3 * player_equip(EQ_RINGS, RING_REGENERATION);
}
- }
- // randarts
- hunger += scan_artefacts(ARTP_METABOLISM);
+ hunger += 4 * player_equip(EQ_RINGS, RING_HUNGER);
- // burden
- if (temp)
- hunger += you.burden_state;
+ // troll leather armour
+ if (you.species != SP_TROLL && you.hp < you.hp_max)
+ {
+ if (player_equip(EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR)
+ || player_equip(EQ_BODY_ARMOUR, ARM_TROLL_HIDE))
+ {
+ hunger += coinflip() ? 2 : 1;
+ }
+ }
- // sustenance affects things at the end, because it is multiplicative
- for (int s = player_equip(EQ_RINGS, RING_SUSTENANCE); s > 0; s--)
- hunger = (3*hunger)/5;
+ // randarts
+ hunger += scan_artefacts(ARTP_METABOLISM);
+
+ // sustenance affects things at the end, because it is multiplicative
+ for (int s = player_equip(EQ_RINGS, RING_SUSTENANCE); s > 0; s--)
+ hunger = (3*hunger)/5;
+ }
if (hunger < 1)
hunger = 1;
@@ -1442,7 +1473,9 @@ int player_spell_levels(void)
int player_likes_chunks(bool permanently)
{
if (player_mutation_level(MUT_GOURMAND) > 0
- || (!permanently && wearing_amulet(AMU_THE_GOURMAND)))
+ || (!you.suppressed()
+ && !permanently
+ && wearing_amulet(AMU_THE_GOURMAND)))
{
return 3;
}
@@ -1454,37 +1487,41 @@ int player_res_fire(bool calc_unid, bool temp, bool items)
{
int rf = 0;
- if (items)
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
{
- // rings of fire resistance/fire
- rf += player_equip(EQ_RINGS, RING_PROTECTION_FROM_FIRE, calc_unid);
- rf += player_equip(EQ_RINGS, RING_FIRE, calc_unid);
-
- // rings of ice
- rf -= player_equip(EQ_RINGS, RING_ICE, calc_unid);
-
- // Staves
- rf += player_equip(EQ_STAFF, STAFF_FIRE, calc_unid);
-
- // body armour:
- rf += 2 * player_equip(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_ARMOUR);
- rf += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
- rf -= player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_ARMOUR);
- rf += 2 * player_equip(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_HIDE);
- rf += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
- rf -= player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_HIDE);
-
- // ego armours
- rf += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_FIRE_RESISTANCE);
- rf += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_RESISTANCE);
-
- // randart weapons:
- rf += scan_artefacts(ARTP_FIRE, calc_unid);
-
- // dragonskin cloak: 0.5 to draconic resistances
- if (player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
- rf++;
+ if (items)
+ {
+ // rings of fire resistance/fire
+ rf += player_equip(EQ_RINGS, RING_PROTECTION_FROM_FIRE, calc_unid);
+ rf += player_equip(EQ_RINGS, RING_FIRE, calc_unid);
+
+ // rings of ice
+ rf -= player_equip(EQ_RINGS, RING_ICE, calc_unid);
+
+ // Staves
+ rf += player_equip(EQ_STAFF, STAFF_FIRE, calc_unid);
+
+ // body armour:
+ rf += 2 * player_equip(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_ARMOUR);
+ rf += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
+ rf -= player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_ARMOUR);
+ rf += 2 * player_equip(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_HIDE);
+ rf += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
+ rf -= player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_HIDE);
+
+ // ego armours
+ rf += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_FIRE_RESISTANCE);
+ rf += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_RESISTANCE);
+
+ // randart weapons:
+ rf += scan_artefacts(ARTP_FIRE, calc_unid);
+
+ // dragonskin cloak: 0.5 to draconic resistances
+ if (player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
+ rf++;
}
+ }
// species:
if (you.species == SP_MUMMY)
@@ -1538,17 +1575,21 @@ int player_res_steam(bool calc_unid, bool temp, bool items)
if (you.species == SP_PALE_DRACONIAN)
res += 2;
- if (items && player_equip(EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_ARMOUR))
- res += 2;
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ if (items && player_equip(EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_ARMOUR))
+ res += 2;
- if (items && player_equip(EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_HIDE))
- res += 2;
+ if (items && player_equip(EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_HIDE))
+ res += 2;
- // dragonskin cloak: 0.5 to draconic resistances
- if (items && player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
- res++;
+ // dragonskin cloak: 0.5 to draconic resistances
+ if (items && player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
+ res++;
- res += (player_res_fire(calc_unid, temp, items) + 1) / 2;
+ res += (player_res_fire(calc_unid, temp, items) + 1) / 2;
+ }
if (res > 3)
res = 3;
@@ -1599,37 +1640,41 @@ int player_res_cold(bool calc_unid, bool temp, bool items)
}
}
- if (items)
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
{
- // rings of cold resistance/ice
- rc += player_equip(EQ_RINGS, RING_PROTECTION_FROM_COLD, calc_unid);
- rc += player_equip(EQ_RINGS, RING_ICE, calc_unid);
+ if (items)
+ {
+ // rings of cold resistance/ice
+ rc += player_equip(EQ_RINGS, RING_PROTECTION_FROM_COLD, calc_unid);
+ rc += player_equip(EQ_RINGS, RING_ICE, calc_unid);
- // rings of fire
- rc -= player_equip(EQ_RINGS, RING_FIRE, calc_unid);
+ // rings of fire
+ rc -= player_equip(EQ_RINGS, RING_FIRE, calc_unid);
- // Staves
- rc += player_equip(EQ_STAFF, STAFF_COLD, calc_unid);
+ // Staves
+ rc += player_equip(EQ_STAFF, STAFF_COLD, calc_unid);
- // body armour:
- rc += 2 * player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_ARMOUR);
- rc += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
- rc -= player_equip(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_ARMOUR);
- rc += 2 * player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_HIDE);
- rc += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
- rc -= player_equip(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_HIDE);
+ // body armour:
+ rc += 2 * player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_ARMOUR);
+ rc += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
+ rc -= player_equip(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_ARMOUR);
+ rc += 2 * player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_HIDE);
+ rc += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
+ rc -= player_equip(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_HIDE);
- // ego armours
- rc += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_COLD_RESISTANCE);
- rc += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_RESISTANCE);
+ // ego armours
+ rc += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_COLD_RESISTANCE);
+ rc += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_RESISTANCE);
- // randart weapons:
- rc += scan_artefacts(ARTP_COLD, calc_unid);
+ // randart weapons:
+ rc += scan_artefacts(ARTP_COLD, calc_unid);
- // dragonskin cloak: 0.5 to draconic resistances
- if (player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
- rc++;
+ // dragonskin cloak: 0.5 to draconic resistances
+ if (player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
+ rc++;
}
+ }
// mutations:
rc += player_mutation_level(MUT_COLD_RESISTANCE, temp);
@@ -1646,10 +1691,14 @@ int player_res_cold(bool calc_unid, bool temp, bool items)
int player_res_corr(bool calc_unid, bool items)
{
- if (items && wearing_amulet(AMU_RESIST_CORROSION, calc_unid))
- return 1;
- else
- return 0;
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ if (items && wearing_amulet(AMU_RESIST_CORROSION, calc_unid))
+ return 1;
+ }
+
+ return 0;
}
int player_res_acid(bool calc_unid, bool items)
@@ -1661,13 +1710,17 @@ int player_res_acid(bool calc_unid, bool items)
res += 2;
}
- if (items)
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
{
- if (wearing_amulet(AMU_RESIST_CORROSION, calc_unid, true))
- res++;
+ if (items)
+ {
+ if (wearing_amulet(AMU_RESIST_CORROSION, calc_unid, true))
+ res++;
- if (player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_PRESERVATION))
- res++;
+ if (player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_PRESERVATION))
+ res++;
+ }
}
// mutations:
@@ -1705,21 +1758,25 @@ int player_res_electricity(bool calc_unid, bool temp, bool items)
{
int re = 0;
- if (items)
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
{
- // staff
- re += player_equip(EQ_STAFF, STAFF_AIR, calc_unid);
+ if (items)
+ {
+ // staff
+ re += player_equip(EQ_STAFF, STAFF_AIR, calc_unid);
- // body armour:
- re += player_equip(EQ_BODY_ARMOUR, ARM_STORM_DRAGON_ARMOUR);
- re += player_equip(EQ_BODY_ARMOUR, ARM_STORM_DRAGON_HIDE);
+ // body armour:
+ re += player_equip(EQ_BODY_ARMOUR, ARM_STORM_DRAGON_ARMOUR);
+ re += player_equip(EQ_BODY_ARMOUR, ARM_STORM_DRAGON_HIDE);
- // randart weapons:
- re += scan_artefacts(ARTP_ELECTRICITY, calc_unid);
+ // randart weapons:
+ re += scan_artefacts(ARTP_ELECTRICITY, calc_unid);
- // dragonskin cloak: 0.5 to draconic resistances
- if (player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
- re++;
+ // dragonskin cloak: 0.5 to draconic resistances
+ if (player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
+ re++;
+ }
}
// mutations:
@@ -1749,7 +1806,8 @@ bool player_control_teleport(bool calc_unid, bool temp, bool items)
{
return ((temp && you.duration[DUR_CONTROL_TELEPORT])
|| (items
- && player_equip(EQ_RINGS, RING_TELEPORT_CONTROL, calc_unid))
+ && player_equip(EQ_RINGS, RING_TELEPORT_CONTROL, calc_unid)
+ && !you.suppressed())
|| player_mutation_level(MUT_TELEPORT_CONTROL));
}
@@ -1775,30 +1833,34 @@ int player_res_poison(bool calc_unid, bool temp, bool items)
int rp = 0;
- if (items)
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
{
- // rings of poison resistance
- rp += player_equip(EQ_RINGS, RING_POISON_RESISTANCE, calc_unid);
+ if (items)
+ {
+ // rings of poison resistance
+ rp += player_equip(EQ_RINGS, RING_POISON_RESISTANCE, calc_unid);
- // Staves
- rp += player_equip(EQ_STAFF, STAFF_POISON, calc_unid);
+ // Staves
+ rp += player_equip(EQ_STAFF, STAFF_POISON, calc_unid);
- // ego armour:
- rp += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_POISON_RESISTANCE);
+ // ego armour:
+ rp += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_POISON_RESISTANCE);
- // body armour:
- rp += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
- rp += player_equip(EQ_BODY_ARMOUR, ARM_SWAMP_DRAGON_ARMOUR);
- rp += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
- rp += player_equip(EQ_BODY_ARMOUR, ARM_SWAMP_DRAGON_HIDE);
+ // body armour:
+ rp += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
+ rp += player_equip(EQ_BODY_ARMOUR, ARM_SWAMP_DRAGON_ARMOUR);
+ rp += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
+ rp += player_equip(EQ_BODY_ARMOUR, ARM_SWAMP_DRAGON_HIDE);
- // randart weapons:
- rp += scan_artefacts(ARTP_POISON, calc_unid);
+ // randart weapons:
+ rp += scan_artefacts(ARTP_POISON, calc_unid);
- // dragonskin cloak: 0.5 to draconic resistances
- if (player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
- rp++;
+ // dragonskin cloak: 0.5 to draconic resistances
+ if (player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
+ rp++;
+ }
}
// mutations:
@@ -1869,14 +1931,18 @@ int player_res_sticky_flame(bool calc_unid, bool temp, bool items)
if (you.species == SP_MOTTLED_DRACONIAN)
rsf++;
- if (items && player_equip(EQ_BODY_ARMOUR, ARM_MOTTLED_DRAGON_ARMOUR))
- rsf++;
- if (items && player_equip(EQ_BODY_ARMOUR, ARM_MOTTLED_DRAGON_HIDE))
- rsf++;
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ if (items && player_equip(EQ_BODY_ARMOUR, ARM_MOTTLED_DRAGON_ARMOUR))
+ rsf++;
+ if (items && player_equip(EQ_BODY_ARMOUR, ARM_MOTTLED_DRAGON_HIDE))
+ rsf++;
- // dragonskin cloak: 0.5 to draconic resistances
- if (items && player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
- rsf++;
+ // dragonskin cloak: 0.5 to draconic resistances
+ if (items && player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
+ rsf++;
+ }
if (rsf > 1)
rsf = 1;
@@ -1888,8 +1954,12 @@ int player_spec_death()
{
int sd = 0;
- // Staves
- sd += player_equip(EQ_STAFF, STAFF_DEATH);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // Staves
+ sd += player_equip(EQ_STAFF, STAFF_DEATH);
+ }
// species:
if (you.species == SP_MUMMY)
@@ -1918,11 +1988,15 @@ int player_spec_fire()
{
int sf = 0;
- // staves:
- sf += player_equip(EQ_STAFF, STAFF_FIRE);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // staves:
+ sf += player_equip(EQ_STAFF, STAFF_FIRE);
- // rings of fire:
- sf += player_equip(EQ_RINGS, RING_FIRE);
+ // rings of fire:
+ sf += player_equip(EQ_RINGS, RING_FIRE);
+ }
if (you.duration[DUR_FIRE_SHIELD])
sf++;
@@ -1934,11 +2008,15 @@ int player_spec_cold()
{
int sc = 0;
- // staves:
- sc += player_equip(EQ_STAFF, STAFF_COLD);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // staves:
+ sc += player_equip(EQ_STAFF, STAFF_COLD);
- // rings of ice:
- sc += player_equip(EQ_RINGS, RING_ICE);
+ // rings of ice:
+ sc += player_equip(EQ_RINGS, RING_ICE);
+ }
return sc;
}
@@ -1947,8 +2025,12 @@ int player_spec_earth()
{
int se = 0;
- // Staves
- se += player_equip(EQ_STAFF, STAFF_EARTH);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // Staves
+ se += player_equip(EQ_STAFF, STAFF_EARTH);
+ }
return se;
}
@@ -1957,8 +2039,12 @@ int player_spec_air()
{
int sa = 0;
- // Staves
- sa += player_equip(EQ_STAFF, STAFF_AIR);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // Staves
+ sa += player_equip(EQ_STAFF, STAFF_AIR);
+ }
return sa;
}
@@ -1967,8 +2053,12 @@ int player_spec_conj()
{
int sc = 0;
- // Staves
- sc += player_equip(EQ_STAFF, STAFF_CONJURATION);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // Staves
+ sc += player_equip(EQ_STAFF, STAFF_CONJURATION);
+ }
return sc;
}
@@ -1977,8 +2067,12 @@ int player_spec_ench()
{
int se = 0;
- // Staves
- se += player_equip(EQ_STAFF, STAFF_ENCHANTMENT);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // Staves
+ se += player_equip(EQ_STAFF, STAFF_ENCHANTMENT);
+ }
return se;
}
@@ -1987,8 +2081,12 @@ int player_spec_summ()
{
int ss = 0;
- // Staves
- ss += player_equip(EQ_STAFF, STAFF_SUMMONING);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // Staves
+ ss += player_equip(EQ_STAFF, STAFF_SUMMONING);
+ }
return ss;
}
@@ -1997,11 +2095,15 @@ int player_spec_poison()
{
int sp = 0;
- // Staves
- sp += player_equip(EQ_STAFF, STAFF_POISON);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // Staves
+ sp += player_equip(EQ_STAFF, STAFF_POISON);
- if (player_equip_unrand(UNRAND_OLGREB))
- sp++;
+ if (player_equip_unrand(UNRAND_OLGREB))
+ sp++;
+ }
return sp;
}
@@ -2010,8 +2112,12 @@ int player_energy()
{
int pe = 0;
- // Staves
- pe += player_equip(EQ_STAFF, STAFF_ENERGY);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // Staves
+ pe += player_equip(EQ_STAFF, STAFF_ENERGY);
+ }
return pe;
}
@@ -2070,30 +2176,34 @@ int player_prot_life(bool calc_unid, bool temp, bool items)
pl += 3;
}
- if (items)
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
{
- if (wearing_amulet(AMU_WARDING, calc_unid))
- pl++;
+ if (items)
+ {
+ if (wearing_amulet(AMU_WARDING, calc_unid))
+ pl++;
- // rings
- pl += player_equip(EQ_RINGS, RING_LIFE_PROTECTION, calc_unid);
+ // rings
+ pl += player_equip(EQ_RINGS, RING_LIFE_PROTECTION, calc_unid);
- // armour (checks body armour only)
- pl += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_POSITIVE_ENERGY);
+ // armour (checks body armour only)
+ pl += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_POSITIVE_ENERGY);
- // pearl dragon counts
- pl += player_equip(EQ_BODY_ARMOUR, ARM_PEARL_DRAGON_ARMOUR);
- pl += player_equip(EQ_BODY_ARMOUR, ARM_PEARL_DRAGON_HIDE);
+ // pearl dragon counts
+ pl += player_equip(EQ_BODY_ARMOUR, ARM_PEARL_DRAGON_ARMOUR);
+ pl += player_equip(EQ_BODY_ARMOUR, ARM_PEARL_DRAGON_HIDE);
- // randart wpns
- pl += scan_artefacts(ARTP_NEGATIVE_ENERGY, calc_unid);
+ // randart wpns
+ pl += scan_artefacts(ARTP_NEGATIVE_ENERGY, calc_unid);
- // dragonskin cloak: 0.5 to draconic resistances
- // this one is dubious (no pearl draconians)
- if (player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
- pl++;
+ // dragonskin cloak: 0.5 to draconic resistances
+ // this one is dubious (no pearl draconians)
+ if (player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
+ pl++;
- pl += player_equip(EQ_STAFF, STAFF_DEATH, calc_unid);
+ pl += player_equip(EQ_STAFF, STAFF_DEATH, calc_unid);
+ }
}
// undead/demonic power
@@ -2384,12 +2494,16 @@ static int _player_evasion_bonuses(ev_ignore_type evit)
if (you.duration[DUR_AGILITY])
evbonus += 5;
- evbonus += player_equip(EQ_RINGS_PLUS, RING_EVASION);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ evbonus += player_equip(EQ_RINGS_PLUS, RING_EVASION);
- if (player_equip_ego_type(EQ_WEAPON, SPWPN_EVASION))
- evbonus += 5;
+ if (player_equip_ego_type(EQ_WEAPON, SPWPN_EVASION))
+ evbonus += 5;
- evbonus += scan_artefacts(ARTP_EVASION);
+ evbonus += scan_artefacts(ARTP_EVASION);
+ }
// mutations
if (_mut_level(MUT_ICY_BLUE_SCALES, MUTACT_FULL) > 1)
@@ -2549,6 +2663,9 @@ int player_armour_shield_spell_penalty()
static int _player_magical_power(void)
{
+ if (you.suppressed())
+ return (0);
+
int ret = 0;
ret += 13 * player_equip(EQ_STAFF, STAFF_POWER);
@@ -2565,11 +2682,15 @@ int player_mag_abil(bool is_weighted)
// Brilliance Potion
ma += 6 * (you.duration[DUR_BRILLIANCE] ? 1 : 0);
- // Rings
- ma += 3 * player_equip(EQ_RINGS, RING_WIZARDRY);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // Rings
+ ma += 3 * player_equip(EQ_RINGS, RING_WIZARDRY);
- // Staves
- ma += 4 * player_equip(EQ_STAFF, STAFF_WIZARDRY);
+ // Staves
+ ma += 4 * player_equip(EQ_STAFF, STAFF_WIZARDRY);
+ }
return ((is_weighted) ? ((ma * you.intel()) / 10) : ma);
}
@@ -2644,7 +2765,11 @@ int player_sust_abil(bool calc_unid)
{
int sa = 0;
- sa += player_equip(EQ_RINGS, RING_SUSTAIN_ABILITIES, calc_unid);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ sa += player_equip(EQ_RINGS, RING_SUSTAIN_ABILITIES, calc_unid);
+ }
if (you.duration[DUR_DIVINE_STAMINA] > 0)
sa += 1;
@@ -2657,15 +2782,11 @@ int player_sust_abil(bool calc_unid)
int player_warding(bool calc_unid)
{
- int ward = 0;
-
// Note: when adding a new source of warding, please add it to
// melee_attack::attack_warded_off() as well.
- ward += player_equip(EQ_AMULET, AMU_WARDING, calc_unid);
-
- ward += player_equip(EQ_STAFF, STAFF_SUMMONING, calc_unid);
-
- return (ward);
+ return (!you.suppressed()
+ && (player_equip(EQ_AMULET, AMU_WARDING, calc_unid)
+ || player_equip(EQ_STAFF, STAFF_SUMMONING, calc_unid)));
}
int carrying_capacity(burden_state_type bs)
@@ -2875,15 +2996,27 @@ void gain_exp(unsigned int exp_gained, unsigned int* actual_gain)
you.attribute[ATTR_EVOL_XP] += exp_gained;
- if (you.duration[DUR_SAGE])
+ if (!you.sage_skills.empty())
{
+ int which_sage = random2(you.sage_skills.size());
+ skill_type skill = you.sage_skills[which_sage];
+
const int old_avail = you.exp_available;
// Bonus skill training from Sage.
you.exp_available =
- (exp_gained * you.sage_bonus_degree) / 100 + exp_gained / 2;
- train_skill(you.sage_bonus_skill, you.exp_available);
+ div_rand_round(exp_gained * (you.sage_bonus[which_sage] + 50), 100);
+ you.sage_xp[which_sage] -= you.exp_available;
+ train_skill(skill, you.exp_available);
you.exp_available = old_avail;
- exp_gained /= 2;
+ exp_gained = div_rand_round(exp_gained, 2);
+
+ if (you.sage_xp[which_sage] <= 0 || you.skills[skill] == 27)
+ {
+ mprf("You feel less studious about %s.", skill_name(skill));
+ erase_any(you.sage_skills, which_sage);
+ erase_any(you.sage_xp, which_sage);
+ erase_any(you.sage_bonus, which_sage);
+ }
}
if (crawl_state.game_is_sprint())
@@ -3183,8 +3316,8 @@ void level_change(bool skip_attribute_increase)
if (you.experience_level == 13)
{
- mpr("You can now constrict enemies with your "
- "snake-like lower body.", MSGCH_INTRINSIC_GAIN);
+ mpr("Your tail grows strong enough to constrict"
+ " your enemies.", MSGCH_INTRINSIC_GAIN);
}
break;
@@ -3658,19 +3791,25 @@ int check_stealth(void)
const item_def *cloak = you.slot_item(EQ_CLOAK, false);
const item_def *boots = you.slot_item(EQ_BOOTS, false);
- if (arm)
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
{
- // [ds] New stealth penalty formula from rob: SP = 6 * (EP^2)
- const int ep = -property(*arm, PARM_EVASION);
- const int penalty = 6 * ep * ep;
-#if 0
- dprf("Stealth penalty for armour (ep: %d): %d", ep, penalty);
-#endif
- stealth -= penalty;
- }
+ if (arm)
+ {
+ // [ds] New stealth penalty formula from rob: SP = 6 * (EP^2)
+ const int ep = -property(*arm, PARM_EVASION);
+ const int penalty = 6 * ep * ep;
+ #if 0
+ dprf("Stealth penalty for armour (ep: %d): %d", ep, penalty);
+ #endif
+ stealth -= penalty;
+ }
- if (cloak && get_equip_race(*cloak) == ISFLAG_ELVEN)
- stealth += 20;
+ if (cloak && get_equip_race(*cloak) == ISFLAG_ELVEN)
+ stealth += 20;
+
+ stealth += scan_artefacts(ARTP_STEALTH);
+ }
if (you.duration[DUR_STEALTH])
stealth += 80;
@@ -3678,8 +3817,6 @@ int check_stealth(void)
if (you.duration[DUR_AGILITY])
stealth += 50;
- stealth += scan_artefacts(ARTP_STEALTH);
-
if (you.airborne())
stealth += 10;
@@ -3695,17 +3832,20 @@ int check_stealth(void)
// No stealth bonus from boots if you're airborne or in water
else if (boots)
{
- if (get_armour_ego_type(*boots) == SPARM_STEALTH)
- stealth += 50;
+ if (!you.suppressed())
+ {
+ if (get_armour_ego_type(*boots) == SPARM_STEALTH)
+ stealth += 50;
- if (get_equip_race(*boots) == ISFLAG_ELVEN)
- stealth += 20;
+ if (get_equip_race(*boots) == ISFLAG_ELVEN)
+ stealth += 20;
+ }
}
else if (player_mutation_level(MUT_HOOVES) > 0)
stealth -= 5 + 5 * player_mutation_level(MUT_HOOVES);
- else if (you.species == SP_FELID && !you.form)
+ else if (you.species == SP_FELID && (!you.form || you.form == TRAN_APPENDAGE))
stealth += 20; // paws
// Radiating silence is the negative complement of shouting all the
@@ -3791,7 +3931,6 @@ int get_expiration_threshold(duration_type dur)
return (10 * BASELINE_DELAY);
// These get no messages when they "flicker".
- case DUR_SAGE:
case DUR_BARGAIN:
return (15 * BASELINE_DELAY);
@@ -4020,7 +4159,7 @@ void display_char_status()
DUR_TRANSFORMATION,
STATUS_BURDEN,
STATUS_MANUAL,
- DUR_SAGE,
+ STATUS_SAGE,
DUR_BARGAIN,
DUR_BREATH_WEAPON,
DUR_LIQUID_FLAMES,
@@ -4102,15 +4241,23 @@ void display_char_status()
bool player_item_conserve(bool calc_unid)
{
- return (player_equip(EQ_AMULET, AMU_CONSERVATION, calc_unid)
- || player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_PRESERVATION));
+ return (!you.suppressed()
+ && (player_equip(EQ_AMULET, AMU_CONSERVATION, calc_unid)
+ || player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_PRESERVATION)));
}
int player_mental_clarity(bool calc_unid, bool items)
{
- int ret = 3 * player_equip(EQ_AMULET, AMU_CLARITY, calc_unid) * items
- + player_mutation_level(MUT_CLARITY)
- + scan_artefacts(ARTP_CLARITY);
+ int ret = 0;
+
+ ret += player_mutation_level(MUT_CLARITY);
+
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ ret += 3 * player_equip(EQ_AMULET, AMU_CLARITY, calc_unid) * items
+ + scan_artefacts(ARTP_CLARITY);
+ }
if (you.religion == GOD_ASHENZARI && you.piety >= piety_breakpoint(2)
&& !player_under_penance())
@@ -4123,8 +4270,180 @@ int player_mental_clarity(bool calc_unid, bool items)
int player_spirit_shield(bool calc_unid)
{
- return player_equip(EQ_AMULET, AMU_GUARDIAN_SPIRIT, calc_unid)
- + player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_SPIRIT_SHIELD);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return player_equip(EQ_AMULET, AMU_GUARDIAN_SPIRIT, calc_unid)
+ + player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_SPIRIT_SHIELD);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int player_effect_inaccuracy()
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return wearing_amulet(AMU_INACCURACY);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// See if the player has an ongoing effect as per the *MUT or +MUT properties.
+int player_effect_mutagenic()
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return scan_artefacts(ARTP_MUTAGENIC);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int player_res_mutation()
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return wearing_amulet(AMU_RESIST_MUTATION);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int player_effect_gourmand()
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return wearing_amulet(AMU_THE_GOURMAND);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int player_effect_stasis(bool calc_unid)
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return wearing_amulet(AMU_STASIS, calc_unid);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// This is a bit confusing. This is not the function that determines whether or
+// not a player is capable of teleporting, only whether they are specifically
+// under the influence of the "notele" effect. See item_blocks_teleport() in
+// item_use.cc for a superset of this function. In the future, I suppose we
+// could use this function for a dimensional anchor spell or something similar.
+int player_effect_notele(bool calc_unid)
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return scan_artefacts(ARTP_PREVENT_TELEPORTATION, calc_unid);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// permaswift effects like boots of running and lightning scales
+int player_effect_running()
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return player_equip_ego_type(EQ_BOOTS, SPARM_RUNNING);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int player_effect_cfly(bool calc_unid)
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return wearing_amulet(AMU_CONTROLLED_FLIGHT, calc_unid);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int player_effect_faith()
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return wearing_amulet(AMU_FAITH);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int player_effect_archmagi()
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return player_equip_ego_type(EQ_BODY_ARMOUR, SPARM_ARCHMAGI);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int player_effect_nocast()
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return scan_artefacts(ARTP_PREVENT_SPELLCASTING);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int player_effect_angry()
+{
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ return (scan_artefacts(ARTP_ANGRY)
+ || player_equip_unrand(UNRAND_TROG));
+ }
+ else
+ {
+ return 0;
+ }
}
// Returns whether the player has the effect of the amulet from a
@@ -4256,19 +4575,23 @@ int slaying_bonus(weapon_property_type which_affected, bool ranged)
{
int ret = 0;
- if (which_affected == PWPN_HIT)
- {
- ret += player_equip(EQ_RINGS_PLUS, RING_SLAYING);
- ret += scan_artefacts(ARTP_ACCURACY);
- if (player_equip_ego_type(EQ_GLOVES, SPARM_ARCHERY))
- ret += ranged ? 5 : -1;
- }
- else if (which_affected == PWPN_DAMAGE)
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
{
- ret += player_equip(EQ_RINGS_PLUS2, RING_SLAYING);
- ret += scan_artefacts(ARTP_DAMAGE);
- if (player_equip_ego_type(EQ_GLOVES, SPARM_ARCHERY))
- ret += ranged ? 3 : -1;
+ if (which_affected == PWPN_HIT)
+ {
+ ret += player_equip(EQ_RINGS_PLUS, RING_SLAYING);
+ ret += scan_artefacts(ARTP_ACCURACY);
+ if (player_equip_ego_type(EQ_GLOVES, SPARM_ARCHERY))
+ ret += ranged ? 5 : -1;
+ }
+ else if (which_affected == PWPN_DAMAGE)
+ {
+ ret += player_equip(EQ_RINGS_PLUS2, RING_SLAYING);
+ ret += scan_artefacts(ARTP_DAMAGE);
+ if (player_equip_ego_type(EQ_GLOVES, SPARM_ARCHERY))
+ ret += ranged ? 3 : -1;
+ }
}
ret += std::min(you.duration[DUR_SLAYING] / (13 * BASELINE_DELAY), 6);
@@ -4652,8 +4975,12 @@ int get_real_hp(bool trans, bool rotted)
if (!rotted)
hitp += you.hp_max_temp;
- if (trans)
- hitp += scan_artefacts(ARTP_HP);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ if (trans)
+ hitp += scan_artefacts(ARTP_HP);
+ }
// Being berserk makes you resistant to damage. I don't know why.
if (trans && you.berserk())
@@ -4698,6 +5025,7 @@ int get_real_mp(bool include_items)
if (enp > 50)
enp = 50 + ((enp - 50) / 2);
+ // Note that suppression doesn't affect the antimagic brand.
if (include_items && player_equip_ego_type(EQ_WEAPON, SPWPN_ANTIMAGIC))
enp /= 3;
@@ -5273,8 +5601,10 @@ void float_player(bool fly)
you.is_wall_clinging() ? "wall" : "floor");
}
- // Amulet of Controlled Flight can auto-ID.
- if (wearing_amulet(AMU_CONTROLLED_FLIGHT)
+ // Amulet of Controlled Flight can auto-ID
+ // ...but not if you're suppressed!
+ if (!you.suppressed()
+ && wearing_amulet(AMU_CONTROLLED_FLIGHT)
&& !extrinsic_amulet_effect(AMU_CONTROLLED_FLIGHT))
{
// it's important to do this only if the amulet is not identified yet,
@@ -5474,8 +5804,9 @@ void player::init()
transfer_skill_points = 0;
transfer_total_skill_points = 0;
- sage_bonus_skill = NUM_SKILLS;
- sage_bonus_degree = 0;
+ sage_skills.clear();
+ sage_xp.clear();
+ sage_bonus.clear();
manual_skill = SK_NONE;
manual_index = -1;
@@ -5843,7 +6174,7 @@ int calc_hunger(int food_cost)
int player::warding() const
{
- return (30 * player_warding());
+ return (60 * player_warding());
}
bool player::paralysed() const
@@ -6047,15 +6378,19 @@ int player::armour_class() const
AC -= ac_value / 2;
}
- AC += player_equip(EQ_RINGS_PLUS, RING_PROTECTION) * 100;
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ AC += player_equip(EQ_RINGS_PLUS, RING_PROTECTION) * 100;
- if (player_equip_ego_type(EQ_WEAPON, SPWPN_PROTECTION))
- AC += 500;
+ if (player_equip_ego_type(EQ_WEAPON, SPWPN_PROTECTION))
+ AC += 500;
- if (player_equip_ego_type(EQ_SHIELD, SPARM_PROTECTION))
- AC += 300;
+ if (player_equip_ego_type(EQ_SHIELD, SPARM_PROTECTION))
+ AC += 300;
- AC += scan_artefacts(ARTP_AC) * 100;
+ AC += scan_artefacts(ARTP_AC) * 100;
+ }
if (duration[DUR_ICY_ARMOUR])
AC += 400 + skill(SK_ICE_MAGIC, 100) / 3; // max 13
@@ -6448,19 +6783,23 @@ int player_res_magic(bool calc_unid, bool temp)
break;
}
- // randarts
- rm += scan_artefacts(ARTP_MAGIC, calc_unid);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ // randarts
+ rm += scan_artefacts(ARTP_MAGIC, calc_unid);
- // armour
- rm += 30 * player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_MAGIC_RESISTANCE,
- calc_unid);
+ // armour
+ rm += 30 * player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_MAGIC_RESISTANCE,
+ calc_unid);
- // rings of magic resistance
- rm += 40 * player_equip(EQ_RINGS, RING_PROTECTION_FROM_MAGIC, calc_unid);
+ // rings of magic resistance
+ rm += 40 * player_equip(EQ_RINGS, RING_PROTECTION_FROM_MAGIC, calc_unid);
- // Enchantment skill through staff of enchantment (up to 90).
- if (player_equip(EQ_STAFF, STAFF_ENCHANTMENT, calc_unid))
- rm += 9 + std::max(you.skill(SK_CHARMS, 3), you.skill(SK_HEXES, 3));
+ // Enchantment skill through staff of enchantment (up to 90).
+ if (player_equip(EQ_STAFF, STAFF_ENCHANTMENT, calc_unid))
+ rm += 9 + std::max(you.skill(SK_CHARMS, 3), you.skill(SK_HEXES, 3));
+ }
// Mutations
rm += 30 * player_mutation_level(MUT_MAGIC_RESISTANCE);
@@ -6515,7 +6854,8 @@ flight_type player::flight_mode() const
else if (is_levitating())
{
return (duration[DUR_CONTROLLED_FLIGHT]
- || wearing_amulet(AMU_CONTROLLED_FLIGHT) ? FL_FLY
+ || (!you.suppressed()
+ && wearing_amulet(AMU_CONTROLLED_FLIGHT)) ? FL_FLY
: FL_LEVITATE);
}
else
@@ -6949,10 +7289,20 @@ bool player::can_see_invisible(bool calc_unid, bool transient) const
int si = 0;
- si += player_equip(EQ_RINGS, RING_SEE_INVISIBLE, calc_unid);
+ // All effects negated by magical suppression should go in here.
+ if (!you.suppressed())
+ {
+ si += player_equip(EQ_RINGS, RING_SEE_INVISIBLE, calc_unid);
+
+ // armour: (checks head armour only)
+ si += player_equip_ego_type(EQ_HELMET, SPARM_SEE_INVISIBLE);
- // armour: (checks head armour only)
- si += player_equip_ego_type(EQ_HELMET, SPARM_SEE_INVISIBLE);
+ // randart wpns
+ int artefacts = scan_artefacts(ARTP_EYESIGHT, calc_unid);
+
+ if (artefacts > 0)
+ si += artefacts;
+ }
if (player_mutation_level(MUT_ACUTE_VISION) > 0)
si += player_mutation_level(MUT_ACUTE_VISION);
@@ -6968,12 +7318,6 @@ bool player::can_see_invisible(bool calc_unid, bool transient) const
if (transient && duration[DUR_SEE_INVISIBLE] > 0)
si++;
- // randart wpns
- int artefacts = scan_artefacts(ARTP_EYESIGHT, calc_unid);
-
- if (artefacts > 0)
- si += artefacts;
-
if (you.religion == GOD_ASHENZARI && you.piety >= piety_breakpoint(2)
&& !player_under_penance())
{
@@ -7378,25 +7722,17 @@ void player::accum_has_constricted()
bool player::attempt_escape()
{
- size_type thesize;
- int attfactor;
- int randfact;
monster *themonst;
if (!is_constricted())
return true;
- escape_attempts++;
- // player breaks free if size*attempts > 5 + d(12) + d(HD)
- // this is inefficient on purpose, simplify after debug
- thesize = body_size(PSIZE_BODY);
- attfactor = thesize * escape_attempts;
-
- randfact = roll_dice(1,5) + 5;
themonst = &env.mons[constricted_by];
- randfact += roll_dice(1,themonst->hit_dice);
+ escape_attempts++;
- if (attfactor > randfact)
+ // player breaks free if (4+n)d(8+str/4) >= 5d(8+HD/4)
+ if (roll_dice(4 + escape_attempts, 8 + div_rand_round(strength(), 4))
+ >= roll_dice(5, 8 + div_rand_round(themonst->hit_dice, 4)))
{
// message that you escaped
@@ -7405,6 +7741,9 @@ bool player::attempt_escape()
emsg += "'s grasp.";
mpr(emsg);
+ // Stun the monster to prevent it from constricting again right away.
+ themonst->speed_increment -= 5;
+
// update monster's has constricted info
for (int i = 0; i < MAX_CONSTRICT; i++)
if (themonst->constricting[i] == MHITYOU)
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index adc9f386c6..4c7a269cea 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -144,8 +144,9 @@ public:
unsigned int transfer_skill_points;
unsigned int transfer_total_skill_points;
- skill_type sage_bonus_skill; // If Sage is in effect, which skill it affects.
- int sage_bonus_degree; // How much bonus XP to give in that skill.
+ std::vector<skill_type> sage_skills; // skills with active Sage
+ std::vector<int> sage_xp; // how much more XP to redirect
+ std::vector<int> sage_bonus; // how much bonus XP to give in these skills
skill_type manual_skill;
int manual_index;
@@ -821,6 +822,18 @@ int player_res_torment(bool calc_unid = true, bool temp = true);
bool player_item_conserve(bool calc_unid = true);
int player_mental_clarity(bool calc_unid = true, bool items = true);
int player_spirit_shield(bool calc_unid = true);
+int player_effect_inaccuracy();
+int player_effect_mutagenic();
+int player_res_mutation();
+int player_effect_gourmand();
+int player_effect_stasis(bool calc_unid = true);
+int player_effect_notele(bool calc_unid = true);
+int player_effect_running();
+int player_effect_cfly(bool calc_unid = true);
+int player_effect_faith();
+int player_effect_archmagi();
+int player_effect_nocast();
+int player_effect_angry();
int player_likes_chunks(bool permanently = false);
bool player_likes_water(bool permanently = false);
@@ -888,13 +901,9 @@ void gain_exp(unsigned int exp_gained, unsigned int* actual_gain = NULL);
bool player_in_bat_form();
bool player_can_open_doors();
+bool player_can_handle_equipment();
bool player_can_reach_floor(std::string feat = "", bool quiet = false);
-inline bool player_can_handle_equipment()
-{
- return player_can_open_doors();
-}
-
void level_change(bool skip_attribute_increase = false);
void adjust_level(int diff, bool just_xp = false);
diff --git a/crawl-ref/source/process_desc.h b/crawl-ref/source/process_desc.h
index 4d1043ae2f..3e4d3d1af6 100644
--- a/crawl-ref/source/process_desc.h
+++ b/crawl-ref/source/process_desc.h
@@ -7,6 +7,7 @@
#define DESCRIBE_TEMPLATES_H
#include "describe.h"
+#include "lang-fake.h"
template<class T> void process_description(T &proc, const describe_info &inf);
template<class T> void process_quote(T &proc, const describe_info &inf);
@@ -22,27 +23,28 @@ inline void process_description(T &proc, const describe_info &inf)
const int height = proc.height();
std::string desc;
+ // most stuff goes through translate() twice unnecessarily, yadda yadda yadda
// How many lines is the title; we also seem to be adding 1 to
// start with.
- int num_lines = count_desc_lines(inf.title, line_width) + 1;
+ int num_lines = count_desc_lines(filtered_lang(inf.title), line_width) + 1;
- int body_lines = count_desc_lines(inf.body.str(), line_width);
- const int suffix_lines = count_desc_lines(inf.suffix, line_width);
- const int prefix_lines = count_desc_lines(inf.prefix, line_width);
- const int footer_lines = count_desc_lines(inf.footer, line_width)
+ int body_lines = count_desc_lines(filtered_lang(inf.body.str()), line_width);
+ const int suffix_lines = count_desc_lines(filtered_lang(inf.suffix), line_width);
+ const int prefix_lines = count_desc_lines(filtered_lang(inf.prefix), line_width);
+ const int footer_lines = count_desc_lines(filtered_lang(inf.footer), line_width)
+ (inf.footer.empty() ? 0 : 1);
if (inf.title.empty())
{
- desc = inf.body.str();
+ desc = filtered_lang(inf.body.str());
// There is a default 1 line addition for some reason.
num_lines = body_lines + 1;
}
else
{
- desc = inf.title + "\n\n";
- desc += inf.body.str();
+ desc = filtered_lang(inf.title) + "\n\n";
+ desc += filtered_lang(inf.body.str());
// Got 2 lines from the two \ns that weren't counted yet.
num_lines += body_lines + 2;
}
@@ -50,14 +52,14 @@ inline void process_description(T &proc, const describe_info &inf)
// Prefer the footer over the suffix.
if (num_lines + suffix_lines + footer_lines <= height)
{
- desc = desc + inf.suffix;
+ desc = desc + filtered_lang(inf.suffix);
num_lines += suffix_lines;
}
// Prefer the footer over the prefix.
if (num_lines + prefix_lines + footer_lines <= height)
{
- desc = inf.prefix + desc;
+ desc = filtered_lang(inf.prefix) + desc;
num_lines += prefix_lines;
}
@@ -70,7 +72,7 @@ inline void process_description(T &proc, const describe_info &inf)
if (newlines >= 0)
{
desc.append(newlines, '\n');
- desc = desc + inf.footer;
+ desc = desc + filtered_lang(inf.footer);
}
}
@@ -78,7 +80,7 @@ inline void process_description(T &proc, const describe_info &inf)
int lineno = 0;
while (!desc.empty())
{
- const std::string line = wordwrap_line(desc, line_width);
+ const std::string line = wordwrap_line(desc, line_width, false, true);
// If this is the bottom line of the display but not
// the last line of text, print an ellipsis instead.
@@ -141,7 +143,7 @@ inline void process_quote(T &proc, const describe_info &inf)
while (!desc.empty())
{
- proc.print(wordwrap_line(desc, line_width));
+ proc.print(wordwrap_line(desc, line_width, false, true));
if (!desc.empty())
proc.nextline();
}
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 68e23ccdb7..ba3929dcf7 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -2561,7 +2561,7 @@ int piety_scale(int piety)
if (piety < 0)
return (-piety_scale(-piety));
- if (wearing_amulet(AMU_FAITH))
+ if (player_effect_faith())
return (piety + div_rand_round(piety, 3));
return (piety);
@@ -3862,7 +3862,8 @@ void handle_god_time()
switch (you.religion)
{
case GOD_XOM:
- xom_tick();
+// Moved to _player_reacts()
+// xom_tick();
return;
case GOD_ELYVILON:
diff --git a/crawl-ref/source/rltiles/dc-dngn/vaults/the_teleporter_vaults.png b/crawl-ref/source/rltiles/dc-dngn/dngn_teleporter.png
index f0742ca77b..f0742ca77b 100644
--- a/crawl-ref/source/rltiles/dc-dngn/vaults/the_teleporter_vaults.png
+++ b/crawl-ref/source/rltiles/dc-dngn/dngn_teleporter.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_shoals.png b/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_shoals.png
new file mode 100644
index 0000000000..e892fb35ba
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_shoals.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_slime.png b/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_slime.png
new file mode 100644
index 0000000000..65dfb5dc1f
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_slime.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_snake.png b/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_snake.png
new file mode 100644
index 0000000000..3ef9fef57d
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_snake.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_swamp.png b/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_swamp.png
new file mode 100644
index 0000000000..2837913131
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-dngn/gateways/dngn_enter_swamp.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-dngn/vaults/the_teleporter_ice_cave.png b/crawl-ref/source/rltiles/dc-dngn/vaults/teleporter_ice_cave.png
index 5b220cd1e3..5b220cd1e3 100644
--- a/crawl-ref/source/rltiles/dc-dngn/vaults/the_teleporter_ice_cave.png
+++ b/crawl-ref/source/rltiles/dc-dngn/vaults/teleporter_ice_cave.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-feat.txt b/crawl-ref/source/rltiles/dc-feat.txt
index e1f2f3cce6..76468d8519 100644
--- a/crawl-ref/source/rltiles/dc-feat.txt
+++ b/crawl-ref/source/rltiles/dc-feat.txt
@@ -108,9 +108,8 @@ gravestone_ornate DNGN_GRAVESTONE_ORNATE
## strange machine for Tukima's Wizlab
machine_tukima DNGN_MACHINE_TUKIMA
-## tiles for the_teleporter vaults
-the_teleporter_vaults DNGN_THE_TELEPORTER_VAULTS
-the_teleporter_ice_cave DNGN_THE_TELEPORTER_ICE_CAVE
+## an icy teleporter
+teleporter_ice_cave DNGN_TELEPORTER_ICE_CAVE
## golden statues for the holy Pan level
golden_statue_1 DNGN_GOLDEN_STATUE
@@ -330,7 +329,11 @@ dngn_enter_zot_closed DNGN_ENTER_ZOT_CLOSED
dngn_enter_zot_open DNGN_ENTER_ZOT_OPEN
%rim 0
dngn_return_zot DNGN_RETURN_ZOT
+dngn_enter_snake DNGN_ENTER_SNAKE_PIT
+dngn_enter_swamp DNGN_ENTER_SWAMP
dngn_enter_spider DNGN_ENTER_SPIDER_NEST
+dngn_enter_shoals DNGN_ENTER_SHOALS
+dngn_enter_slime DNGN_ENTER_SLIME_PITS
dngn_enter_dis DNGN_ENTER_DIS
dngn_enter_gehenna DNGN_ENTER_GEHENNA
dngn_enter_cocytus DNGN_ENTER_COCYTUS
@@ -455,46 +458,123 @@ dngn_dry_fountain DNGN_DRY_FOUNTAIN
%repeat DNGN_DRY_FOUNTAIN DNGN_DRY_FOUNTAIN_WHITE
%resetcol
+dngn_teleporter DNGN_TELEPORTER
+
## Miscellaneous entries that get drawn on the background.
## Flavour is fixed again.
%sdir dc-misc/blood
-blood_red BLOOD
-blood_red1
-blood_red2
-blood_red3
-blood_red4
-wall_blood1_s WALL_BLOOD_S
-wall_blood2_s
-wall_blood3_s
-wall_blood4_s
-wall_blood5_s
-wall_blood6_s
-wall_blood7_s
-wall_blood8_s
-wall_blood1_w WALL_BLOOD_W
-wall_blood2_w
-wall_blood3_w
-wall_blood4_w
-wall_blood5_w
-wall_blood6_w
-wall_blood7_w
-wall_blood8_w
-wall_blood1_n WALL_BLOOD_N
-wall_blood2_n
-wall_blood3_n
-wall_blood4_n
-wall_blood5_n
-wall_blood6_n
-wall_blood7_n
-wall_blood8_n
-wall_blood1_e WALL_BLOOD_E
-wall_blood2_e
-wall_blood3_e
-wall_blood4_e
-wall_blood5_e
-wall_blood6_e
-wall_blood7_e
-wall_blood8_e
+blood_red00 BLOOD
+blood_red01
+blood_red02
+blood_red03
+blood_red04
+blood_red05
+blood_red06
+blood_red07
+blood_red08
+blood_red09
+blood_red10
+blood_red11
+blood_red12
+blood_red13
+blood_red14
+blood_red15
+blood_red16
+blood_red17
+blood_red18
+blood_red19
+blood_red20
+blood_red21
+blood_red22
+blood_red23
+blood_red24
+blood_red25
+blood_red26
+blood_red27
+blood_red28
+blood_red29
+wall_blood00_s WALL_BLOOD_S
+wall_blood01_s
+wall_blood03_s
+wall_blood04_s
+wall_blood05_s
+wall_blood06_s
+wall_blood07_s
+wall_blood08_s
+wall_blood09_s
+wall_blood10_s
+wall_blood11_s
+wall_blood12_s
+wall_blood13_s
+wall_blood14_s
+wall_blood15_s
+wall_blood16_s
+wall_blood17_s
+wall_blood18_s
+wall_blood00_w WALL_BLOOD_W
+wall_blood01_w
+wall_blood03_w
+wall_blood04_w
+wall_blood05_w
+wall_blood06_w
+wall_blood07_w
+wall_blood08_w
+wall_blood09_w
+wall_blood10_w
+wall_blood11_w
+wall_blood12_w
+wall_blood13_w
+wall_blood14_w
+wall_blood15_w
+wall_blood16_w
+wall_blood17_w
+wall_blood18_w
+wall_blood00_n WALL_BLOOD_N
+wall_blood01_n
+wall_blood03_n
+wall_blood04_n
+wall_blood05_n
+wall_blood06_n
+wall_blood07_n
+wall_blood08_n
+wall_blood09_n
+wall_blood10_n
+wall_blood11_n
+wall_blood12_n
+wall_blood13_n
+wall_blood14_n
+wall_blood15_n
+wall_blood16_n
+wall_blood17_n
+wall_blood18_n
+wall_blood00_e WALL_BLOOD_E
+wall_blood01_e
+wall_blood03_e
+wall_blood04_e
+wall_blood05_e
+wall_blood06_e
+wall_blood07_e
+wall_blood08_e
+wall_blood09_e
+wall_blood10_e
+wall_blood11_e
+wall_blood12_e
+wall_blood13_e
+wall_blood14_e
+wall_blood15_e
+wall_blood16_e
+wall_blood17_e
+wall_blood18_e
+wall_old_blood00 WALL_OLD_BLOOD
+wall_old_blood01
+wall_old_blood02
+wall_old_blood03
+wall_old_blood04
+wall_old_blood05
+wall_old_blood06
+wall_old_blood07
+wall_old_blood08
+wall_old_blood09
%sdir dc-misc
halo HALO
effect/halo_range HALO_RANGE
diff --git a/crawl-ref/source/rltiles/dc-item.txt b/crawl-ref/source/rltiles/dc-item.txt
index 8f029e082c..7c1d27e675 100644
--- a/crawl-ref/source/rltiles/dc-item.txt
+++ b/crawl-ref/source/rltiles/dc-item.txt
@@ -55,7 +55,9 @@ orcish_hammer2
dwarven_hammer1 WPN_HAMMER_DWARF
dwarven_hammer2
%rim 1
+#... if TAG_MAJOR_VERSION == 32
ankus WPN_ANKUS
+#...
bullwhip WPN_WHIP
bullwhip2
%rim 0
diff --git a/crawl-ref/source/rltiles/dc-misc.txt b/crawl-ref/source/rltiles/dc-misc.txt
index cfc8dfc44a..b90ceff2f0 100644
--- a/crawl-ref/source/rltiles/dc-misc.txt
+++ b/crawl-ref/source/rltiles/dc-misc.txt
@@ -65,6 +65,11 @@ cloud_magic_trail0 CLOUD_MAGIC_TRAIL_0
cloud_magic_trail1 CLOUD_MAGIC_TRAIL_1
cloud_magic_trail2 CLOUD_MAGIC_TRAIL_2
cloud_magic_trail3 CLOUD_MAGIC_TRAIL_3
+# rolling boulder dust
+cloud_dust_trail0 CLOUD_DUST_TRAIL_0
+cloud_dust_trail1 CLOUD_DUST_TRAIL_1
+cloud_dust_trail2 CLOUD_DUST_TRAIL_2
+cloud_dust_trail3 CLOUD_DUST_TRAIL_3
cloud_rain1 CLOUD_RAIN
cloud_rain2
cloud_grey_smoke CLOUD_MIST
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red.png
deleted file mode 100644
index 81ab20b052..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/blood_red.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red00.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red00.png
new file mode 100644
index 0000000000..a9047b7e85
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red00.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red01.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red01.png
new file mode 100644
index 0000000000..11083b5eae
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red01.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red02.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red02.png
new file mode 100644
index 0000000000..c575c93712
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red02.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red03.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red03.png
new file mode 100644
index 0000000000..5395c3b54e
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red03.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red04.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red04.png
new file mode 100644
index 0000000000..9fc6d63f8f
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red04.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red05.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red05.png
new file mode 100644
index 0000000000..9d9ec7e4cb
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red05.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red06.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red06.png
new file mode 100644
index 0000000000..452ce15a3a
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red06.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red07.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red07.png
new file mode 100644
index 0000000000..736b20e684
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red07.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red08.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red08.png
new file mode 100644
index 0000000000..6c862f4182
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red08.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red09.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red09.png
new file mode 100644
index 0000000000..574ce2c718
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red09.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red1.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red1.png
deleted file mode 100644
index 43c96dab35..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/blood_red1.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red10.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red10.png
new file mode 100644
index 0000000000..b79be42e98
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red10.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red11.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red11.png
new file mode 100644
index 0000000000..efaba26377
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red11.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red12.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red12.png
new file mode 100644
index 0000000000..519d48d7a4
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red12.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red13.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red13.png
new file mode 100644
index 0000000000..1886575024
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red13.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red14.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red14.png
new file mode 100644
index 0000000000..e4a0439536
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red14.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red15.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red15.png
new file mode 100644
index 0000000000..1a4c63a364
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red15.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red16.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red16.png
new file mode 100644
index 0000000000..8a8159ca8a
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red16.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red17.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red17.png
new file mode 100644
index 0000000000..d08e208dcc
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red17.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red18.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red18.png
new file mode 100644
index 0000000000..8cad1efc67
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red18.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red19.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red19.png
new file mode 100644
index 0000000000..f3fcbdbc03
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red19.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red2.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red2.png
deleted file mode 100644
index cea6c18c4f..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/blood_red2.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red20.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red20.png
new file mode 100644
index 0000000000..cb80de4da8
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red20.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red21.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red21.png
new file mode 100644
index 0000000000..4cbceef943
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red21.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red22.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red22.png
new file mode 100644
index 0000000000..76db5d4f55
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red22.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red23.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red23.png
new file mode 100644
index 0000000000..0bce386fac
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red23.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red24.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red24.png
new file mode 100644
index 0000000000..11e460f90d
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red24.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red25.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red25.png
new file mode 100644
index 0000000000..13f0b9975a
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red25.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red26.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red26.png
new file mode 100644
index 0000000000..5eddc385e0
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red26.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red27.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red27.png
new file mode 100644
index 0000000000..e1e3d08f36
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red27.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red28.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red28.png
new file mode 100644
index 0000000000..154a1ffda5
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red28.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red29.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red29.png
new file mode 100644
index 0000000000..756f9325a0
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/blood_red29.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red3.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red3.png
deleted file mode 100644
index 9ecdb60dbf..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/blood_red3.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/blood_red4.png b/crawl-ref/source/rltiles/dc-misc/blood/blood_red4.png
deleted file mode 100644
index 11547cd8ba..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/blood_red4.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_e.png
new file mode 100644
index 0000000000..2bb4916dbb
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_n.png
new file mode 100644
index 0000000000..d898da14da
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_s.png
new file mode 100644
index 0000000000..b5159a48a6
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_w.png
new file mode 100644
index 0000000000..ed1052ab5a
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood00_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_e.png
new file mode 100644
index 0000000000..a06bd2ded7
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_n.png
new file mode 100644
index 0000000000..afdf0bbc5f
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_s.png
new file mode 100644
index 0000000000..c5447ece85
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_w.png
new file mode 100644
index 0000000000..d807dab657
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood01_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_e.png
new file mode 100644
index 0000000000..7c212d14f5
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_n.png
new file mode 100644
index 0000000000..de4e84a57b
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_s.png
new file mode 100644
index 0000000000..1383323c5c
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_w.png
new file mode 100644
index 0000000000..4d1c012c53
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood03_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_e.png
new file mode 100644
index 0000000000..905c38f935
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_n.png
new file mode 100644
index 0000000000..cb56e6a604
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_s.png
new file mode 100644
index 0000000000..373a1c0235
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_w.png
new file mode 100644
index 0000000000..b79b5a8a59
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood04_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_e.png
new file mode 100644
index 0000000000..84fed0c114
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_n.png
new file mode 100644
index 0000000000..7a54821f28
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_s.png
new file mode 100644
index 0000000000..136a9e76e5
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_w.png
new file mode 100644
index 0000000000..722637ed51
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood05_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_e.png
new file mode 100644
index 0000000000..be207ff3fc
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_n.png
new file mode 100644
index 0000000000..107591bc99
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_s.png
new file mode 100644
index 0000000000..bbceb04b55
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_w.png
new file mode 100644
index 0000000000..a1f5fa821b
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood06_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_e.png
new file mode 100644
index 0000000000..c9a15bb7bc
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_n.png
new file mode 100644
index 0000000000..3626334184
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_s.png
new file mode 100644
index 0000000000..9ac16d489d
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_w.png
new file mode 100644
index 0000000000..ddcefa465d
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood07_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_e.png
new file mode 100644
index 0000000000..cc4ede13ca
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_n.png
new file mode 100644
index 0000000000..04668ee3f1
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_s.png
new file mode 100644
index 0000000000..a556e0935f
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_w.png
new file mode 100644
index 0000000000..4e6b1a8c04
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood08_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_e.png
new file mode 100644
index 0000000000..297bea2fae
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_n.png
new file mode 100644
index 0000000000..7c9fe971f9
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_s.png
new file mode 100644
index 0000000000..db67a52983
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_w.png
new file mode 100644
index 0000000000..f2f003564b
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood09_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_e.png
new file mode 100644
index 0000000000..408969cf19
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_n.png
new file mode 100644
index 0000000000..b873b2f9f4
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_s.png
new file mode 100644
index 0000000000..3b383c7e80
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_w.png
new file mode 100644
index 0000000000..ca3b2cc197
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood10_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_e.png
new file mode 100644
index 0000000000..d6174760bf
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_n.png
new file mode 100644
index 0000000000..fd5d4315eb
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_s.png
new file mode 100644
index 0000000000..4980415ed1
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_w.png
new file mode 100644
index 0000000000..ea3eab1758
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood11_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_e.png
new file mode 100644
index 0000000000..11b9788f18
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_n.png
new file mode 100644
index 0000000000..d43513191c
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_s.png
new file mode 100644
index 0000000000..efd7522e7e
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_w.png
new file mode 100644
index 0000000000..8965e69e83
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood12_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_e.png
new file mode 100644
index 0000000000..cbb1532e78
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_n.png
new file mode 100644
index 0000000000..c034e9d9a6
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_s.png
new file mode 100644
index 0000000000..5911b9388d
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_w.png
new file mode 100644
index 0000000000..534318a008
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood13_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_e.png
new file mode 100644
index 0000000000..7db0270afa
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_n.png
new file mode 100644
index 0000000000..c0c42668b4
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_s.png
new file mode 100644
index 0000000000..df5ffaa7b6
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_w.png
new file mode 100644
index 0000000000..c63df3be24
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood14_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_e.png
new file mode 100644
index 0000000000..18224e9368
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_n.png
new file mode 100644
index 0000000000..91eb42abb4
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_s.png
new file mode 100644
index 0000000000..818149ac2b
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_w.png
new file mode 100644
index 0000000000..ea2d1d34a4
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood15_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_e.png
new file mode 100644
index 0000000000..d126ed0d92
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_n.png
new file mode 100644
index 0000000000..601061d09f
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_s.png
new file mode 100644
index 0000000000..b6e3e95096
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_w.png
new file mode 100644
index 0000000000..c3846ed071
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood16_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_e.png
new file mode 100644
index 0000000000..2ae723d254
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_n.png
new file mode 100644
index 0000000000..0b42d7daf7
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_s.png
new file mode 100644
index 0000000000..a0cddcb106
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_w.png
new file mode 100644
index 0000000000..ef16a11b73
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood17_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_e.png
new file mode 100644
index 0000000000..4245ef35a9
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_e.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_n.png
new file mode 100644
index 0000000000..59ca0d35f2
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_n.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_s.png
new file mode 100644
index 0000000000..66bc85b217
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_s.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_w.png
new file mode 100644
index 0000000000..e730ee8af8
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood18_w.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_e.png
deleted file mode 100644
index 1bdd8c0ce5..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_e.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_n.png
deleted file mode 100644
index 14002209ce..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_n.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_s.png
deleted file mode 100644
index 8304d038c9..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_s.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_w.png
deleted file mode 100644
index 13bcf64e34..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood1_w.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_e.png
deleted file mode 100644
index 6dc99a2d0f..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_e.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_n.png
deleted file mode 100644
index d79270af0c..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_n.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_s.png
deleted file mode 100644
index a1e194e61f..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_s.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_w.png
deleted file mode 100644
index 0361ab7e9b..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood2_w.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_e.png
deleted file mode 100644
index 7980582706..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_e.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_n.png
deleted file mode 100644
index 5736f2f009..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_n.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_s.png
deleted file mode 100644
index d359b7ff52..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_s.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_w.png
deleted file mode 100644
index 8b91fbf5d0..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood3_w.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_e.png
deleted file mode 100644
index cfe701af2e..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_e.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_n.png
deleted file mode 100644
index ede049514f..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_n.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_s.png
deleted file mode 100644
index 2a8225b578..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_s.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_w.png
deleted file mode 100644
index d7b1723b65..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood4_w.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_e.png
deleted file mode 100644
index 16822d792d..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_e.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_n.png
deleted file mode 100644
index 3f0b50845f..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_n.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_s.png
deleted file mode 100644
index e1eed03125..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_s.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_w.png
deleted file mode 100644
index b5ff2f77bb..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood5_w.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_e.png
deleted file mode 100644
index 2f7fbfca6d..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_e.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_n.png
deleted file mode 100644
index d33ff7cbd8..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_n.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_s.png
deleted file mode 100644
index 68d6a2877f..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_s.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_w.png
deleted file mode 100644
index 255c3b8c19..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood6_w.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_e.png
deleted file mode 100644
index a10261ff52..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_e.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_n.png
deleted file mode 100644
index 6820c5caa6..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_n.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_s.png
deleted file mode 100644
index ddae51be70..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_s.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_w.png
deleted file mode 100644
index bb0f4a475b..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood7_w.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_e.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_e.png
deleted file mode 100644
index ad600d6e19..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_e.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_n.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_n.png
deleted file mode 100644
index 7368cee100..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_n.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_s.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_s.png
deleted file mode 100644
index 0b4fab6a8f..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_s.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_w.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_w.png
deleted file mode 100644
index ae37643181..0000000000
--- a/crawl-ref/source/rltiles/dc-misc/blood/wall_blood8_w.png
+++ /dev/null
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood00.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood00.png
new file mode 100644
index 0000000000..f23048d658
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood00.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood01.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood01.png
new file mode 100644
index 0000000000..de9cd60533
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood01.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood02.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood02.png
new file mode 100644
index 0000000000..68633fc305
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood02.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood03.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood03.png
new file mode 100644
index 0000000000..ed47faf993
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood03.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood04.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood04.png
new file mode 100644
index 0000000000..3186da9b6c
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood04.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood05.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood05.png
new file mode 100644
index 0000000000..d9ef77e3ba
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood05.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood06.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood06.png
new file mode 100644
index 0000000000..6db72ec4b8
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood06.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood07.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood07.png
new file mode 100644
index 0000000000..fe9cb9a64d
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood07.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood08.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood08.png
new file mode 100644
index 0000000000..1ef5ead3dc
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood08.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood09.png b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood09.png
new file mode 100644
index 0000000000..eb80082001
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/blood/wall_old_blood09.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-mon.txt b/crawl-ref/source/rltiles/dc-mon.txt
index e21584bc7f..099cf9fd83 100644
--- a/crawl-ref/source/rltiles/dc-mon.txt
+++ b/crawl-ref/source/rltiles/dc-mon.txt
@@ -163,6 +163,10 @@ jellyfish MONS_JELLYFISH /*'J'*/
goliath_beetle MONS_GOLIATH_BEETLE
boring_beetle MONS_BORING_BEETLE
boulder_beetle MONS_BOULDER_BEETLE
+boulder_beetle_rolling0 MONS_BOULDER_BEETLE_ROLLING
+boulder_beetle_rolling1
+boulder_beetle_rolling2
+boulder_beetle_rolling3
## Frogs ('F')
%sdir dc-mon/unique
diff --git a/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling0.png b/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling0.png
new file mode 100644
index 0000000000..8137204f50
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling0.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling1.png b/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling1.png
new file mode 100644
index 0000000000..67b78c0398
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling1.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling2.png b/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling2.png
new file mode 100644
index 0000000000..3272efbce6
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling2.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling3.png b/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling3.png
new file mode 100644
index 0000000000..24032cbf41
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-mon/animals/boulder_beetle_rolling3.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-mon/demons/hell_sentinel.png b/crawl-ref/source/rltiles/dc-mon/demons/hell_sentinel.png
index 335a8fa1a8..8980016d75 100644
--- a/crawl-ref/source/rltiles/dc-mon/demons/hell_sentinel.png
+++ b/crawl-ref/source/rltiles/dc-mon/demons/hell_sentinel.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-player.txt b/crawl-ref/source/rltiles/dc-player.txt
index 10f5616d43..c1c56137d5 100644
--- a/crawl-ref/source/rltiles/dc-player.txt
+++ b/crawl-ref/source/rltiles/dc-player.txt
@@ -544,7 +544,9 @@ mace MACE2
mace3 MACE
mace2 GREAT_MACE
mace_ruby MACE_RUBY
+#... if TAG_MAJOR_VERSION == 32
ankus ANKUS
+#...
morningstar MORNINGSTAR2
morningstar2 MORNINGSTAR
eveningstar EVENINGSTAR
diff --git a/crawl-ref/source/rltiles/effect/cloud_dust_trail0.png b/crawl-ref/source/rltiles/effect/cloud_dust_trail0.png
new file mode 100644
index 0000000000..106bbc90f0
--- /dev/null
+++ b/crawl-ref/source/rltiles/effect/cloud_dust_trail0.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/effect/cloud_dust_trail1.png b/crawl-ref/source/rltiles/effect/cloud_dust_trail1.png
new file mode 100644
index 0000000000..15f6619917
--- /dev/null
+++ b/crawl-ref/source/rltiles/effect/cloud_dust_trail1.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/effect/cloud_dust_trail2.png b/crawl-ref/source/rltiles/effect/cloud_dust_trail2.png
new file mode 100644
index 0000000000..b684e0c225
--- /dev/null
+++ b/crawl-ref/source/rltiles/effect/cloud_dust_trail2.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/effect/cloud_dust_trail3.png b/crawl-ref/source/rltiles/effect/cloud_dust_trail3.png
new file mode 100644
index 0000000000..9e84aa0a1b
--- /dev/null
+++ b/crawl-ref/source/rltiles/effect/cloud_dust_trail3.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/item/weapon/elven_dagger1.png b/crawl-ref/source/rltiles/item/weapon/elven_dagger1.png
index 2a458967f5..5e2abca00d 100644
--- a/crawl-ref/source/rltiles/item/weapon/elven_dagger1.png
+++ b/crawl-ref/source/rltiles/item/weapon/elven_dagger1.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/item/weapon/elven_dagger2.png b/crawl-ref/source/rltiles/item/weapon/elven_dagger2.png
index 0fdc0f7cec..20fc56a253 100644
--- a/crawl-ref/source/rltiles/item/weapon/elven_dagger2.png
+++ b/crawl-ref/source/rltiles/item/weapon/elven_dagger2.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/item/weapon/elven_short_sword1.png b/crawl-ref/source/rltiles/item/weapon/elven_short_sword1.png
index 18e342bde2..08313f81f2 100644
--- a/crawl-ref/source/rltiles/item/weapon/elven_short_sword1.png
+++ b/crawl-ref/source/rltiles/item/weapon/elven_short_sword1.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/item/weapon/elven_short_sword2.png b/crawl-ref/source/rltiles/item/weapon/elven_short_sword2.png
index b4b3f99c1a..2820afb0ab 100644
--- a/crawl-ref/source/rltiles/item/weapon/elven_short_sword2.png
+++ b/crawl-ref/source/rltiles/item/weapon/elven_short_sword2.png
Binary files differ
diff --git a/crawl-ref/source/scripts/csim.lua b/crawl-ref/source/scripts/csim.lua
new file mode 100644
index 0000000000..980b90fb1f
--- /dev/null
+++ b/crawl-ref/source/scripts/csim.lua
@@ -0,0 +1,29 @@
+-- a crude constriction escape simulator
+
+local niters = 10000
+local mons = { [1]="ball python",
+ [5]="naga",
+ [10]="naga_warrior",
+ [15]="greater_naga",
+ [23]="tentacled_monstrosity"
+ }
+
+for hd,mon in pairs(mons) do
+ crawl.stderr(string.format("Against %s HD %d", mon, hd))
+ crawl.stderr("| str | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |")
+ for str = 3, 27, 3 do
+ local line = string.format("| %02d |", str)
+ for turns = 1, 8 do
+ local escape = 0
+ for i = 1, niters do
+ if crawl.roll_dice(4+turns, 8 + crawl.div_rand_round(str, 4))
+ >= crawl.roll_dice(5, 8 + crawl.div_rand_round(hd, 4)) then
+ escape = escape + 1
+ end
+ end
+ line = line .. string.format(" %5.1f |", escape * 100 / niters)
+ end
+ crawl.stderr(line)
+ end
+ crawl.stderr("")
+end
diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc
index 950e0dff4d..62517d08c2 100644
--- a/crawl-ref/source/shopping.cc
+++ b/crawl-ref/source/shopping.cc
@@ -971,7 +971,9 @@ unsigned int item_value(item_def item, bool ident)
valued += 35;
break;
+#if TAG_MAJOR_VERSION == 32
case WPN_ANKUS:
+#endif
case WPN_WAR_AXE:
case WPN_MORNINGSTAR:
case WPN_SABRE:
diff --git a/crawl-ref/source/show.cc b/crawl-ref/source/show.cc
index ec9f33aba6..63340f26aa 100644
--- a/crawl-ref/source/show.cc
+++ b/crawl-ref/source/show.cc
@@ -392,8 +392,11 @@ static void _update_monster(monster* mons)
you.attribute[ATTR_SEEN_INVIS_SEED] = random_int();
}
+ bool show_location = (mons->friendly()
+ || (mons->constricted_by == MHITYOU));
+
// maybe show unstealthy invis monsters
- if (mons->friendly()
+ if (show_location
|| _hashed_rand(mons, 0, 7) >= mons->stealth() + 4)
{
// We cannot use regular randomness here, otherwise redrawing the
@@ -401,13 +404,12 @@ static void _update_monster(monster* mons)
// seed too -- but it needs to be regenerated every turn.
// Maybe mark their square.
- if (mons->friendly()
+ if (show_location
|| mons->stealth() <= -2
|| mons->stealth() <= 2 && !_hashed_rand(mons, 1, 4))
{
env.map_knowledge(gp).set_invisible_monster();
- // Just display the actual position for friendlies.
- if (mons->friendly())
+ if (show_location) // Don't add extra fake trails.
return;
}
diff --git a/crawl-ref/source/showsymb.cc b/crawl-ref/source/showsymb.cc
index 48c7b2337a..6fc84eaea3 100644
--- a/crawl-ref/source/showsymb.cc
+++ b/crawl-ref/source/showsymb.cc
@@ -95,7 +95,7 @@ unsigned short _cell_feat_show_colour(const map_cell& cell, bool coloured)
colour = ETC_LIQUEFIED;
}
- if (feat >= DNGN_FLOOR_MIN && feat <= DNGN_FLOOR_MAX)
+ if (feat == DNGN_FLOOR)
{
if (cell.flags & MAP_HALOED)
{
diff --git a/crawl-ref/source/skills.cc b/crawl-ref/source/skills.cc
index 956a2fe968..2b79eaae82 100644
--- a/crawl-ref/source/skills.cc
+++ b/crawl-ref/source/skills.cc
@@ -298,12 +298,7 @@ static void _check_inventory_skills()
static void _check_equipment_skills()
{
- skill_set_iter it = you.stop_train.find(SK_ARMOUR);
- const item_def *armour = you.slot_item(EQ_BODY_ARMOUR, true);
- if (it != you.stop_train.end() && armour && property(*armour, PARM_EVASION))
- you.stop_train.erase(it);
-
- it = you.stop_train.find(SK_SHIELDS);
+ skill_set_iter it = you.stop_train.find(SK_SHIELDS);
if (it != you.stop_train.end() && you.slot_item(EQ_SHIELD, true))
you.stop_train.erase(it);
}
@@ -441,6 +436,7 @@ bool training_restricted(skill_type sk)
case SK_FIGHTING:
// Requiring missiles would mean disabling the skill when you run out.
case SK_THROWING:
+ case SK_ARMOUR:
case SK_DODGING:
case SK_STEALTH:
case SK_STABBING:
@@ -562,13 +558,13 @@ void init_training()
skills.init(0);
for (int i = 0; i < NUM_SKILLS; ++i)
if (skill_trained(i))
- skills[i] = you.skill_points[i];
+ skills[i] = pow(you.skill_points[i], 2);
_scale_array(skills, EXERCISE_QUEUE_SIZE, true);
_init_queue(you.exercises, skills);
for (int i = 0; i < NUM_SKILLS; ++i)
- skills[i] = you.skill_points[i];
+ skills[i] = pow(you.skill_points[i], 2);
_scale_array(skills, EXERCISE_QUEUE_SIZE, true);
_init_queue(you.exercises_all, skills);
@@ -1058,6 +1054,7 @@ void set_skill_level(skill_type skill, double amount)
// Maximum number of skill points to transfer in one go.
// It's max_xp*10/cost rounded up.
int max_skp = (max_xp * 10 + cost - 1) / cost;
+ max_skp = std::max(max_skp, 1);
int delta_skp = std::min<int>(abs(target - you.skill_points[skill]),
max_skp);
int delta_xp = (delta_skp * cost + 9) / 10;
diff --git a/crawl-ref/source/skills2.cc b/crawl-ref/source/skills2.cc
index 30148663d8..41dfdfa055 100644
--- a/crawl-ref/source/skills2.cc
+++ b/crawl-ref/source/skills2.cc
@@ -146,7 +146,9 @@ int get_skill_progress(skill_type sk, int level, int points, int scale)
const int needed = skill_exp_needed(level + 1, sk);
const int prev_needed = skill_exp_needed(level, sk);
- const int amt_done = points - prev_needed;
+ // A scale as small as 92 would overflow with 31 bits if skill_rdiv()
+ // is involved: needed can be 91985, skill_rdiv() multiplies by 256.
+ const int64_t amt_done = points - prev_needed;
int prog = (amt_done * scale) / (needed - prev_needed);
ASSERT(prog >= 0);
diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc
index 312fae2c85..e3084bd01e 100644
--- a/crawl-ref/source/spl-book.cc
+++ b/crawl-ref/source/spl-book.cc
@@ -1436,9 +1436,7 @@ int staff_spell(int staff)
int food = spell_hunger(spell, true);
- // For now player_energy() is always 0, because you've got to
- // be wielding the rod...
- if (you.is_undead == US_UNDEAD || player_energy() > 0)
+ if (you.is_undead == US_UNDEAD)
food = 0;
else
food = calc_hunger(food);
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index 2f561ac773..f0c144f5bd 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -373,7 +373,7 @@ int spell_fail(spell_type spell)
}
}
- chance2 += 10 * player_mutation_level(MUT_WILD_MAGIC);
+ chance2 += 7 * player_mutation_level(MUT_WILD_MAGIC);
// Apply the effects of Vehumet and items of wizardry.
chance2 = _apply_spellcasting_success_boosts(spell, chance2);
@@ -494,7 +494,7 @@ static int _spell_enhancement(unsigned int typeflags)
if (you.attribute[ATTR_SHADOWS])
enhanced -= 2;
- if (player_equip_ego_type(EQ_BODY_ARMOUR, SPARM_ARCHMAGI))
+ if (player_effect_archmagi())
enhanced++;
enhanced += augmentation_amount();
@@ -536,7 +536,7 @@ static bool _can_cast()
}
// Randart weapons.
- if (scan_artefacts(ARTP_PREVENT_SPELLCASTING))
+ if (player_effect_nocast())
{
mpr("Something interferes with your magic!");
return false;
@@ -726,7 +726,6 @@ bool cast_a_spell(bool check_range, spell_type spell)
}
}
- const bool staff_energy = player_energy();
you.last_cast_spell = spell;
const spret_type cast_result = your_spells(spell, 0, true, check_range);
if (cast_result == SPRET_ABORT)
@@ -746,7 +745,7 @@ bool cast_a_spell(bool check_range, spell_type spell)
dec_mp(spell_mana(spell));
- if (!staff_energy && you.is_undead != US_UNDEAD)
+ if (you.is_undead != US_UNDEAD)
{
const int spellh = calc_hunger(spell_hunger(spell));
if (spellh > 0)
@@ -1691,11 +1690,13 @@ static double _get_true_fail_rate(int raw_fail)
//PIE: the negative term takes the maximum of 100 (or 99) into
//consideration. Note that only one term can exceed it in this case,
//which is why this works.
- return (double) (_tetrahedral_number(target) - 2*_tetrahedral_number(target-101) - _tetrahedral_number(target-100))/1020100;
+ return (double) (_tetrahedral_number(target)
+ - 2*_tetrahedral_number(target - 101)
+ - _tetrahedral_number(target - 100)) / 1020100;
}
//The random2avg distribution is symmetric, so the last interval is
//essentially the same as the first interval.
- return (double) (1020100 - _tetrahedral_number(300 - target))/1020100;
+ return (double) (1020100 - _tetrahedral_number(300 - target)) / 1020100;
}
diff --git a/crawl-ref/source/spl-damage.cc b/crawl-ref/source/spl-damage.cc
index 81f9d8514f..7773f55c64 100644
--- a/crawl-ref/source/spl-damage.cc
+++ b/crawl-ref/source/spl-damage.cc
@@ -682,7 +682,7 @@ spret_type vampiric_drain(int pow, monster* mons, bool fail)
hp_gain /= 2;
- if (hp_gain && !mons_was_summoned)
+ if (hp_gain && !mons_was_summoned && !you.duration[DUR_DEATHS_DOOR])
{
mpr("You feel life coursing into your body.");
inc_hp(hp_gain);
diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h
index e8d0061129..ff6bce909b 100644
--- a/crawl-ref/source/spl-data.h
+++ b/crawl-ref/source/spl-data.h
@@ -106,7 +106,7 @@ struct spell_desc
0,
SPFLAG_DIR_OR_TARGET | SPFLAG_BATTLE, // rod of striking
1,
- 25,
+ 50,
5, 5,
0,
NULL,
@@ -647,7 +647,7 @@ struct spell_desc
SPFLAG_DIR_OR_TARGET,
4,
100,
- 5, 5,
+ 7, 7,
0,
NULL,
true,
diff --git a/crawl-ref/source/spl-goditem.cc b/crawl-ref/source/spl-goditem.cc
index a2b82bae3e..3910b885e3 100644
--- a/crawl-ref/source/spl-goditem.cc
+++ b/crawl-ref/source/spl-goditem.cc
@@ -399,14 +399,20 @@ void antimagic()
DUR_PETRIFYING, DUR_SHROUD_OF_GOLUBRIA
};
+ bool need_msg = false;
+
if (!you.permanent_levitation() && !you.permanent_flight()
&& you.duration[DUR_LEVITATION] > 11)
{
you.duration[DUR_LEVITATION] = 11;
+ need_msg = true;
}
if (!you.permanent_flight() && you.duration[DUR_CONTROLLED_FLIGHT] > 11)
+ {
you.duration[DUR_CONTROLLED_FLIGHT] = 11;
+ need_msg = true;
+ }
if (you.duration[DUR_TELEPORT] > 0)
{
@@ -419,8 +425,22 @@ void antimagic()
you.duration[DUR_SLOW] = std::max(you.duration[DUR_EXHAUSTED], 1);
for (unsigned int i = 0; i < ARRAYSZ(dur_list); ++i)
+ {
if (you.duration[dur_list[i]] > 1)
+ {
you.duration[dur_list[i]] = 1;
+ need_msg = true;
+ }
+ }
+
+ bool danger = need_expiration_warning(you.pos());
+
+ if (need_msg)
+ {
+ mprf(danger ? MSGCH_DANGER : MSGCH_WARN,
+ "%sYour magical effects are unravelling.",
+ danger ? "Careful! " : "");
+ }
contaminate_player(-1 * (1 + random2(5)));
}
@@ -505,6 +525,9 @@ static bool _mark_detected_creature(coord_def where, monster* mon,
place.set(where.x + random2(fuzz_diam) - fuzz_radius,
where.y + random2(fuzz_diam) - fuzz_radius);
+ if (!map_bounds(place))
+ continue;
+
// If the player would be able to see a monster at this location
// don't place it there.
if (you.see_cell(place))
@@ -516,7 +539,7 @@ static bool _mark_detected_creature(coord_def where, monster* mon,
// Don't print monsters on terrain they cannot pass through,
// not even if said terrain has since changed.
- if (map_bounds(place) && !env.map_knowledge(place).changed()
+ if (!env.map_knowledge(place).changed()
&& mon->can_pass_through_feat(grd(place)))
{
found_good = true;
@@ -839,7 +862,7 @@ static bool _do_imprison(int pow, const coord_def& where, bool zin)
if (grd(*ai) == safe_tiles[i] || feat_is_trap(grd(*ai), true))
proceed = true;
- if (!proceed && grd(*ai) > DNGN_MAX_NONREACH)
+ if (!proceed && feat_is_reachable_past(grd(*ai)))
{
success = false;
none_vis = false;
diff --git a/crawl-ref/source/spl-miscast.cc b/crawl-ref/source/spl-miscast.cc
index 12a0b1be38..cf26613f7b 100644
--- a/crawl-ref/source/spl-miscast.cc
+++ b/crawl-ref/source/spl-miscast.cc
@@ -1153,107 +1153,90 @@ void MiscastEffect::_translocation(int severity)
break;
case 2: // less harmless
- {
- bool reroll = true;
-
- while (reroll)
+ reroll_2:
+ switch (random2(7))
{
- switch (random2(7))
+ case 0:
+ case 1:
+ case 2:
+ you_msg = "You are caught in a strong localised spatial "
+ "distortion.";
+ mon_msg_seen = "@The_monster@ is caught in a strong localised "
+ "spatial distortion.";
+ mon_msg_unseen = "A piece of empty space twists and writhes.";
+ _ouch(9 + random2avg(23, 2));
+ break;
+ case 3:
+ case 4:
+ you_msg = "Space warps around you!";
+ mon_msg_seen = "Space warps around @the_monster@!";
+ mon_msg_unseen = "A piece of empty space twists and writhes.";
+ _ouch(5 + random2avg(9, 2));
+ if (target->alive())
{
- case 0:
- case 1:
- case 2:
- you_msg = "You are caught in a strong localised spatial "
- "distortion.";
- mon_msg_seen = "@The_monster@ is caught in a strong localised "
- "spatial distortion.";
- mon_msg_unseen = "A piece of empty space twists and writhes.";
- _ouch(9 + random2avg(23, 2));
- reroll = false;
- break;
- case 3:
- case 4:
- you_msg = "Space warps around you!";
- mon_msg_seen = "Space warps around @the_monster@!";
- mon_msg_unseen = "A piece of empty space twists and writhes.";
- _ouch(5 + random2avg(9, 2));
- reroll = false;
+ if (one_chance_in(3))
+ target->teleport(true);
+ else
+ target->blink(false);
if (target->alive())
- {
- if (one_chance_in(3))
- target->teleport(true);
- else
- target->blink(false);
_potion_effect(POT_CONFUSION, 40);
- reroll = false;
- }
- break;
- case 5:
- {
- bool success = false;
-
- for (int i = 1 + random2(3); i >= 0; --i)
- {
- if (_create_monster(MONS_SPATIAL_VORTEX, 3))
- success = true;
- }
-
- if (success)
- all_msg = "Space twists in upon itself!";
- reroll = false;
- break;
}
- case 6:
- reroll = !_send_to_abyss();
- break;
+ break;
+ case 5:
+ {
+ bool success = false;
+
+ for (int i = 1 + random2(3); i >= 0; --i)
+ {
+ if (_create_monster(MONS_SPATIAL_VORTEX, 3))
+ success = true;
}
- }
+ if (success)
+ all_msg = "Space twists in upon itself!";
+ break;
+ }
+ case 6:
+ if (!_send_to_abyss())
+ goto reroll_2;
+ break;
+ }
break;
- }
case 3: // much less harmless
- {
- bool reroll = true;
-
- while (reroll)
+ reroll_3:
+ // Don't use the last case for monsters.
+ switch (random2(target->is_player() ? 4 : 3))
{
- // Don't use the last case for monsters.
- switch (random2(target->is_player() ? 4 : 3))
+ case 0:
+ you_msg = "You are caught in an extremely strong localised "
+ "spatial distortion!";
+ mon_msg_seen = "@The_monster@ is caught in an extremely strong "
+ "localised spatial distortion!";
+ mon_msg_unseen = "A rift temporarily opens in the fabric of space!";
+ _ouch(15 + random2avg(29, 2));
+ break;
+ case 1:
+ you_msg = "Space warps crazily around you!";
+ mon_msg_seen = "Space warps crazily around @the_monster@!";
+ mon_msg_unseen = "A rift temporarily opens in the fabric of space!";
+ if (_ouch(9 + random2avg(17, 2)) && target->alive())
{
- case 0:
- you_msg = "You are caught in an extremely strong localised "
- "spatial distortion!";
- mon_msg_seen = "@The_monster@ is caught in an extremely strong "
- "localised spatial distortion!";
- mon_msg_unseen = "A rift temporarily opens in the fabric of space!";
- _ouch(15 + random2avg(29, 2));
- reroll = false;
- break;
- case 1:
- you_msg = "Space warps crazily around you!";
- mon_msg_seen = "Space warps crazily around @the_monster@!";
- mon_msg_unseen = "A rift temporarily opens in the fabric of space!";
- if (_ouch(9 + random2avg(17, 2)) && target->alive())
- {
- target->teleport(true);
+ target->teleport(true);
+ if (target->alive())
_potion_effect(POT_CONFUSION, 60);
- }
- reroll = false;
- break;
- case 2:
- reroll = !_send_to_abyss();
- break;
- case 3:
- contaminate_player(random2avg(19, 3), spell != SPELL_NO_SPELL);
- reroll = false;
- break;
}
+ break;
+ case 2:
+ if (!_send_to_abyss())
+ goto reroll_3;
+ break;
+ case 3:
+ contaminate_player(random2avg(19, 3), spell != SPELL_NO_SPELL);
+ break;
}
-
break;
}
- }
}
void MiscastEffect::_summoning(int severity)
diff --git a/crawl-ref/source/spl-other.cc b/crawl-ref/source/spl-other.cc
index 583c2ae63d..e383b85971 100644
--- a/crawl-ref/source/spl-other.cc
+++ b/crawl-ref/source/spl-other.cc
@@ -332,6 +332,7 @@ static int _intoxicate_monsters(coord_def where, int pow, int, actor *)
if (x_chance_in_y(40 + pow/3, 100))
{
mons->add_ench(mon_enchant(ENCH_CONFUSION, 0, &you));
+ simple_monster_message(mons, " looks rather confused.");
return 1;
}
return 0;
@@ -340,6 +341,7 @@ static int _intoxicate_monsters(coord_def where, int pow, int, actor *)
spret_type cast_intoxicate(int pow, bool fail)
{
fail_check();
+ mpr("You radiate an intoxicating aura.");
if (x_chance_in_y(60 - pow/3, 100))
potion_effect(POT_CONFUSION, 10 + (100 - pow) / 10);
diff --git a/crawl-ref/source/spl-selfench.cc b/crawl-ref/source/spl-selfench.cc
index a39a023928..e2df7b5ce5 100644
--- a/crawl-ref/source/spl-selfench.cc
+++ b/crawl-ref/source/spl-selfench.cc
@@ -21,6 +21,7 @@
#include "religion.h"
#include "spl-cast.h"
#include "spl-other.h"
+#include "spl-transloc.h"
#include "spl-util.h"
#include "stuff.h"
#include "transform.h"
@@ -240,8 +241,12 @@ spret_type cast_insulation(int power, bool fail)
spret_type cast_teleport_control(int power, bool fail)
{
fail_check();
- you.increase_duration(DUR_CONTROL_TELEPORT, 10 + random2(power), 50,
- "You feel in control.");
+ if (allow_control_teleport(true))
+ mpr("You feel in control.");
+ else
+ mpr("You feel your control is inadequate.");
+
+ you.increase_duration(DUR_CONTROL_TELEPORT, 10 + random2(power), 50);
return SPRET_SUCCESS;
}
diff --git a/crawl-ref/source/spl-summoning.cc b/crawl-ref/source/spl-summoning.cc
index d1795857fa..fe992a0507 100644
--- a/crawl-ref/source/spl-summoning.cc
+++ b/crawl-ref/source/spl-summoning.cc
@@ -180,7 +180,9 @@ static bool _snakable_weapon(const item_def& item)
return (item.base_type == OBJ_WEAPONS
&& !is_artefact(item)
&& (item.sub_type == WPN_CLUB
+#if TAG_MAJOR_VERSION == 32
|| item.sub_type == WPN_ANKUS
+#endif
|| item.sub_type == WPN_GIANT_CLUB
|| item.sub_type == WPN_GIANT_SPIKED_CLUB
|| item.sub_type == WPN_SPEAR
@@ -1214,7 +1216,7 @@ bool can_cast_malign_gateway()
return count_malign_gateways() < 1;
}
-coord_def find_gateway_location (actor* caster, bool (*environment_checker)(dungeon_feature_type))
+coord_def find_gateway_location (actor* caster)
{
coord_def point = coord_def(0, 0);
@@ -1224,7 +1226,6 @@ coord_def find_gateway_location (actor* caster, bool (*environment_checker)(dung
unsigned compass_idx[8] = {0, 1, 2, 3, 4, 5, 6, 7};
std::random_shuffle(compass_idx, compass_idx + 8);
- bool check_environment = (environment_checker != NULL);
for (unsigned i = 0; i < 8; ++i)
{
@@ -1237,7 +1238,7 @@ coord_def find_gateway_location (actor* caster, bool (*environment_checker)(dung
for (int t = 0; t < tries; t++)
{
test = caster->pos() + (delta * (2+t+random2(4)));
- if (!in_bounds(test) || check_environment && !feat_is_test(test, environment_checker)
+ if (!in_bounds(test) || !feat_is_malign_gateway_suitable(grd(test))
|| actor_at(test) || count_neighbours_with_func(test, &feat_is_solid) != 0
|| !caster->see_cell(test))
{
@@ -1274,15 +1275,19 @@ spret_type cast_malign_gateway(actor * caster, int pow, god_type god, bool fail)
env.markers.add(new map_malign_gateway_marker(point,
malign_gateway_duration,
is_player,
- is_player ? "" : caster->as_monster()->full_name(DESC_A, true),
- is_player ? BEH_FRIENDLY : attitude_creation_behavior(caster->as_monster()->attitude),
+ is_player ? ""
+ : caster->as_monster()->full_name(DESC_A, true),
+ is_player ? BEH_FRIENDLY
+ : attitude_creation_behavior(
+ caster->as_monster()->attitude),
god,
pow));
env.markers.clear_need_activate();
env.grid(point) = DNGN_MALIGN_GATEWAY;
noisy(10, point);
- mpr("The dungeon shakes, a horrible noise fills the air, and a portal to some otherworldly place is opened!", MSGCH_WARN);
+ mpr("The dungeon shakes, a horrible noise fills the air, and a portal "
+ "to some otherworldly place is opened!", MSGCH_WARN);
if (one_chance_in(5) && caster->is_player())
{
diff --git a/crawl-ref/source/spl-summoning.h b/crawl-ref/source/spl-summoning.h
index 257591a98f..144c295f17 100644
--- a/crawl-ref/source/spl-summoning.h
+++ b/crawl-ref/source/spl-summoning.h
@@ -59,8 +59,7 @@ spret_type cast_summon_horrible_things(int pow, god_type god, bool fail);
bool can_cast_malign_gateway();
spret_type cast_malign_gateway(actor* caster, int pow,
god_type god = GOD_NO_GOD, bool fail = false);
-coord_def find_gateway_location (actor* caster, bool (
- *environment_checker)(dungeon_feature_type) = feat_is_malign_gateway_suitable);
+coord_def find_gateway_location(actor* caster);
int animate_remains(const coord_def &a, corpse_type class_allowed,
beh_type beha, unsigned short hitting,
diff --git a/crawl-ref/source/spl-tornado.cc b/crawl-ref/source/spl-tornado.cc
index 72f39aeb9b..179fdee9e0 100644
--- a/crawl-ref/source/spl-tornado.cc
+++ b/crawl-ref/source/spl-tornado.cc
@@ -391,10 +391,7 @@ void tornado_damage(actor *caster, int dur)
// have spawned something new (like Royal Jelly spawns).
for (int i = move_avail.size() - 1; i >= 0; i--)
if (actor_at(move_avail[i]))
- {
- move_avail[i] = move_avail[move_avail.size() - 1];
- move_avail.pop_back();
- }
+ erase_any(move_avail, i);
// Calculate destinations.
for (unsigned int i = 0; i < move_act.size(); i++)
@@ -406,8 +403,7 @@ void tornado_damage(actor *caster, int dur)
if (move_avail[j] == dest)
{
// Only one monster per destination.
- move_avail[j] = move_avail[move_avail.size() - 1];
- move_avail.pop_back();
+ erase_any(move_avail, j);
break;
}
move_dest[move_act[i]->mid] = dest;
diff --git a/crawl-ref/source/spl-transloc.cc b/crawl-ref/source/spl-transloc.cc
index 16fdb19d3a..e01b077970 100644
--- a/crawl-ref/source/spl-transloc.cc
+++ b/crawl-ref/source/spl-transloc.cc
@@ -219,7 +219,9 @@ int blink(int pow, bool high_level_controlled_blink, bool wizard_blink,
else
{
// Leave a purple cloud.
- place_cloud(CLOUD_TLOC_ENERGY, you.pos(), 1 + random2(3), &you);
+ if (!wizard_blink)
+ place_cloud(CLOUD_TLOC_ENERGY, you.pos(), 1 + random2(3), &you);
+
move_player_to_grid(beam.target, false, true);
// Controlling teleport contaminates the player. -- bwr
@@ -561,7 +563,8 @@ static bool _teleport_player(bool allow_control, bool new_abyss_area,
else
{
// Leave a purple cloud.
- place_cloud(CLOUD_TLOC_ENERGY, old_pos, 1 + random2(3), &you);
+ if (!wizard_tele)
+ place_cloud(CLOUD_TLOC_ENERGY, old_pos, 1 + random2(3), &you);
move_player_to_grid(pos, false, true);
@@ -753,7 +756,7 @@ spret_type cast_apportation(int pow, bolt& beam, bool fail)
{
const coord_def where = beam.target;
- if (you.trans_wall_blocking(where))
+ if (!cell_see_cell(you.pos(), where, LOS_SOLID))
{
mpr("There's something in the way!");
return SPRET_ABORT;
@@ -805,7 +808,7 @@ spret_type cast_apportation(int pow, bolt& beam, bool fail)
else
mpr("The mass is resisting your pull.");
- return SPRET_SUCCESS;
+ return SPRET_SUCCESS;
}
// We need to modify the item *before* we move it, because
@@ -818,14 +821,17 @@ spret_type cast_apportation(int pow, bolt& beam, bool fail)
// There's also a 1-in-6 flat chance of apport failing.
if (one_chance_in(6))
{
- orb_pickup_noise(where, 30, "The orb shrieks and becomes a dead weight against your magic!",
- "The orb lets out a furious burst of light and becomes a dead weight against your magic!");
+ orb_pickup_noise(where, 30,
+ "The orb shrieks and becomes a dead weight against your magic!",
+ "The orb lets out a furious burst of light and becomes "
+ "a dead weight against your magic!");
return SPRET_SUCCESS;
}
else // Otherwise it's just a noisy little shiny thing
{
- orb_pickup_noise(where, 30, "The orb shrieks as your magic touches it!",
- "The orb lets out a furious burst of light as your magic touches it!");
+ orb_pickup_noise(where, 30,
+ "The orb shrieks as your magic touches it!",
+ "The orb lets out a furious burst of light as your magic touches it!");
}
}
diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc
index 68013d92aa..4b335deb3c 100644
--- a/crawl-ref/source/spl-util.cc
+++ b/crawl-ref/source/spl-util.cc
@@ -391,6 +391,9 @@ int spell_hunger(spell_type which_spell, bool rod)
else
hunger -= you.skill(SK_SPELLCASTING, you.intel());
+ // Staff of energy
+ hunger /= (1 + player_energy());
+
if (hunger < 0)
hunger = 0;
diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc
index b0b7511ee1..d9b97a4e65 100644
--- a/crawl-ref/source/stairs.cc
+++ b/crawl-ref/source/stairs.cc
@@ -1020,9 +1020,10 @@ static void _update_level_state()
env.orb_pos = orb_position();
if (player_has_orb())
+ {
env.orb_pos = you.pos();
- if (you.char_direction == GDT_ASCENDING)
invalidate_agrid(true);
+ }
}
void new_level(bool restore)
diff --git a/crawl-ref/source/status.cc b/crawl-ref/source/status.cc
index bae79d86d4..01be379985 100644
--- a/crawl-ref/source/status.cc
+++ b/crawl-ref/source/status.cc
@@ -79,8 +79,6 @@ static duration_def duration_data[] =
BLUE, "RMsl", "repel missiles", "You are protected from missiles." },
{ DUR_RESISTANCE, true,
LIGHTBLUE, "Resist", "", "You resist elements." },
- { DUR_SAGE, true,
- BLUE, "Sage", "", "" },
{ DUR_SEE_INVISIBLE, true,
BLUE, "SInv", "", "You can see invisible." },
{ DUR_SLAYING, false,
@@ -228,6 +226,7 @@ static void _describe_rotting(status_info* inf);
static void _describe_sickness(status_info* inf);
static void _describe_nausea(status_info* inf);
static void _describe_speed(status_info* inf);
+static void _describe_sage(status_info* inf);
static void _describe_poison(status_info* inf);
static void _describe_transform(status_info* inf);
static void _describe_stat_zero(status_info* inf, stat_type st);
@@ -361,6 +360,10 @@ void fill_status_info(int status, status_info* inf)
_describe_speed(inf);
break;
+ case STATUS_SAGE:
+ _describe_sage(inf);
+ break;
+
case STATUS_AUGMENTED:
{
int level = augmentation_amount();
@@ -445,15 +448,6 @@ void fill_status_info(int status, status_info* inf)
}
break;
- case DUR_SAGE:
- {
- std::string sk = skill_name(you.sage_bonus_skill);
- inf->short_text = "studious about " + sk;
- inf->long_text = "You are " + inf->short_text + ".";
- _mark_expiring(inf, dur_expiring(DUR_SAGE));
- break;
- }
-
case STATUS_MANUAL:
if (!is_invalid_skill(you.manual_skill))
{
@@ -731,6 +725,23 @@ static void _describe_speed(status_info* inf)
}
}
+static void _describe_sage(status_info* inf)
+{
+ if (you.sage_skills.empty())
+ return;
+
+ std::vector<const char*> sages;
+ for (unsigned long i = 0; i < you.sage_skills.size(); ++i)
+ sages.push_back(skill_name(you.sage_skills[i]));
+
+ inf->light_colour = LIGHTBLUE;
+ inf->light_text = "Sage";
+ inf->short_text = "sage [" + comma_separated_line(sages.begin(),
+ sages.end(), ", ") + "]";
+ inf->long_text = "You feel studious about " + comma_separated_line(
+ sages.begin(), sages.end()) + ".";
+}
+
static void _describe_airborne(status_info* inf)
{
if (!you.airborne())
@@ -740,7 +751,7 @@ static void _describe_airborne(status_info* inf)
const bool expiring = (!perm && dur_expiring(DUR_LEVITATION));
const bool uncancel = you.attribute[ATTR_LEV_UNCANCELLABLE];
- if (wearing_amulet(AMU_CONTROLLED_FLIGHT))
+ if (player_effect_cfly())
{
inf->light_colour = you.light_flight() ? BLUE : perm ? WHITE : MAGENTA;
inf->light_text = "Fly";
diff --git a/crawl-ref/source/status.h b/crawl-ref/source/status.h
index 0b8fe5f5f1..64f06b0f11 100644
--- a/crawl-ref/source/status.h
+++ b/crawl-ref/source/status.h
@@ -19,6 +19,7 @@ enum status_type
STATUS_SICK,
STATUS_SPEED,
STATUS_CLINGING,
+ STATUS_SAGE,
STATUS_STR_ZERO,
STATUS_INT_ZERO,
STATUS_DEX_ZERO,
diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc
index ea8e6d8fad..78f058b37e 100644
--- a/crawl-ref/source/stuff.cc
+++ b/crawl-ref/source/stuff.cc
@@ -372,7 +372,7 @@ int stepdown_value(int base_value, int stepping, int first_step,
if (return_value > this_step)
return_value = ((return_value - this_step) / 2) + this_step;
else
- break; // exit loop iff value fully "stepped down"
+ break; // exit loop if value fully "stepped down"
}
// "no final ceiling" == -1
diff --git a/crawl-ref/source/tag-version.h b/crawl-ref/source/tag-version.h
index c873a279b5..96f3fedcba 100644
--- a/crawl-ref/source/tag-version.h
+++ b/crawl-ref/source/tag-version.h
@@ -72,6 +72,7 @@ enum tag_minor_version
TAG_MINOR_REMOVE_SKILL_SET, // Remove the useless you.skill_set array.
TAG_MINOR_TOTAL_EXPERIENCE, // Keep track of the total number of XP gained.
TAG_MINOR_DES_CACHE_TIMESTAMP, // Embed the timestamp into des cache files.
+ TAG_MINOR_MULTI_SAGE, // Sage card can't be waited out or replaced.
NUM_TAG_MINORS,
TAG_MINOR_VERSION = NUM_TAG_MINORS - 1
};
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index b93a16005b..03d81ec846 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -1053,8 +1053,6 @@ static void tag_construct_you(writer &th)
marshallByte(th, you.is_undead);
marshallShort(th, you.unrand_reacts);
marshallByte(th, you.berserk_penalty);
- marshallShort(th, you.sage_bonus_skill);
- marshallInt(th, you.sage_bonus_degree);
marshallShort(th, you.manual_skill);
marshallInt(th, you.manual_index);
marshallInt(th, you.abyss_speed);
@@ -1067,6 +1065,15 @@ static void tag_construct_you(writer &th)
marshallInt(th, you.earth_attunement);
marshallInt(th, you.form);
+ j = std::min<int>(you.sage_skills.size(), 32767);
+ marshallShort(th, you.sage_skills.size());
+ for (i = 0; i < (int)you.sage_skills.size(); ++i)
+ {
+ marshallByte(th, you.sage_skills[i]);
+ marshallInt(th, you.sage_xp[i]);
+ marshallInt(th, you.sage_bonus[i]);
+ }
+
// how many you.equip?
marshallByte(th, NUM_EQUIP);
for (i = 0; i < NUM_EQUIP; ++i)
@@ -1780,10 +1787,12 @@ static void tag_read_you(reader &th)
ASSERT(you.is_undead <= US_SEMI_UNDEAD);
you.unrand_reacts = unmarshallShort(th);
you.berserk_penalty = unmarshallByte(th);
- you.sage_bonus_skill = static_cast<skill_type>(unmarshallShort(th));
- ASSERT(you.sage_bonus_skill <= NUM_SKILLS);
- you.sage_bonus_degree = unmarshallInt(th);
#if TAG_MAJOR_VERSION == 32
+ if (th.getMinorVersion() < TAG_MINOR_MULTI_SAGE)
+ {
+ unmarshallShort(th);
+ unmarshallInt(th);
+ }
if (th.getMinorVersion() >= TAG_MINOR_MANUAL)
{
#endif
@@ -1806,6 +1815,27 @@ static void tag_read_you(reader &th)
you.form = static_cast<transformation_type>(unmarshallInt(th));
ASSERT(you.form >= TRAN_NONE && you.form <= LAST_FORM);
+#if TAG_MAJOR_VERSION == 32
+ if (th.getMinorVersion() >= TAG_MINOR_MULTI_SAGE)
+ {
+#endif
+ count = unmarshallShort(th);
+ ASSERT(count >= 0 && count <= 32767);
+ you.sage_skills.resize(count, SK_NONE);
+ you.sage_xp.resize(count, 0);
+ you.sage_bonus.resize(count, 0);
+ for (i = 0; i < count; ++i)
+ {
+ you.sage_skills[i] = static_cast<skill_type>(unmarshallByte(th));
+ ASSERT(!is_invalid_skill(you.sage_skills[i]));
+ ASSERT(!is_useless_skill(you.sage_skills[i]));
+ you.sage_xp[i] = unmarshallInt(th);
+ you.sage_bonus[i] = unmarshallInt(th);
+ }
+#if TAG_MAJOR_VERSION == 32
+ }
+#endif
+
// How many you.equip?
count = unmarshallByte(th);
ASSERT(count <= NUM_EQUIP);
diff --git a/crawl-ref/source/target.cc b/crawl-ref/source/target.cc
index efc4cece71..7e8b3c4127 100644
--- a/crawl-ref/source/target.cc
+++ b/crawl-ref/source/target.cc
@@ -159,7 +159,7 @@ aff_type targetter_reach::is_affected(coord_def loc)
return AFF_YES;
if (((loc - origin) * 2 - (aim - origin)).abs() <= 1
- && grd(loc) > DNGN_MAX_NONREACH)
+ && feat_is_reachable_past(grd(loc)))
{
return AFF_TRACER;
}
diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc
index 45fc1f12e0..933fe7b590 100644
--- a/crawl-ref/source/terrain.cc
+++ b/crawl-ref/source/terrain.cc
@@ -64,16 +64,6 @@ int count_neighbours_with_func(const coord_def& c, bool (*checker)(dungeon_featu
return count;
}
-bool feat_is_test(dungeon_feature_type feat, bool (*checker)(dungeon_feature_type))
-{
- return (checker(feat));
-}
-
-bool feat_is_test(const coord_def& c, bool (*checker)(dungeon_feature_type))
-{
- return (checker(grd(c)));
-}
-
bool feat_is_malign_gateway_suitable(dungeon_feature_type feat)
{
return (feat == DNGN_FLOOR || feat == DNGN_SHALLOW_WATER);
@@ -320,11 +310,6 @@ bool cell_is_solid(const coord_def &c)
return (feat_is_solid(grd(c)));
}
-bool feat_is_floor(dungeon_feature_type feat)
-{
- return (feat >= DNGN_FLOOR_MIN && feat <= DNGN_FLOOR_MAX);
-}
-
bool feat_has_solid_floor(dungeon_feature_type feat)
{
return (!feat_is_solid(feat) && feat != DNGN_DEEP_WATER &&
@@ -378,8 +363,7 @@ bool feat_is_water(dungeon_feature_type feat)
return (feat == DNGN_SHALLOW_WATER
|| feat == DNGN_DEEP_WATER
|| feat == DNGN_OPEN_SEA
- || feat == DNGN_SWAMP_TREE
- || feat == DNGN_WATER_RESERVED);
+ || feat == DNGN_SWAMP_TREE);
}
bool feat_is_watery(dungeon_feature_type feat)
@@ -459,6 +443,15 @@ bool feat_is_fountain(dungeon_feature_type feat)
return feat >= DNGN_FOUNTAIN_BLUE && feat <= DNGN_PERMADRY_FOUNTAIN;
}
+bool feat_is_reachable_past(dungeon_feature_type feat)
+{
+#if TAG_MAJOR_VERSION == 32
+ return feat > DNGN_MAX_NONREACH && !feat_is_tree(feat);
+#else
+ return feat > DNGN_MAX_NONREACH;
+#endif
+}
+
// Find all connected cells containing ft, starting at d.
void find_connected_identical(const coord_def &d, dungeon_feature_type ft,
std::set<coord_def>& out)
@@ -1644,13 +1637,17 @@ static const char *dngn_feature_names[] =
"wax_wall", "metal_wall", "green_crystal_wall", "rock_wall",
"slimy_wall", "stone_wall", "permarock_wall",
"clear_rock_wall", "clear_stone_wall", "clear_permarock_wall", "iron_grate",
+#if TAG_MAJOR_VERSION == 32
"open_sea", "tree", "orcish_idol", "swamp_tree", "endless_lava", "",
+#else
+"tree", "swamp_tree", "open_sea", "endless_lava", "orcish_idol", "",
+#endif
"granite_statue", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "lava",
-"deep_water", "", "", "shallow_water", "water_stuck", "floor",
-"", "floor_reserved", "exit_hell", "enter_hell",
-"open_door", "", "", "trap_mechanical", "trap_magical", "trap_natural",
+"deep_water", "", "", "shallow_water", "", "floor",
+"", "", "exit_hell", "enter_hell", "open_door", "teleporter", "",
+"trap_mechanical", "trap_magical", "trap_natural",
"undiscovered_trap", "", "enter_shop", "enter_labyrinth",
"stone_stairs_down_i", "stone_stairs_down_ii",
"stone_stairs_down_iii", "escape_hatch_down", "stone_stairs_up_i",
diff --git a/crawl-ref/source/terrain.h b/crawl-ref/source/terrain.h
index 2434d77e3a..d31967e7cc 100644
--- a/crawl-ref/source/terrain.h
+++ b/crawl-ref/source/terrain.h
@@ -28,8 +28,6 @@ private:
actor* actor_at(const coord_def& c);
int count_neighbours_with_func(const coord_def& c, bool (*checker)(dungeon_feature_type));
-bool feat_is_test(dungeon_feature_type feat, bool (*checker)(dungeon_feature_type));
-bool feat_is_test(const coord_def& c, bool (*checker)(dungeon_feature_type));
bool fall_into_a_pool(const coord_def& entry, bool allow_shift,
dungeon_feature_type terrain);
@@ -41,7 +39,6 @@ bool feat_is_malign_gateway_suitable(dungeon_feature_type feat);
bool feat_is_wall(dungeon_feature_type feat);
bool feat_is_opaque(dungeon_feature_type feat);
bool feat_is_solid(dungeon_feature_type feat);
-bool feat_is_floor(dungeon_feature_type feat);
bool feat_has_solid_floor(dungeon_feature_type feat);
bool feat_is_door(dungeon_feature_type feat);
bool feat_is_closed_door(dungeon_feature_type feat);
@@ -79,6 +76,7 @@ bool feat_is_branch_stairs(dungeon_feature_type feat);
bool feat_is_branchlike(dungeon_feature_type feat);
bool feat_is_bidirectional_portal(dungeon_feature_type feat);
bool feat_is_fountain(dungeon_feature_type feat);
+bool feat_is_reachable_past(dungeon_feature_type feat);
void find_connected_identical(const coord_def& d, dungeon_feature_type ft,
std::set<coord_def>& out);
std::set<coord_def> connected_doors(const coord_def& d);
diff --git a/crawl-ref/source/test/rune-gen.lua b/crawl-ref/source/test/rune-gen.lua
index af4d89e9ee..d367265411 100644
--- a/crawl-ref/source/test/rune-gen.lua
+++ b/crawl-ref/source/test/rune-gen.lua
@@ -21,6 +21,7 @@ test_item_places(niters,
{ { "Snake:$", "serpentine rune" },
{ "Shoals:$", "barnacled rune" },
{ "Swamp:$", "decaying rune" },
+ { "Spider:$", "gossamer rune" },
{ "Slime:$", "slimy rune" },
{ "Vaults:$", "silver rune" },
{ "Coc:$", "icy rune" },
diff --git a/crawl-ref/source/test/stress/abyss.rc b/crawl-ref/source/test/stress/abyss.rc
index 2e506aa3fe..b3a8195fd9 100644
--- a/crawl-ref/source/test/stress/abyss.rc
+++ b/crawl-ref/source/test/stress/abyss.rc
@@ -1,6 +1,6 @@
# A bot to exercise player-vs-monsters combat and Abyss generation.
#
-# Usage: rm -f saves/Avyss_walker.cs && ./crawl --rc test/stress/abyss.rc
+# Usage: rm -f saves/Abyss_walker.cs && ./crawl --rc test/stress/abyss.rc
#
# Wizmode is needed.
diff --git a/crawl-ref/source/tilecell.h b/crawl-ref/source/tilecell.h
index cf676dcf0d..6dd5bb9383 100644
--- a/crawl-ref/source/tilecell.h
+++ b/crawl-ref/source/tilecell.h
@@ -33,6 +33,7 @@ struct packed_cell
bool swamp_tree_water;
uint8_t orb_glow;
char blood_rotation;
+ bool old_blood;
bool operator ==(const packed_cell &other) const;
bool operator !=(const packed_cell &other) const { return !(*this == other); }
@@ -41,7 +42,7 @@ struct packed_cell
is_silenced(false), is_suppressed(false), halo(HALO_NONE),
is_moldy(false), glowing_mold(false), is_sanctuary(false),
is_liquefied(false), swamp_tree_water(false), orb_glow(0),
- blood_rotation(0) {}
+ blood_rotation(0), old_blood(false) {}
packed_cell(const packed_cell* c) : num_dngn_overlay(c->num_dngn_overlay),
fg(c->fg), bg(c->bg), flv(c->flv),
@@ -55,7 +56,8 @@ struct packed_cell
is_liquefied(c->is_liquefied),
swamp_tree_water(c->swamp_tree_water),
orb_glow(c->orb_glow),
- blood_rotation(c->blood_rotation) {}
+ blood_rotation(c->blood_rotation),
+ old_blood(c->old_blood) {}
void clear();
};
diff --git a/crawl-ref/source/tiledgnbuf.cc b/crawl-ref/source/tiledgnbuf.cc
index 4b34a71810..5ac12e0152 100644
--- a/crawl-ref/source/tiledgnbuf.cc
+++ b/crawl-ref/source/tiledgnbuf.cc
@@ -190,8 +190,8 @@ void DungeonCellBuffer::add_blood_overlay(int x, int y, const packed_cell &cell,
tileidx_t basetile;
if (is_wall)
{
- basetile = TILE_WALL_BLOOD_S + tile_dngn_count(TILE_WALL_BLOOD_S)
- * cell.blood_rotation;
+ basetile = cell.old_blood ? TILE_WALL_OLD_BLOOD : TILE_WALL_BLOOD_S;
+ basetile += tile_dngn_count(basetile) * cell.blood_rotation;
}
else
basetile = TILE_BLOOD;
diff --git a/crawl-ref/source/tiledoll.cc b/crawl-ref/source/tiledoll.cc
index f6f630bbdf..fc454d0a27 100644
--- a/crawl-ref/source/tiledoll.cc
+++ b/crawl-ref/source/tiledoll.cc
@@ -82,7 +82,8 @@ bool save_doll_data(int mode, int num, const dolls_data* dolls)
// Print some explanatory comments. May contain no spaces!
fprintf(fp, "#Legend:\n");
fprintf(fp, "#***:equipment/123:index/000:none\n");
- fprintf(fp, "#Shadow/Base/Cloak/Boots/Legs/Body/Gloves/Weapon/Shield/Hair/Beard/Helmet/Halo/Enchant/DrcHead/DrcWing\n");
+ fprintf(fp, "#Shadow/Base/Cloak/Boots/Legs/Body/Gloves/Weapon/Shield/"
+ "Hair/Beard/Helmet/Halo/Enchant/DrcHead/DrcWing\n");
fprintf(fp, "#Sh:Bse:Clk:Bts:Leg:Bdy:Glv:Wpn:Shd:Hai:Brd:Hlm:Hal:Enc:Drc:Wng\n");
char fbuf[80];
for (unsigned int i = 0; i < NUM_MAX_DOLLS; ++i)
@@ -437,7 +438,8 @@ void save_doll_file(writer &dollf)
}
#ifdef USE_TILE_LOCAL
-void pack_doll_buf(SubmergedTileBuffer& buf, const dolls_data &doll, int x, int y, bool submerged, bool ghost)
+void pack_doll_buf(SubmergedTileBuffer& buf, const dolls_data &doll,
+ int x, int y, bool submerged, bool ghost)
{
// Ordered from back to front.
int p_order[TILEP_PART_MAX] =
diff --git a/crawl-ref/source/tilepick-p.cc b/crawl-ref/source/tilepick-p.cc
index 34ca73dff0..189a6ac1da 100644
--- a/crawl-ref/source/tilepick-p.cc
+++ b/crawl-ref/source/tilepick-p.cc
@@ -88,7 +88,9 @@ tileidx_t tilep_equ_weapon(const item_def &item)
case WPN_EVENINGSTAR: return TILEP_HAND1_EVENINGSTAR;
case WPN_GIANT_CLUB: return TILEP_HAND1_GIANT_CLUB_PLAIN;
case WPN_GIANT_SPIKED_CLUB: return TILEP_HAND1_GIANT_CLUB_SPIKE_SLANT;
+#if TAG_MAJOR_VERSION == 32
case WPN_ANKUS: return TILEP_HAND1_ANKUS;
+#endif
case WPN_WHIP: return TILEP_HAND1_WHIP;
case WPN_DEMON_WHIP: return TILEP_HAND1_BLACK_WHIP;
case WPN_SACRED_SCOURGE: return TILEP_HAND1_SACRED_SCOURGE;
diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc
index ad2374da53..a2aba1aa2d 100644
--- a/crawl-ref/source/tilepick.cc
+++ b/crawl-ref/source/tilepick.cc
@@ -274,21 +274,25 @@ static tileidx_t _tileidx_feature_base(dungeon_feature_type feat)
case DNGN_ENTER_DWARVEN_HALL:
case DNGN_ENTER_ORCISH_MINES:
case DNGN_ENTER_LAIR:
- case DNGN_ENTER_SLIME_PITS:
case DNGN_ENTER_VAULTS:
case DNGN_ENTER_CRYPT:
case DNGN_ENTER_HALL_OF_BLADES:
case DNGN_ENTER_TEMPLE:
- case DNGN_ENTER_SNAKE_PIT:
case DNGN_ENTER_ELVEN_HALLS:
case DNGN_ENTER_TOMB:
- case DNGN_ENTER_SWAMP:
- case DNGN_ENTER_SHOALS:
case DNGN_ENTER_FOREST:
return TILE_DNGN_ENTER;
+ case DNGN_ENTER_SNAKE_PIT:
+ return TILE_DNGN_ENTER_SNAKE_PIT;
+ case DNGN_ENTER_SWAMP:
+ return TILE_DNGN_ENTER_SWAMP;
case DNGN_ENTER_SPIDER_NEST:
return TILE_DNGN_ENTER_SPIDER_NEST;
+ case DNGN_ENTER_SHOALS:
+ return TILE_DNGN_ENTER_SHOALS;
+ case DNGN_ENTER_SLIME_PITS:
+ return TILE_DNGN_ENTER_SLIME_PITS;
case DNGN_ENTER_ZOT:
if (you.opened_zot)
@@ -2447,6 +2451,11 @@ static tileidx_t _tileidx_monster_no_props(const monster_info& mon)
return TILEP_MONS_AGATE_SNAIL
+ (mon.is(MB_WITHDRAWN) ? 1 : 0);
+ case MONS_BOULDER_BEETLE:
+ return (mon.is(MB_ROLLING)
+ ? _mon_random(TILEP_MONS_BOULDER_BEETLE_ROLLING)
+ : TILEP_MONS_BOULDER_BEETLE);
+
case MONS_ITEM_MIMIC:
{
tileidx_t t = tileidx_item(*mon.get_mimic_item());
@@ -2801,8 +2810,10 @@ static tileidx_t _tileidx_weapon_base(const item_def &item)
case WPN_GIANT_SPIKED_CLUB:
return TILE_WPN_GIANT_SPIKED_CLUB;
+#if TAG_MAJOR_VERSION == 32
case WPN_ANKUS:
return TILE_WPN_ANKUS;
+#endif
case WPN_WHIP:
return TILE_WPN_WHIP;
@@ -3903,7 +3914,7 @@ tileidx_t tileidx_item(const item_def &item)
{
if (item.flags & ISFLAG_KNOW_TYPE)
{
- return TILE_ROD_ID_FIRST + type - STAFF_SMITING;
+ return TILE_ROD_ID_FIRST + type - STAFF_FIRST_ROD;
}
int desc = (special / NDSC_STAVE_PRI) % NDSC_STAVE_SEC;
@@ -4042,21 +4053,33 @@ tileidx_t tileidx_known_base_item(tileidx_t label)
{
int type = label - TILE_POT_ID_FIRST;
int desc = you.item_description[IDESC_POTIONS][type] % NDSC_POT_PRI;
- return (TILE_POTION_OFFSET + desc);
+
+ if (get_ident_type(OBJ_POTIONS, type) != ID_KNOWN_TYPE)
+ return TILE_UNSEEN_POTION;
+ else
+ return (TILE_POTION_OFFSET + desc);
}
if (label >= TILE_RING_ID_FIRST && label <= TILE_RING_ID_LAST)
{
int type = label - TILE_RING_ID_FIRST + RING_FIRST_RING;
int desc = you.item_description[IDESC_RINGS][type] % NDSC_JEWEL_PRI;
- return (TILE_RING_NORMAL_OFFSET + desc);
+
+ if (get_ident_type(OBJ_JEWELLERY, type) != ID_KNOWN_TYPE)
+ return TILE_UNSEEN_RING;
+ else
+ return (TILE_RING_NORMAL_OFFSET + desc);
}
if (label >= TILE_AMU_ID_FIRST && label <= TILE_AMU_ID_LAST)
{
int type = label - TILE_AMU_ID_FIRST + AMU_FIRST_AMULET;
int desc = you.item_description[IDESC_RINGS][type] % NDSC_JEWEL_PRI;
- return (TILE_AMU_NORMAL_OFFSET + desc);
+
+ if (get_ident_type(OBJ_JEWELLERY, type) != ID_KNOWN_TYPE)
+ return TILE_UNSEEN_AMULET;
+ else
+ return (TILE_AMU_NORMAL_OFFSET + desc);
}
if (label >= TILE_SCR_ID_FIRST && label <= TILE_SCR_ID_LAST)
@@ -4066,7 +4089,11 @@ tileidx_t tileidx_known_base_item(tileidx_t label)
{
int type = label - TILE_WAND_ID_FIRST;
int desc = you.item_description[IDESC_WANDS][type] % NDSC_WAND_PRI;
- return (TILE_WAND_OFFSET + desc);
+
+ if (get_ident_type(OBJ_WANDS, type) != ID_KNOWN_TYPE)
+ return TILE_UNSEEN_WAND;
+ else
+ return (TILE_WAND_OFFSET + desc);
}
if (label >= TILE_STAFF_ID_FIRST && label <= TILE_STAFF_ID_LAST)
@@ -4074,7 +4101,11 @@ tileidx_t tileidx_known_base_item(tileidx_t label)
int type = label - TILE_STAFF_ID_FIRST;
int desc = you.item_description[IDESC_STAVES][type];
desc = (desc / NDSC_STAVE_PRI) % NDSC_STAVE_SEC;
- return (TILE_STAFF_OFFSET + desc);
+
+ if (get_ident_type(OBJ_STAVES, type) != ID_KNOWN_TYPE)
+ return TILE_UNSEEN_STAFF;
+ else
+ return (TILE_STAFF_OFFSET + desc);
}
if (label >= TILE_ROD_ID_FIRST && label <= TILE_ROD_ID_LAST)
@@ -4082,7 +4113,11 @@ tileidx_t tileidx_known_base_item(tileidx_t label)
int type = label - TILE_ROD_ID_FIRST + STAFF_FIRST_ROD;
int desc = you.item_description[IDESC_STAVES][type];
desc = (desc / NDSC_STAVE_PRI) % NDSC_STAVE_SEC;
- return (TILE_ROD_OFFSET + desc);
+
+ if (get_ident_type(OBJ_STAVES, type) != ID_KNOWN_TYPE)
+ return TILE_UNSEEN_STAFF;
+ else
+ return (TILE_ROD_OFFSET + desc);
}
return (0);
@@ -4152,6 +4187,10 @@ tileidx_t tileidx_cloud(const cloud_info &cl, bool disturbance)
ch = TILE_CLOUD_MAGIC_TRAIL_0 + dur;
break;
+ case CLOUD_DUST_TRAIL:
+ ch = TILE_CLOUD_DUST_TRAIL_0 + dur;
+ break;
+
case CLOUD_INK:
ch = TILE_CLOUD_INK;
break;
diff --git a/crawl-ref/source/tilereg-doll.cc b/crawl-ref/source/tilereg-doll.cc
index 0cc712c94e..6fa66ad718 100644
--- a/crawl-ref/source/tilereg-doll.cc
+++ b/crawl-ref/source/tilereg-doll.cc
@@ -291,12 +291,24 @@ void DollEditRegion::render()
const int width = m_font->char_width();
const float start_y = doll_name_y + height * 3;
const float start_x = width * 6;
- m_font_buf.add("Change parts left/right Confirm choice Enter", VColour::white, start_x, start_y);
- m_font_buf.add("Change category up/down Copy doll Ctrl-C", VColour::white, start_x, start_y + height * 1);
- m_font_buf.add("Change doll 0-9, Shift + arrows Paste copied doll Ctrl-V", VColour::white, start_x, start_y + height * 2);
- m_font_buf.add("Change doll mode m Randomise doll Ctrl-R", VColour::white, start_x, start_y + height * 3);
- m_font_buf.add("Save menu Escape, Ctrl-S Toggle equipment *", VColour::white, start_x, start_y + height * 4);
- m_font_buf.add("Quit menu q, Ctrl-Q", VColour::white, start_x, start_y + height * 5);
+ m_font_buf.add(
+ "Change parts left/right Confirm choice Enter",
+ VColour::white, start_x, start_y);
+ m_font_buf.add(
+ "Change category up/down Copy doll Ctrl-C",
+ VColour::white, start_x, start_y + height * 1);
+ m_font_buf.add(
+ "Change doll 0-9, Shift + arrows Paste copied doll Ctrl-V",
+ VColour::white, start_x, start_y + height * 2);
+ m_font_buf.add(
+ "Change doll mode m Randomise doll Ctrl-R",
+ VColour::white, start_x, start_y + height * 3);
+ m_font_buf.add(
+ "Save menu Escape, Ctrl-S Toggle equipment *",
+ VColour::white, start_x, start_y + height * 4);
+ m_font_buf.add(
+ "Quit menu q, Ctrl-Q",
+ VColour::white, start_x, start_y + height * 5);
}
m_font_buf.draw();
diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc
index 33efd297b2..c04559842b 100644
--- a/crawl-ref/source/tileview.cc
+++ b/crawl-ref/source/tileview.cc
@@ -425,15 +425,15 @@ void tile_floor_halo(dungeon_feature_type target, tileidx_t tile)
{
for (int y = 0; y < GYM; y++)
{
- if (grd[x][y] < DNGN_FLOOR_MIN)
+ if (grd[x][y] < DNGN_FLOOR)
continue;
if (!_adjacent_target(target, x, y))
continue;
- bool l_flr = (x > 0 && grd[x-1][y] >= DNGN_FLOOR_MIN);
- bool r_flr = (x < GXM - 1 && grd[x+1][y] >= DNGN_FLOOR_MIN);
- bool u_flr = (y > 0 && grd[x][y-1] >= DNGN_FLOOR_MIN);
- bool d_flr = (y < GYM - 1 && grd[x][y+1] >= DNGN_FLOOR_MIN);
+ bool l_flr = (x > 0 && grd[x-1][y] >= DNGN_FLOOR);
+ bool r_flr = (x < GXM - 1 && grd[x+1][y] >= DNGN_FLOOR);
+ bool u_flr = (y > 0 && grd[x][y-1] >= DNGN_FLOOR);
+ bool d_flr = (y < GYM - 1 && grd[x][y+1] >= DNGN_FLOOR);
bool l_target = _adjacent_target(target, x-1, y);
bool r_target = _adjacent_target(target, x+1, y);
@@ -743,6 +743,11 @@ static void _tile_place_invisible_monster(const coord_def &gc)
{
const coord_def ep = grid2show(gc);
+ // Shallow water has its own modified tile for disturbances
+ // see tileidx_feature
+ if (env.map_knowledge(gc).feat() == DNGN_SHALLOW_WATER)
+ return;
+
tileidx_t t = TILE_UNSEEN_MONSTER;
if (!you.see_cell(gc))
{
@@ -1192,6 +1197,7 @@ void tile_apply_properties(const coord_def &gc, packed_cell &cell)
{
cell.is_bloody = true;
cell.blood_rotation = blood_rotation(gc);
+ cell.old_blood = env.pgrid(gc) & FPROP_OLD_BLOOD;
}
}
diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc
index 90b2d52023..d61e4f41a1 100644
--- a/crawl-ref/source/tileweb.cc
+++ b/crawl-ref/source/tileweb.cc
@@ -1112,9 +1112,11 @@ void TilesFramework::cgotoxy(int x, int y, GotoRegion region)
}
break;
case GOTO_MSG:
+ set_ui_state(UI_NORMAL);
m_print_area = &m_text_message;
break;
case GOTO_STAT:
+ set_ui_state(UI_NORMAL);
m_print_area = &m_text_stat;
break;
default:
diff --git a/crawl-ref/source/transform.cc b/crawl-ref/source/transform.cc
index 4a64e2f708..b28fe0e717 100644
--- a/crawl-ref/source/transform.cc
+++ b/crawl-ref/source/transform.cc
@@ -65,8 +65,7 @@ bool form_can_wield(transformation_type form)
bool form_can_fly(transformation_type form)
{
- if ((form == TRAN_NONE || form == TRAN_LICH || form == TRAN_APPENDAGE)
- && you.species == SP_TENGU
+ if (you.species == SP_TENGU
&& (you.experience_level >= 15 || you.airborne()))
{
return (true);
@@ -139,6 +138,7 @@ bool form_can_wear_item(const item_def& item, transformation_type form)
case TRAN_BAT:
case TRAN_PIG:
case TRAN_SPIDER:
+ case TRAN_ICE_BEAST:
return false;
// And some need more complicated logic.
@@ -149,9 +149,6 @@ bool form_can_wear_item(const item_def& item, transformation_type form)
return (eqslot == EQ_CLOAK || eqslot == EQ_HELMET
|| eqslot == EQ_SHIELD);
- case TRAN_ICE_BEAST:
- return (eqslot == EQ_CLOAK);
-
default: // Bug-catcher.
die("Unknown transformation type %d in form_can_wear_item", you.form);
}
@@ -188,7 +185,19 @@ _init_equipment_removal(transformation_type form)
{
const equipment_type eq = static_cast<equipment_type>(i);
const item_def *pitem = you.slot_item(eq, true);
- if (pitem && !form_can_wear_item(*pitem, form))
+
+ if (!pitem)
+ continue;
+
+ // Octopodes lose their extra ring slots (3--8) in forms that do not
+ // have eight limbs. Handled specially here because we do have to
+ // distinguish between slots the same type.
+ if (i >= EQ_RING_THREE && i <= EQ_RING_EIGHT
+ && !(form_keeps_mutations(form) || form == TRAN_SPIDER))
+ {
+ result.insert(eq);
+ }
+ else if (!form_can_wear_item(*pitem, form))
result.insert(eq);
}
return (result);
@@ -497,7 +506,7 @@ static bool _slot_conflict(equipment_type eq)
if (you.equip[eq] != -1)
{
// Horns + hat is fine.
- if (eq != EQ_HELMET || is_hard_helmet(*(you.slot_item(eq))))
+ if (eq != EQ_HELMET || you.melded[eq] || is_hard_helmet(*(you.slot_item(eq))))
return true;
}
@@ -790,6 +799,10 @@ bool transform(int pow, transformation_type which_trans, bool force,
if (just_check)
return (true);
+ // Switching between forms takes a bit longer.
+ if (!force && previous_trans != TRAN_NONE && previous_trans != which_trans)
+ you.time_taken = div_rand_round(you.time_taken * 3, 2);
+
// All checks done, transformation will take place now.
you.redraw_quiver = true;
you.redraw_evasion = true;
@@ -1057,6 +1070,11 @@ void untransform(bool skip_wielding, bool skip_move)
move_player_to_grid(you.pos(), false, true);
}
+#ifdef USE_TILE
+ if (you.species == SP_MERFOLK)
+ init_player_doll();
+#endif
+
if (form_can_butcher_barehanded(old_form))
stop_butcher_delay();
diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc
index fb1090ca3f..fc479c1618 100644
--- a/crawl-ref/source/traps.cc
+++ b/crawl-ref/source/traps.cc
@@ -248,8 +248,8 @@ bool trap_def::is_safe(actor* act) const
// No prompt (teleport traps are ineffective if
// wearing an amulet of stasis)
if (type == TRAP_TELEPORT
- && (player_equip(EQ_AMULET, AMU_STASIS, false)
- || scan_artefacts(ARTP_PREVENT_TELEPORTATION, false)))
+ && (player_effect_stasis(false)
+ || player_effect_notele(false)))
{
return true;
}
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index 7c9cb34e5c..48001027e9 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -279,8 +279,10 @@ bool feat_is_traversable(dungeon_feature_type feat)
if (feat >= DNGN_TRAP_MECHANICAL && feat <= DNGN_TRAP_WEB)
#endif
return false;
- else if (feat >= DNGN_FLOOR_MIN || feat == DNGN_DETECTED_SECRET_DOOR
- || feat == DNGN_CLOSED_DOOR || feat == DNGN_SHALLOW_WATER)
+ else if (feat == DNGN_TELEPORTER) // never ever enter it automatically
+ return false;
+ else if (feat >= DNGN_MOVEMENT_MIN || feat == DNGN_DETECTED_SECRET_DOOR
+ || feat == DNGN_CLOSED_DOOR)
{
return true;
}
@@ -2350,14 +2352,20 @@ bool travel_kill_monster(monster_type mons)
return (false);
// Don't auto-kill things with berserkitis or *rage.
- if ((player_mutation_level(MUT_BERSERK) || scan_artefacts(ARTP_ANGRY)
- || player_equip_unrand(UNRAND_TROG))
- && !wearing_amulet(AMU_STASIS, false)
- && !player_mental_clarity(false)
- && you.is_undead != US_UNDEAD
- && you.is_undead != US_HUNGRY_DEAD)
+ if (player_mutation_level(MUT_BERSERK)
+ || player_effect_angry())
{
- return (false);
+ if (player_effect_stasis(false)
+ || player_mental_clarity(false)
+ || you.is_undead == US_UNDEAD
+ || you.is_undead == US_HUNGRY_DEAD)
+ {
+ return (true);
+ }
+ else
+ {
+ return (false);
+ }
}
return (true);
@@ -3909,9 +3917,6 @@ const runrest &runrest::operator = (int newrunmode)
static dungeon_feature_type _base_feat_type(dungeon_feature_type grid)
{
- if (grid >= DNGN_FLOOR_MIN && grid <= DNGN_FLOOR_MAX)
- return (DNGN_FLOOR);
-
// Merge walls.
if (feat_is_wall(grid))
return (DNGN_ROCK_WALL);
diff --git a/crawl-ref/source/viewchar.cc b/crawl-ref/source/viewchar.cc
index 1806c61448..aef3d143d5 100644
--- a/crawl-ref/source/viewchar.cc
+++ b/crawl-ref/source/viewchar.cc
@@ -8,20 +8,24 @@
#include "unicode.h"
// For order and meaning of symbols, see dungeon_char_type in enum.h.
-static const unsigned dchar_table[ NUM_CSET ][ NUM_DCHAR_TYPES ] =
+static const ucs_t dchar_table[ NUM_CSET ][ NUM_DCHAR_TYPES ] =
{
// CSET_DEFAULT
// It must be limited to stuff present both in CP437 and WGL4.
{
'#', '*', '.', ',', '\'', '+', '^', '>', '<',
+ // ∩ ⌠ ≈
'#', '_', 0x2229, 0x2320, 0x2248, '8', '{',
#if defined(TARGET_OS_WINDOWS) && !defined(USE_TILE_LOCAL)
+ // ⌂
0x2302, // CP437 but "optional" in WGL4
#else
+ // ∆
0x2206, // WGL4 and DEC
#endif
'0', ')', '[', '/', '%', '?', '=', '!', '(',
- ':', '|', '}', '%', '$', '"', 0xA7, 0x2663,
+ // § ♣ ©
+ ':', '|', '}', '%', '$', '"', 0xA7, 0x2663, 0xA9,
' ', '!', '#', '%', '+', ')', '*', '+', // space .. fired_burst
'/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
},
@@ -30,28 +34,33 @@ static const unsigned dchar_table[ NUM_CSET ][ NUM_DCHAR_TYPES ] =
'#', '*', '.', ',', '\'', '+', '^', '>', '<', // wall .. stairs up
'#', '_', '\\', '}', '~', '8', '{', '{', // grate .. item detect
'{', ')', '[', '/', '%', '?', '=', '!', '(', // orb .. missile
- ':', '|', '}', '%', '$', '"', '0', '7', // book .. tree
+ ':', '|', '}', '%', '$', '"', '0', '7', '^', // book .. teleporter
' ', '!', '#', '%', ':', ')', '*', '+', // space .. fired_burst
'/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
},
// CSET_IBM - this is ANSI 437
{
+ // ▒ ░ ∙ · ' ■
0x2592, 0x2591, 0x2219, 0xb7, '\'', 0x25a0, '^', '>', '<', // wall .. stairs up
+ // ▄ ∩ ⌠ ≈
'#', 0x2584, 0x2229, 0x2320, 0x2248, '8', '{', '{', // grate .. item detect
- '0', ')', '[', '/', '%', '?', '=', '!', '(', // orb .. missile
- 0x221e, '\\', '}', '%', '$', '"', '#', 0x3a9, // book .. tree
- ' ', '!', '#', '%', '+', ')', '*', '+', // space .. fired_burst
- '/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
+ '0', ')', '[', '/', '%', '?', '=', '!', '(', // orb .. missile
+ // ∞ \ ♣ Ω
+ 0x221e, '\\', '}', '%', '$', '"', '#', 0x2663, 0x3a9, // book .. teleporter
+ ' ', '!', '#', '%', '+', ')', '*', '+', // space .. fired_burst
+ '/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
},
// CSET_DEC
// It's better known as "vt100 line drawing characters".
{
+ // ▒ ♦ · ' ┼
0x2592, 0x2666, 0xb7, ':', '\'', 0x253c, '^', '>', '<', // wall .. stairs up
+ // π ¶ § » → ¨
'#', 0x3c0, 0xb6, 0xa7, 0xbb, '8', 0x2192, 0xa8, // grate .. item detect
'0', ')', '[', '/', '%', '?', '=', '!', '(', // orb .. missile
- ':', '\\', '}', '%', '$', '"', '#', '7', // book .. tree
+ ':', '\\', '}', '%', '$', '"', '#', '7', '^', // book .. teleporter
' ', '!', '#', '%', '+', ')', '*', '+', // space .. fired_burst
'/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
},
@@ -60,15 +69,18 @@ static const unsigned dchar_table[ NUM_CSET ][ NUM_DCHAR_TYPES ] =
/* Beware, some popular terminals (PuTTY, xterm) are incapable of coping with
the lack of a character in the chosen font, and most popular fonts have a
quite limited repertoire. A subset that is reasonably likely to be present
- is http://en.wikipedia.org/wiki/WGL4; we could provide a richer alternate
+ is https://en.wikipedia.org/wiki/WGL4; we could provide a richer alternate
set for those on more capable terminals (including for example Thai 0xEB0
for clouds), but that would require decoupling encoding from charset.
*/
{
+ // ▒ ░ · ◦ ' ◼
0x2592, 0x2591, 0xB7, 0x25E6, '\'', 0x25FC, '^', '>', '<',
+ // ∩ ⌠ ≈ ∆
'#', '_', 0x2229, 0x2320, 0x2248, '8', '{', 0x2206,
'0', ')', '[', '/', '%', '?', '=', '!', '(',
- 0x221E, '|', '}', '%', '$', '"', 0xA7, 0x2663,
+ // ∞ § ♣ ©
+ 0x221E, '|', '}', '%', '$', '"', 0xA7, 0x2663, 0xA9,
' ', '!', '#', '%', '+', ')', '*', '+', // space .. fired_burst
'/', '=', '?', 'X', '[', '`', '#' // fi_stick .. explosion
},
@@ -85,12 +97,13 @@ dungeon_char_type dchar_by_name(const std::string &name)
"item_orb", "item_weapon", "item_armour", "item_wand", "item_food",
"item_scroll", "item_ring", "item_potion", "item_missile", "item_book",
"item_stave", "item_miscellany", "item_corpse", "item_gold",
- "item_amulet", "cloud", "tree",
+ "item_amulet", "cloud", "tree", "teleporter",
"space", "fired_flask", "fired_bolt", "fired_chunk", "fired_book",
"fired_weapon", "fired_zap", "fired_burst", "fired_stick",
"fired_trinket", "fired_scroll", "fired_debug", "fired_armour",
"fired_missile", "explosion",
};
+ COMPILE_CHECK(ARRAYSZ(dchar_names) == NUM_DCHAR_TYPES);
for (unsigned i = 0; i < sizeof(dchar_names) / sizeof(*dchar_names); ++i)
if (dchar_names[i] == name)
@@ -114,7 +127,7 @@ void init_char_table(char_set_type set)
}
}
-unsigned dchar_glyph(dungeon_char_type dchar)
+ucs_t dchar_glyph(dungeon_char_type dchar)
{
if (dchar >= 0 && dchar < NUM_DCHAR_TYPES)
return (Options.char_table[dchar]);
diff --git a/crawl-ref/source/viewchar.h b/crawl-ref/source/viewchar.h
index 8b49a26f6d..36d8c65f19 100644
--- a/crawl-ref/source/viewchar.h
+++ b/crawl-ref/source/viewchar.h
@@ -4,7 +4,7 @@
void init_char_table(char_set_type set);
dungeon_char_type get_feature_dchar(dungeon_feature_type feat);
-unsigned dchar_glyph(dungeon_char_type dchar);
+ucs_t dchar_glyph(dungeon_char_type dchar);
std::string stringize_glyph(ucs_t glyph);
diff --git a/crawl-ref/source/webserver/game_data/static/display.js b/crawl-ref/source/webserver/game_data/static/display.js
index 7d585bc7df..e75a7f3824 100644
--- a/crawl-ref/source/webserver/game_data/static/display.js
+++ b/crawl-ref/source/webserver/game_data/static/display.js
@@ -28,6 +28,8 @@ function ($, comm, map_knowledge, view_data, monster_list, minimap,
if (!map_knowledge.bounds())
return;
+ var t1 = new Date();
+
if (map_knowledge.reset_bounds_changed())
{
minimap.center();
@@ -51,6 +53,13 @@ function ($, comm, map_knowledge, view_data, monster_list, minimap,
map_knowledge.reset_dirty();
monster_list.update();
+
+ var render_time = (new Date() - t1);
+ if (!window.render_times)
+ window.render_times = [];
+ if (window.render_times.length > 20)
+ window.render_times.shift();
+ window.render_times.push(render_time);
}
function clear_map()
diff --git a/crawl-ref/source/webserver/ws_handler.py b/crawl-ref/source/webserver/ws_handler.py
index 7030c8a892..a1da3a1dd3 100644
--- a/crawl-ref/source/webserver/ws_handler.py
+++ b/crawl-ref/source/webserver/ws_handler.py
@@ -129,6 +129,8 @@ class CrawlWebSocket(tornado.websocket.WebSocketHandler):
"set_rc": self.set_rc,
}
+ client_closed = property(lambda self: self.ws_connection and self.ws_connection.client_terminated)
+
def _process_log_msg(self, msg, kwargs):
return "#%-5s %s" % (self.id, msg), kwargs
@@ -201,7 +203,7 @@ class CrawlWebSocket(tornado.websocket.WebSocketHandler):
self.logger.info("Stopping crawl after idle time limit.")
self.process.stop()
- if not self.client_terminated:
+ if not self.client_closed:
self.reset_timeout()
def start_crawl(self, game_id):
@@ -253,7 +255,7 @@ class CrawlWebSocket(tornado.websocket.WebSocketHandler):
socket.send_message("lobby_remove", id=self.process.id)
self.process = None
- if self.client_terminated:
+ if self.client_closed:
sockets.remove(self)
else:
if shutting_down:
@@ -287,7 +289,7 @@ class CrawlWebSocket(tornado.websocket.WebSocketHandler):
self.send_message("go_lobby")
def shutdown(self):
- if not self.client_terminated:
+ if not self.client_closed:
msg = self.render_string("shutdown.html", game=self)
self.send_message("close", reason = msg)
self.close()
@@ -438,7 +440,7 @@ class CrawlWebSocket(tornado.websocket.WebSocketHandler):
def write_message(self, msg):
try:
msg = to_unicode(msg)
- if not self.client_terminated:
+ if not self.client_closed:
super(CrawlWebSocket, self).write_message(msg)
except:
self.logger.warning("Exception trying to send message.", exc_info = True)
@@ -447,7 +449,7 @@ class CrawlWebSocket(tornado.websocket.WebSocketHandler):
def send_message(self, msg, **data):
"""Sends a JSON message to the client."""
data["msg"] = msg
- if not self.client_terminated:
+ if not self.client_closed:
self.write_message(json_encode(data))
def on_close(self):
diff --git a/crawl-ref/source/wiz-dgn.cc b/crawl-ref/source/wiz-dgn.cc
index a22aa5587c..2f8f7efc74 100644
--- a/crawl-ref/source/wiz-dgn.cc
+++ b/crawl-ref/source/wiz-dgn.cc
@@ -13,6 +13,7 @@
#include "coordit.h"
#include "delay.h"
#include "dactions.h"
+#include "dgn-overview.h"
#include "dungeon.h"
#include "effects.h"
#include "env.h"
@@ -798,6 +799,15 @@ void wizard_recreate_level()
}
dgn_erase_unused_vault_placements();
+ for (monster_iterator mi; mi; ++mi)
+ {
+ if (mons_is_unique(mi->type))
+ {
+ remove_unique_annotation(*mi);
+ you.unique_creatures[mi->type] = false;
+ }
+ }
+
level_id lev = level_id::current();
dungeon_feature_type stair_taken = DNGN_STONE_STAIRS_DOWN_I;
diff --git a/crawl-ref/source/wiz-fsim.cc b/crawl-ref/source/wiz-fsim.cc
index 858aa8c59a..01c9860761 100644
--- a/crawl-ref/source/wiz-fsim.cc
+++ b/crawl-ref/source/wiz-fsim.cc
@@ -22,6 +22,7 @@
#include "mon-place.h"
#include "mgen_data.h"
#include "monster.h"
+#include "mon-clone.h"
#include "mon-stuff.h"
#include "mon-util.h"
#include "options.h"
@@ -30,575 +31,605 @@
#include "skills.h"
#include "skills2.h"
#include "species.h"
+#include "stuff.h"
+#include "wiz-you.h"
#ifdef WIZARD
-static monster* _create_fsim_monster(monster_type mtype, int hp)
-{
- monster *mon = create_monster(
- mgen_data::hostile_at(mtype,
- "the fight simulator", false, 0, 0, you.pos()));
- if (!mon)
- return 0;
+fight_data null_fight = {0.0,0,0,0.0,0.0,0.0};
+typedef std::map<skill_type, int8_t> skill_map;
+typedef std::map<skill_type, int8_t>::iterator skill_map_iterator;
- // To prevent distracted stabing.
- mon->foe = MHITYOU;
+static const char* _title_line =
+ "AvHitDam | MaxDam | Accuracy | AvDam | AvTime | AvEffDam"; // 55 columns
- // Move the monster next to the player
- if (!adjacent(mon->pos(), you.pos()))
- for (adjacent_iterator ai(you.pos()); ai; ++ai)
- if (mon->move_to_pos(*ai))
- break;
+static const std::string _fight_string(fight_data fdata)
+{
+ return make_stringf(" %5.1f | %3d | %3d%% |"
+ " %5.1f | %5.1f | %5.1f",
+ fdata.av_hit_dam, fdata.max_dam, fdata.accuracy,
+ fdata.av_dam, fdata.av_time, fdata.av_eff_dam);
+}
- if (!adjacent(mon->pos(), you.pos()))
+static skill_type _equipped_skill()
+{
+ const int weapon = you.equip[EQ_WEAPON];
+ const item_def * iweap = weapon != -1 ? &you.inv[weapon] : NULL;
+ const int missile = you.m_quiver->get_fire_item();
+
+ if (iweap && iweap->base_type == OBJ_WEAPONS)
{
- monster_die(mon, KILL_DISMISSED, NON_MONSTER);
- return 0;
+ if (is_range_weapon(*iweap))
+ return range_skill(*iweap);
+ return weapon_skill(*iweap);
}
- // the monster is never saved, and thus we might allow any 31 bit value
- mon->hit_points = mon->max_hit_points = hp;
- return mon;
+ if (missile != -1)
+ return range_skill(you.inv[missile]);
+
+ return SK_UNARMED_COMBAT;
}
-static skill_type _fsim_melee_skill(const item_def *item)
+static std::string _equipped_weapon_name()
{
- return (item ? weapon_skill(*item) : SK_UNARMED_COMBAT);
+ const int weapon = you.equip[EQ_WEAPON];
+ const item_def * iweap = weapon != -1 ? &you.inv[weapon] : NULL;
+ const int missile = you.m_quiver->get_fire_item();
+
+ if (iweap)
+ {
+ std::string item_buf = iweap->name(DESC_PLAIN, true);
+ // If it's a ranged weapon, add the description of the missile
+ if (is_range_weapon(*iweap) && missile < ENDOFPACK && missile >= 0)
+ item_buf += " with " + you.inv[missile].name(DESC_PLAIN);
+ return "Wielding: " + item_buf;
+ }
+
+ if (missile != -1)
+ return "Quivering: " + you.inv[missile].name(DESC_PLAIN);
+
+ return "Unarmed";
}
-static void _fsim_set_melee_skill(int skill, const item_def *item)
+static std::string _time_string()
{
- set_skill_level(_fsim_melee_skill(item), skill);
- set_skill_level(SK_FIGHTING, skill * 15 / 27);
- set_skill_level(SK_ARMOUR, skill * 15 / 27);
- set_skill_level(SK_SHIELDS, skill);
- for (int i = SK_FIRST_MAGIC_SCHOOL; i <= SK_LAST_SKILL; ++i)
- set_skill_level(skill_type(i), skill);
+ time_t curr_time = time(NULL);
+ struct tm *ltime = TIME_FN(&curr_time);
+ if (ltime)
+ {
+ return make_stringf("%4d/%02d/%02d/%2d:%02d:%02d",
+ ltime->tm_year + 1900,
+ ltime->tm_mon + 1,
+ ltime->tm_mday,
+ ltime->tm_hour,
+ ltime->tm_min,
+ ltime->tm_sec);
+ }
+ return ("");
}
-static void _fsim_set_ranged_skill(int skill, const item_def *item)
+static void _write_version(FILE * o)
{
- set_skill_level(range_skill(*item), skill);
+ fprintf(o, CRAWL " version %s\n", Version::Long().c_str());
}
-static void _fsim_item(FILE *out,
- bool melee,
- const item_def *weap,
- skill_type sk,
- unsigned int damage,
- int iterations, int hits,
- int maxdam, unsigned int time)
+static void _write_matchup(FILE * o, monster &mon, bool defend, int iter_limit)
{
- double hitdam = hits? double(damage) / hits : 0.0;
- double avspeed = ((double) time / (double) iterations);
- fprintf(out,
- " %2d | %3.1f | %3d%% | %5.2f | %5.2f |"
- " %5.2f | %3d | %5.1f\n",
- you.skills[sk],
- (you.skill(sk, 10) - you.skill(sk, 10, true)) / 10.0,
- 100 * hits / iterations,
- double(damage) / iterations,
- hitdam,
- double(damage) * player_speed() / avspeed / iterations,
- maxdam,
- avspeed);
+ fprintf(o, "%s: %s %s vs. %s (%d rounds) (%s)\n",
+ defend ? "Defense" : "Attack",
+ species_name(you.species).c_str(),
+ you.class_name.c_str(),
+ mon.name(DESC_PLAIN, true).c_str(),
+ iter_limit,
+ _time_string().c_str());
}
-static void _fsim_defence_item(FILE *out, int cum, int hits, int max,
- int speed, int iters)
+static void _write_you(FILE * o)
{
- skill_type sk = you.skills[SK_DODGING] ? SK_DODGING : SK_ARMOUR;
- // AC | EV | Arm | Dod | Bonus | Acc | Av.Dam | Av.HitDam | Eff.Dam | Max.Dam | Av.Time
- fprintf(out, "%2d %2d %2d %2d %3.1f %3d%% %5.2f %5.2f %5.2f %3d"
- " %2d\n",
- you.armour_class(),
- player_evasion(),
- you.skills[SK_DODGING],
- you.skills[SK_ARMOUR],
- (you.skill(sk, 10) - you.skill(sk, 10, true)) / 10.0,
- 100 * hits / iters,
- double(cum) / iters,
- hits? double(cum) / hits : 0.0,
- double(cum) / iters * speed / 10,
- max,
- 100 / speed);
+ fprintf(o, "%s %s: XL %d Str %d Int %d Dex %d\n",
+ species_name(you.species).c_str(),
+ you.class_name.c_str(),
+ you.experience_level,
+ you.strength(),
+ you.intel(),
+ you.dex());
}
+static void _write_weapon(FILE * o)
+{
+ fprintf(o, "%s, Skill: %s\n",
+ _equipped_weapon_name().c_str(),
+ skill_name(_equipped_skill()));
+}
-static bool _fsim_ranged_combat(FILE *out, int wskill, monster &mon,
- const item_def *item, int missile_slot)
+static void _write_mon(FILE * o, monster &mon)
{
- const monster orig = mon;
- unsigned int cumulative_damage = 0;
- unsigned int time_taken = 0;
- int hits = 0;
- int maxdam = 0;
+ fprintf(o, "%s: HD %d AC %d EV %d\n",
+ mon.name(DESC_PLAIN, true).c_str(),
+ mon.hit_dice,
+ mon.ac,
+ mon.ev);
+}
- const int thrown = missile_slot == -1 ? you.m_quiver->get_fire_item() : missile_slot;
- if (thrown == ENDOFPACK || thrown == -1)
+static bool _fsim_kit_equip(const std::string &kit)
+{
+ std::string::size_type ammo_div = kit.find("/");
+ std::string weapon = kit;
+ std::string missile;
+ if (ammo_div != std::string::npos)
{
- mprf("No suitable missiles for combat simulation.");
- return (false);
+ weapon = kit.substr(0, ammo_div);
+ missile = kit.substr(ammo_div + 1);
+ trim_string(weapon);
+ trim_string(missile);
}
- _fsim_set_ranged_skill(wskill, item);
+ if (!weapon.empty())
+ {
+ for (int i = 0; i < ENDOFPACK; ++i)
+ {
+ if (!you.inv[i].defined())
+ continue;
- no_messages mx;
- const int iter_limit = Options.fsim_rounds;
- const int hunger = you.hunger;
- for (int i = 0; i < iter_limit; ++i)
+ if (you.inv[i].name(DESC_PLAIN).find(weapon) != std::string::npos)
+ {
+ if (i != you.equip[EQ_WEAPON])
+ {
+ wield_weapon(true, i, false);
+ if (i != you.equip[EQ_WEAPON])
+ return false;
+ }
+ break;
+ }
+ }
+ }
+ else if (you.weapon())
+ unwield_item(false);
+
+ if (!missile.empty())
{
- mon = orig;
- mon.hit_points = mon.max_hit_points;
- mon.move_to_pos(mon.pos());
- bolt beam;
- you.time_taken = player_speed();
-
- // throw_it() will decrease quantity by 1
- inc_inv_item_quantity(thrown, 1);
-
- beam.target = mon.pos();
- beam.animate = false;
- if (throw_it(beam, thrown, false, DEBUG_COOKIE))
- hits++;
-
- you.hunger = hunger;
- time_taken += you.time_taken;
-
- int damage = (mon.max_hit_points - mon.hit_points);
- cumulative_damage += damage;
- if (damage > maxdam)
- maxdam = damage;
+ for (int i = 0; i < ENDOFPACK; ++i)
+ {
+ if (!you.inv[i].defined())
+ continue;
+
+ if (you.inv[i].name(DESC_PLAIN).find(missile) != std::string::npos)
+ {
+ quiver_item(i);
+ break;
+ }
+ }
}
- _fsim_item(out, false, item, range_skill(*item),
- cumulative_damage, iter_limit, hits, maxdam, time_taken);
- return (true);
+ return true;
}
-static bool _fsim_mon_melee(FILE *out, int dodge, int armour, monster &mon)
+// fight simulator internals
+static monster* _init_fsim()
{
- set_skill_level(SK_DODGING, dodge);
- set_skill_level(SK_ARMOUR, armour);
-
- const int yhp = you.hp;
- const int ymhp = you.hp_max;
- unsigned int cumulative_damage = 0;
- int hits = 0;
- int maxdam = 0;
- no_messages mx;
+ monster * mon = NULL;
+ monster_type mtype = get_monster_by_name(Options.fsim_mons);
- for (int i = 0; i < Options.fsim_rounds; ++i)
+ if(mtype == MONS_PROGRAM_BUG && monster_nearby())
{
- you.hp = you.hp_max = 5000;
- fight_melee(&mon, &you);
- const int damage = you.hp_max - you.hp;
- if (damage)
- hits++;
- cumulative_damage += damage;
- if (damage > maxdam)
- maxdam = damage;
+ // get a monster via targetting.
+ dist moves;
+ direction_chooser_args args;
+ args.needs_path = false;
+ args.top_prompt = "Select a monster, or hit Escape to use default.";
+ direction(moves, args);
+ if (monster_at(moves.target))
+ mon = clone_mons(monster_at(moves.target), true);
}
- you.hp = yhp;
- you.hp_max = ymhp;
-
- _fsim_defence_item(out, cumulative_damage, hits, maxdam, mon.speed,
- Options.fsim_rounds);
- return (true);
-}
+ if (!mon)
+ {
+ if (mtype == MONS_PROGRAM_BUG)
+ {
+ char specs[100];
+ mpr("Enter monster name (or MONS spec): ", MSGCH_PROMPT);
+ if (cancelable_get_line_autohist(specs, sizeof specs) || !*specs)
+ {
+ canned_msg(MSG_OK);
+ return NULL;
+ }
+ mtype = get_monster_by_name(specs);
+ }
-static bool _fsim_melee_combat(FILE *out, int wskill, monster &mon,
- const item_def *item)
-{
- const monster orig = mon;
- unsigned int cumulative_damage = 0;
- unsigned int time_taken = 0;
- int hits = 0;
- int maxdam = 0;
+ mon = create_monster(
+ mgen_data::hostile_at(mtype, "fightsim", false, 0, 0, you.pos(),
+ MG_DONT_COME));
+ if (!mon)
+ {
+ mprf("Failed to create monster.");
+ return NULL;
+ }
+ }
- _fsim_set_melee_skill(wskill, item);
+ // move the monster next to the player
+ // this probably works best in the arena, or at least somewhere
+ // where there's no water or anything weird to interfere
+ if (!adjacent(mon->pos(), you.pos()))
+ for (adjacent_iterator ai(you.pos()); ai; ++ai)
+ if (mon->move_to_pos(*ai))
+ break;
- no_messages mx;
- const int iter_limit = Options.fsim_rounds;
- const int hunger = you.hunger;
- for (int i = 0; i < iter_limit; ++i)
+ if (!adjacent(mon->pos(), you.pos()))
{
- mon = orig;
- mon.hit_points = mon.max_hit_points;
- you.time_taken = player_speed();
- bool did_hit = false;
- fight_melee(&you, &mon, &did_hit);
- if (did_hit)
- hits++;
-
- you.hunger = hunger;
- time_taken += you.time_taken;
-
- int damage = (mon.max_hit_points - mon.hit_points);
- cumulative_damage += damage;
- if (damage > maxdam)
- maxdam = damage;
+ monster_die(mon, KILL_DISMISSED, NON_MONSTER);
+ mprf("Could not put monster adjacent to player.");
+ return 0;
}
- _fsim_item(out, true, item, _fsim_melee_skill(item),
- cumulative_damage, iter_limit, hits, maxdam, time_taken);
- return (true);
+ // prevent distracted stabbing
+ mon->foe = MHITYOU;
+ // this line is actually kind of important for distortion now
+ mon->hit_points = mon->max_hit_points = MAX_MONSTER_HP;
+ mon->behaviour = BEH_SEEK;
+
+ return mon;
}
-static bool debug_fight_simulate(FILE *out, int wskill, monster &m, int miss_slot)
+static void _uninit_fsim(monster *mon)
{
- int weapon = you.equip[EQ_WEAPON];
- const item_def *iweap = weapon != -1? &you.inv[weapon] : NULL;
-
- if (iweap && iweap->base_type == OBJ_WEAPONS && is_range_weapon(*iweap))
- return _fsim_ranged_combat(out, wskill, m, iweap, miss_slot);
- else
- return _fsim_melee_combat(out, wskill, m, iweap);
+ monster_die(mon, KILL_DISMISSED, NON_MONSTER);
+ reset_training();
}
-static const item_def *_fsim_weap_item()
+static fight_data _get_fight_data(monster &mon, int iter_limit, bool defend)
{
- const int weap = you.equip[EQ_WEAPON];
- if (weap == -1)
- return NULL;
+ const monster orig = mon;
+ unsigned int cumulative_damage = 0;
+ unsigned int time_taken = 0;
+ int hits = 0;
+ fight_data fdata;
+ fdata.max_dam = 0;
- return &you.inv[weap];
-}
+ const int weapon = you.equip[EQ_WEAPON];
+ const item_def *iweap = weapon != -1 ? &you.inv[weapon] : NULL;
+ const int missile = you.m_quiver->get_fire_item();
-static std::string _fsim_wskill(int missile_slot)
-{
- const item_def *iweap = _fsim_weap_item();
- if (!iweap && missile_slot != -1)
- return skill_name(range_skill(you.inv[missile_slot]));
+ // now make sure the player is ready
+ you.exp_available = 0;
+ const int yhp = you.hp;
+ const int ymhp = you.hp_max;
- if (iweap && iweap->base_type == OBJ_WEAPONS)
- {
- if (is_range_weapon(*iweap))
- return skill_name(range_skill(*iweap));
+ // disable death and delay, but make sure that these values
+ // get reset when the function call ends
+ unwind_var<FixedBitArray<NUM_DISABLEMENTS> > disabilities(crawl_state.disables);
+ crawl_state.disables.set(DIS_DEATH);
+ crawl_state.disables.set(DIS_DELAY);
- return skill_name(_fsim_melee_skill(iweap));
- }
- return skill_name(SK_UNARMED_COMBAT);
-}
+ no_messages mx;
+ const int hunger = you.hunger;
-static std::string _fsim_weapon(int missile_slot)
-{
- if (const item_def* weapon = you.weapon())
+ if(!defend) // you're the attacker
{
- std::string item_buf = weapon->name(DESC_PLAIN, true);
-
- // If it's a ranged weapon, add the description of the missile
- // if applicable.
- if (is_range_weapon(*weapon))
+ for (int i = 0; i < iter_limit; i++)
{
- const int missile =
- (missile_slot == -1 ? you.m_quiver->get_fire_item()
- : missile_slot);
+ mon = orig;
+ mon.hit_points = mon.max_hit_points;
+ mon.move_to_pos(mon.pos());
+ you.time_taken = player_speed();
+
+ // first, ranged weapons. note: this includes
+ // being empty-handed but having a missile quivered
+ if ((iweap && iweap->base_type == OBJ_WEAPONS &&
+ is_range_weapon(*iweap))
+ || (!iweap && (missile != -1)))
+ {
+ bolt beam;
+ // throw_it() will decrease quantity by 1
+ inc_inv_item_quantity(missile, 1);
+ beam.target = mon.pos();
+ beam.animate = false;
+ if (throw_it(beam, missile, false, DEBUG_COOKIE))
+ hits++;
+ }
+ else // otherwise, melee combat
+ {
+ bool did_hit = false;
+ fight_melee(&you, &mon, &did_hit, true);
+ if (did_hit)
+ hits++;
+ }
+ you.hunger = hunger;
+ time_taken += you.time_taken;
- if (missile < ENDOFPACK && missile >= 0)
- item_buf += " with " + you.inv[missile].name(DESC_PLAIN);
+ int damage = (mon.max_hit_points - mon.hit_points);
+ cumulative_damage += damage;
+ if (damage > fdata.max_dam)
+ fdata.max_dam = damage;
}
-
- return item_buf;
}
- else if (missile_slot != -1)
- return you.inv[missile_slot].name(DESC_PLAIN);
- else
- return "unarmed";
-}
-
-static std::string _fsim_time_string()
-{
- time_t curr_time = time(NULL);
- struct tm *ltime = TIME_FN(&curr_time);
- if (ltime)
+ else // you're defending
{
- return make_stringf("%4d%02d%02d/%2d:%02d:%02d",
- ltime->tm_year + 1900,
- ltime->tm_mon + 1,
- ltime->tm_mday,
- ltime->tm_hour,
- ltime->tm_min,
- ltime->tm_sec);
+ for (int i = 0; i < iter_limit; i++)
+ {
+ you.hp = you.hp_max = 999; // again, arbitrary
+ bool did_hit = false;
+ fight_melee(&mon, &you, &did_hit, true);
+
+ time_taken += (100 / mon.speed);
+
+ int damage = you.hp_max - you.hp;
+ if (did_hit)
+ hits++;
+ cumulative_damage += damage;
+ if (damage > fdata.max_dam)
+ fdata.max_dam = damage;
+ }
+ you.hp = yhp;
+ you.hp_max = ymhp;
}
- return ("");
-}
-static void _fsim_mon_stats(FILE *o, const monster& mon)
-{
- fprintf(o, "Monster : %s\n", mon.name(DESC_PLAIN, true).c_str());
- fprintf(o, "HD : %d\n", mon.hit_dice);
- fprintf(o, "AC : %d\n", mon.ac);
- fprintf(o, "EV : %d\n", mon.ev);
-}
+ fdata.av_hit_dam = hits ? double(cumulative_damage) / hits : 0.0;
+ fdata.accuracy = 100 * hits / iter_limit;
+ fdata.av_dam = double(cumulative_damage) / iter_limit;
+ fdata.av_time = double(time_taken) / double(iter_limit) / 10.0;
+ fdata.av_eff_dam = fdata.av_dam / fdata.av_time;
-static void _fsim_title(FILE *o, monster &mon, int ms)
-{
- fprintf(o, CRAWL " version %s\n\n", Version::Long().c_str());
- fprintf(o, "Combat simulation: %s %s vs. %s (%d rounds) (%s)\n",
- species_name(you.species).c_str(),
- you.class_name.c_str(),
- mon.name(DESC_PLAIN, true).c_str(),
- Options.fsim_rounds,
- _fsim_time_string().c_str());
-
- fprintf(o, "Experience: %d\n", you.experience_level);
- fprintf(o, "Strength : %d\n", you.strength());
- fprintf(o, "Intel. : %d\n", you.intel());
- fprintf(o, "Dexterity : %d\n", you.dex());
- fprintf(o, "Base speed: %d\n", player_speed());
- fprintf(o, "\n");
-
- _fsim_mon_stats(o, mon);
-
- fprintf(o, "\n");
- fprintf(o, "Weapon : %s\n", _fsim_weapon(ms).c_str());
- fprintf(o, "Skill : %s\n", _fsim_wskill(ms).c_str());
- fprintf(o, "\n");
- fprintf(o, "Skill | Bonus | Accuracy | Av.Dam | Av.HitDam | Eff.Dam | Max.Dam | Av.Time\n");
+ return fdata;
}
-static void _fsim_defence_title(FILE *o, monster &mon)
+// this is the skeletal simulator call, and the one that's easily accessed
+void wizard_quick_fsim()
{
- fprintf(o, CRAWL " version %s\n\n", Version::Long().c_str());
- fprintf(o, "Combat simulation: %s vs. %s %s (%d rounds) (%s)\n",
- mon.name(DESC_PLAIN).c_str(),
- species_name(you.species).c_str(),
- you.class_name.c_str(),
- Options.fsim_rounds,
- _fsim_time_string().c_str());
- fprintf(o, "Experience: %d\n", you.experience_level);
- fprintf(o, "Strength : %d\n", you.strength());
- fprintf(o, "Intel. : %d\n", you.intel());
- fprintf(o, "Dexterity : %d\n", you.dex());
- fprintf(o, "Base speed: %d\n", player_speed());
- fprintf(o, "\n");
- _fsim_mon_stats(o, mon);
- fprintf(o, "\n");
- fprintf(o, "AC | EV | Dod | Arm | Bonus | Acc | Av.Dam | Av.HitDam | Eff.Dam | Max.Dam | Av.Time\n");
+ // we could declare this in the fight calls, but i'm worried that
+ // the actual monsters that are made will be slightly different,
+ // so it's safer to do it here.
+ monster *mon = _init_fsim();
+ if(!mon)
+ return;
+
+ const int iter_limit = Options.fsim_rounds;
+ fight_data fdata = _get_fight_data(*mon, iter_limit, false);
+ mprf(" %s\nAttacking: %s", _title_line,
+ _fight_string(fdata).c_str());
+
+ fdata = _get_fight_data(*mon, iter_limit, true);
+ mprf("Defending: %s", _fight_string(fdata).c_str());
+
+ _uninit_fsim(mon);
+ return;
}
-static bool _fsim_mon_hit_you(FILE *ostat, monster &mon, int)
+static std::string _init_scale(skill_map &scale, bool &xl_mode)
{
- _fsim_defence_title(ostat, mon);
+ std::string ret;
- for (int sk = 0; sk <= 27; ++sk)
+ for (int i = 0, size = Options.fsim_scale.size(); i < size; ++i)
{
- mesclr();
- mprf("Calculating average damage for %s at dodging %d",
- mon.name(DESC_PLAIN).c_str(),
- sk);
-
- if (!_fsim_mon_melee(ostat, sk, 0, mon))
- return (false);
-
- fflush(ostat);
- // Not checking in the combat loop itself; that would be more responsive
- // for the user, but slow down the sim with all the calls to kbhit().
- if (kbhit() && getchk() == 27)
+ std::string sk_str = lowercase_string(Options.fsim_scale[i]);
+ if (sk_str == "xl")
{
- mprf("Cancelling simulation\n");
- return (false);
+ xl_mode = true;
+ ret = "XL";
+ continue;
}
- }
-
- for (int sk = 0; sk <= 27; ++sk)
- {
- mesclr();
- mprf("Calculating average damage for %s at armour %d",
- mon.name(DESC_PLAIN).c_str(),
- sk);
- if (!_fsim_mon_melee(ostat, 0, sk, mon))
- return (false);
+ int divider = 1;
+ skill_type sk;
- fflush(ostat);
- // Not checking in the combat loop itself; that would be more responsive
- // for the user, but slow down the sim with all the calls to kbhit().
- if (kbhit() && getchk() == 27)
+ std::string::size_type sep = sk_str.find("/");
+ if (sep == std::string::npos)
+ sep = sk_str.find(":");
+ if (sep != std::string::npos)
{
- mprf("Cancelling simulation\n");
- return (false);
+ std::string divider_str = sk_str.substr(sep + 1);
+ sk_str = sk_str.substr(0, sep);
+ trim_string(sk_str);
+ trim_string(divider_str);
+ divider = atoi(divider_str.c_str());
}
+
+ if (sk_str == "weapon")
+ sk = _equipped_skill();
+ else
+ sk = skill_from_name(sk_str.c_str());
+
+ scale[sk] = divider;
+ if (divider == 1 && ret.empty())
+ ret = skill_name(sk);
}
- mprf("Done defence simulation with %s",
- mon.name(DESC_PLAIN).c_str());
+ if (xl_mode)
+ {
+ you.training.init(0);
+ for (skill_map_iterator it = scale.begin(); it != scale.end(); ++it)
+ you.training[it->first] = it->second;
+ }
- return (true);
+ return ret;
}
-static bool _fsim_you_hit_mon(FILE *ostat, monster &mon, int missile_slot)
+static void _fsim_simple_scale(FILE * o, monster* mon, bool defense)
{
- _fsim_title(ostat, mon, missile_slot);
- for (int wskill = 0; wskill <= 27; ++wskill)
+ skill_map scale;
+ bool xl_mode = false;
+ std::string col_name;
+
+ if (Options.fsim_scale.empty())
+ {
+ skill_type sk = defense ? SK_ARMOUR : _equipped_skill();
+ scale[sk] = 1;
+ col_name = skill_name(sk);
+ }
+ else
+ col_name = _init_scale(scale, xl_mode);
+
+ const char* title = make_stringf("%10.10s | %s", col_name.c_str(),
+ _title_line).c_str();
+ fprintf(o, "%s\n", title);
+ mpr(title);
+
+ const int iter_limit = Options.fsim_rounds;
+ for(int i = xl_mode ? 1 : 0; i <= 27; i++)
{
mesclr();
- mprf("Calculating average damage for %s at skill %d",
- _fsim_weapon(missile_slot).c_str(), wskill);
- if (!debug_fight_simulate(ostat, wskill, mon, missile_slot))
- return (false);
+ if (xl_mode)
+ set_xl(i, true);
+ else
+ for (skill_map_iterator it = scale.begin(); it != scale.end(); ++it)
+ set_skill_level(it->first, i / it->second);
- fflush(ostat);
- // Not checking in the combat loop itself; that would be more responsive
- // for the user, but slow down the sim with all the calls to kbhit().
+ fight_data fdata = _get_fight_data(*mon, iter_limit, defense);
+ const std::string line = make_stringf(" %2d | %s", i,
+ _fight_string(fdata).c_str());
+ mpr(line);
+ fprintf(o, "%s\n", line.c_str());
+ fflush(o);
+
+ // kill the loop if the user hits escape
if (kbhit() && getchk() == 27)
{
- mprf("Cancelling simulation\n");
- return (false);
+ mprf("Cancelling simulation.\n");
+ fprintf(o, "Simulation cancelled!\n\n");
+ break;
}
}
- mprf("Done fight simulation with %s", _fsim_weapon(missile_slot).c_str());
- return (true);
}
-static bool debug_fight_sim(monster &mon, int missile_slot,
- bool (*combat)(FILE *, monster &mon, int mslot))
+static void _fsim_double_scale(FILE * o, monster* mon, bool defense)
{
- FILE *ostat = fopen("fight.stat", "a");
- if (!ostat)
+ skill_type skx, sky;
+ if (defense)
{
- mprf(MSGCH_ERROR, "Can't write fight.stat: %s", strerror(errno));
- return (false);
+ skx = SK_ARMOUR;
+ sky = SK_DODGING;
}
-
- bool success = true;
- unwind_var<FixedVector<uint8_t, NUM_SKILLS> > skills(you.skills);
- unwind_var<FixedVector<unsigned int, NUM_SKILLS> > skill_points(you.skill_points);
- unwind_var<std::list<skill_type> > exercises(you.exercises);
- unwind_var<std::list<skill_type> > exercises_all(you.exercises_all);
- unwind_var<FixedVector<int8_t, NUM_STATS> > stats(you.base_stats);
- unwind_var<int> xp(you.experience_level);
-
- for (int i = SK_FIGHTING; i < NUM_SKILLS; ++i)
- you.skills[i] = 0;
-
- if (Options.fsim_xl != -1)
+ else
{
- you.experience_level = Options.fsim_xl;
- if (you.experience_level < 1)
- you.experience_level = 1;
- if (you.experience_level > 27)
- you.experience_level = 27;
+ skx = SK_FIGHTING;
+ sky = _equipped_skill();
}
- if (Options.fsim_str != -1)
- you.base_stats[STAT_STR] = debug_cap_stat(Options.fsim_str);
- if (Options.fsim_int != -1)
- you.base_stats[STAT_INT] = debug_cap_stat(Options.fsim_int);
- if (Options.fsim_dex != -1)
- you.base_stats[STAT_DEX] = debug_cap_stat(Options.fsim_dex);
-
- combat(ostat, mon, missile_slot);
+ fprintf(o, "%s(x) vs %s(y)\n", skill_name(skx), skill_name(sky));
+ fprintf(o, " ");
+ for(int y = 1; y <= 27; y += 2)
+ fprintf(o," %2d", y);
- fprintf(ostat, "-----------------------------------\n\n");
- fclose(ostat);
+ fprintf(o,"\n");
- return (success);
+ const int iter_limit = Options.fsim_rounds;
+ for(int y = 1; y <= 27; y += 2)
+ {
+ fprintf(o, "%2d", y);
+ for(int x = 1; x <= 27; x += 2)
+ {
+ mesclr();
+ set_skill_level(skx, x);
+ set_skill_level(sky, y);
+ fight_data fdata = _get_fight_data(*mon, iter_limit, defense);
+ mprf("%s %d, %s %d: %d", skill_name(skx), x, skill_name(sky), y,
+ int(fdata.av_eff_dam));
+ fprintf(o,"%5.1f", fdata.av_eff_dam);
+ fflush(o);
+
+ // kill the loop if the user hits escape
+ if (kbhit() && getchk() == 27)
+ {
+ mprf("Cancelling simulation.\n");
+ fprintf(o, "\nSimulation cancelled!\n\n");
+ return;
+ }
+ }
+ fprintf(o,"\n");
+ }
}
-static int _fsim_kit_equip(const std::string &kit)
+void wizard_fight_sim(bool double_scale)
{
- int missile_slot = -1;
+ monster * mon = _init_fsim();
+ if(!mon)
+ return;
- std::string::size_type ammo_div = kit.find("/");
- std::string weapon = kit;
- std::string missile;
- if (ammo_div != std::string::npos)
+ bool defense = false;
+ const char * fightstat = "fight.stat";
+
+ FILE * o = fopen(fightstat, "a");
+ if (!o)
{
- weapon = kit.substr(0, ammo_div);
- missile = kit.substr(ammo_div + 1);
- trim_string(weapon);
- trim_string(missile);
+ mprf(MSGCH_ERROR, "Can't write %s: %s", fightstat, strerror(errno));
+ return;
}
- if (!weapon.empty())
+ if (Options.fsim_mode.find("defen") != std::string::npos)
+ defense = true;
+ else if (Options.fsim_mode.find("attack") != std::string::npos
+ || Options.fsim_mode.find("offen") != std::string::npos)
{
- for (int i = 0; i < ENDOFPACK; ++i)
- {
- if (!you.inv[i].defined())
- continue;
-
- if (you.inv[i].name(DESC_PLAIN).find(weapon) != std::string::npos)
- {
- if (i != you.equip[EQ_WEAPON])
- {
- wield_weapon(true, i, false);
- if (i != you.equip[EQ_WEAPON])
- return -100;
- }
- break;
- }
- }
+ defense = false;
}
- else if (you.weapon())
- unwield_item(false);
-
- if (!missile.empty())
+ else
{
- for (int i = 0; i < ENDOFPACK; ++i)
- {
- if (!you.inv[i].defined())
- continue;
+ mpr("(A)ttack or (D)efense?", MSGCH_PROMPT);
- if (you.inv[i].name(DESC_PLAIN).find(missile) != std::string::npos)
- {
- missile_slot = i;
- break;
- }
+ switch (tolower(getchk()))
+ {
+ case 'a':
+ case 'A':
+ defense = false;
+ break;
+ case 'd':
+ case 'D':
+ defense = true;
+ break;
+ default:
+ canned_msg(MSG_OK);
+ return;
}
}
- return (missile_slot);
-}
-
-// Writes statistics about a fight to fight.stat in the current directory.
-// For fight purposes, a punching bag is summoned and given lots of hp, and the
-// average damage the player does to the p. bag over 10000 hits is noted,
-// advancing the weapon skill from 0 to 27, and keeping fighting skill to 2/5
-// of current weapon skill.
-void debug_fight_statistics(bool use_defaults, bool defence)
-{
- monster_type punching_bag = get_monster_by_name(Options.fsim_mons);
- if (punching_bag == MONS_NO_MONSTER)
- punching_bag = MONS_WORM;
+ _write_version(o);
+ _write_matchup(o, *mon, defense, Options.fsim_rounds);
+ _write_you(o);
+ _write_weapon(o);
+ _write_mon(o, *mon);
+ fprintf(o,"\n");
- monster *mon = _create_fsim_monster(punching_bag, 500);
- if (!mon)
- {
- mprf("Failed to create punching bag");
- return;
- }
- mon->behaviour = BEH_SEEK;
+ skill_state skill_backup;
+ skill_backup.save();
+ int xl = you.experience_level;
- you.exp_available = 0;
+ // disable death and delay, but make sure that these values
+ // get reset when the function call ends
unwind_var<FixedBitArray<NUM_DISABLEMENTS> > disabilities(crawl_state.disables);
crawl_state.disables.set(DIS_DEATH);
crawl_state.disables.set(DIS_DELAY);
- if (!use_defaults || defence)
- {
- debug_fight_sim(*mon, -1,
- defence? _fsim_mon_hit_you : _fsim_you_hit_mon);
- }
+ void (*fsim_proc)(FILE * o, monster* mon, bool defense) = NULL;
+ fsim_proc = double_scale ? _fsim_double_scale : _fsim_simple_scale;
+
+ if (Options.fsim_kit.empty())
+ fsim_proc(o, mon, defense);
else
- {
for (int i = 0, size = Options.fsim_kit.size(); i < size; ++i)
{
- int missile = _fsim_kit_equip(Options.fsim_kit[i]);
- if (missile == -100)
+ if (_fsim_kit_equip(Options.fsim_kit[i]))
+ {
+ _write_weapon(o);
+ fsim_proc(o, mon, defense);
+ fprintf(o, "\n");
+ }
+ else
{
mprf("Aborting sim on %s", Options.fsim_kit[i].c_str());
break;
}
- if (!debug_fight_sim(*mon, missile, _fsim_you_hit_mon))
- break;
}
- }
- monster_die(mon, KILL_DISMISSED, NON_MONSTER);
- reset_training();
+
+ fprintf(o, "-----------------------------------\n\n");
+ fclose(o);
+
+ skill_backup.restore_levels();
+ skill_backup.restore_training();
+ if (you.experience_level != xl)
+ set_xl(xl, false);
+
+ _uninit_fsim(mon);
+ mprf("Done.");
}
#endif
diff --git a/crawl-ref/source/wiz-fsim.h b/crawl-ref/source/wiz-fsim.h
index 1422feb9d3..1f2d6837dd 100644
--- a/crawl-ref/source/wiz-fsim.h
+++ b/crawl-ref/source/wiz-fsim.h
@@ -1,11 +1,21 @@
/**
* @file
- * @brief Fight simualtion wizard functions.
+ * @brief Fight simulation wizard functions.
**/
#ifndef WIZFSIM_H
#define WIZFSIM_H
-void debug_fight_statistics(bool use_init_defaults, bool defence = false);
+struct fight_data {
+double av_hit_dam;
+int max_dam;
+int accuracy;
+double av_dam;
+double av_time;
+double av_eff_dam;
+};
+
+void wizard_quick_fsim();
+void wizard_fight_sim(bool double_scale);
#endif
diff --git a/crawl-ref/source/wiz-you.cc b/crawl-ref/source/wiz-you.cc
index 1c1bed2bb0..25522199f5 100644
--- a/crawl-ref/source/wiz-you.cc
+++ b/crawl-ref/source/wiz-you.cc
@@ -185,6 +185,11 @@ void wizard_change_species(void)
// Sanitize skills.
fixup_skills();
+ // Could delete only inappropriate ones, but meh.
+ you.sage_skills.clear();
+ you.sage_xp.clear();
+ you.sage_bonus.clear();
+
calc_hp();
calc_mp();
@@ -751,7 +756,9 @@ static const char* dur_names[] =
"stealth",
"magic shield",
"sleep",
+#if TAG_MAJOR_VERSION == 32
"sage",
+#endif
"telepathy",
"petrified",
"lowered mr",
@@ -943,8 +950,11 @@ void wizard_set_xl()
return;
}
- const bool train = yesno("Train skills?", true, 'n');
+ set_xl(newxl, yesno("Train skills?", true, 'n'));
+}
+void set_xl(const int newxl, const bool train)
+{
no_messages mx;
if (newxl < you.experience_level)
debug_downtick_xl(newxl);
diff --git a/crawl-ref/source/wiz-you.h b/crawl-ref/source/wiz-you.h
index 80b80b2adf..264fbfb5a9 100644
--- a/crawl-ref/source/wiz-you.h
+++ b/crawl-ref/source/wiz-you.h
@@ -18,6 +18,7 @@ void wizard_set_skill_level(skill_type skill = SK_NONE);
void wizard_set_all_skills(void);
void wizard_change_species(void);
void wizard_set_xl();
+void set_xl(const int newxl, const bool train);
bool wizard_add_mutation();
void wizard_set_stats(void);
void wizard_edit_durations(void);
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc
index d96ddad52a..8c540ac7f8 100644
--- a/crawl-ref/source/xom.cc
+++ b/crawl-ref/source/xom.cc
@@ -101,9 +101,8 @@ static const spell_type _xom_tension_spells[] =
SPELL_DISPERSAL, SPELL_STONESKIN, SPELL_RING_OF_FLAMES,
SPELL_OLGREBS_TOXIC_RADIANCE, SPELL_FIRE_BRAND, SPELL_FREEZING_AURA,
SPELL_POISON_WEAPON, SPELL_LETHAL_INFUSION, SPELL_EXCRUCIATING_WOUNDS,
- SPELL_WARP_BRAND, SPELL_TUKIMAS_DANCE, SPELL_RECALL,
- SPELL_SUMMON_BUTTERFLIES, SPELL_SUMMON_SMALL_MAMMALS,
- SPELL_SUMMON_SCORPIONS, SPELL_SUMMON_SWARM, SPELL_FLY,
+ SPELL_WARP_BRAND, SPELL_TUKIMAS_DANCE, SPELL_SUMMON_BUTTERFLIES,
+ SPELL_SUMMON_SMALL_MAMMALS, SPELL_SUMMON_SCORPIONS, SPELL_SUMMON_SWARM,
SPELL_BEASTLY_APPENDAGE, SPELL_SPIDER_FORM, SPELL_STATUE_FORM,
SPELL_ICE_FORM, SPELL_DRAGON_FORM, SPELL_SHADOW_CREATURES,
SPELL_SUMMON_HORRIBLE_THINGS, SPELL_CALL_CANINE_FAMILIAR,
@@ -198,9 +197,10 @@ bool xom_is_nice(int tension)
// At high tension Xom is more likely to be nice, at zero
// tension the opposite.
const int tension_bonus
- = (tension == -1 ? 0 :
- tension == 0 ? -std::min(abs(HALF_MAX_PIETY - you.piety) / 2,
- you.piety / 10)
+ = (tension == -1 ? 0 // :
+// Xom needs to be less negative
+// : tension == 0 ? -std::min(abs(HALF_MAX_PIETY - you.piety) / 2,
+// you.piety / 10)
: std::min((MAX_PIETY - you.piety) / 2,
random2(tension)));
@@ -285,61 +285,64 @@ void xom_is_stimulated(int maxinterestingness, const std::string& message,
void xom_tick()
{
- // Xom semi-randomly drifts your piety.
- const std::string old_xom_favour = describe_xom_favour();
- const bool good = (you.piety == HALF_MAX_PIETY? coinflip()
- : you.piety > HALF_MAX_PIETY);
- int size = abs(you.piety - HALF_MAX_PIETY);
-
- // Piety slowly drifts towards the extremes.
- const int delta = piety_scale(x_chance_in_y(511, 1000) ? 1 : -1);
- size += delta;
- if (size > HALF_MAX_PIETY)
- size = HALF_MAX_PIETY;
-
- you.piety = HALF_MAX_PIETY + (good ? size : -size);
- std::string new_xom_favour = describe_xom_favour();
- if (old_xom_favour != new_xom_favour)
- {
- // If we entered another favour state, take a big step into
- // the new territory, to avoid oscillating favour announcements
- // every few turns.
- size += delta * 8;
+ // Xom now ticks every action, not every 20 turns.
+ if (x_chance_in_y(1, 20))
+ {
+ // Xom semi-randomly drifts your piety.
+ const std::string old_xom_favour = describe_xom_favour();
+ const bool good = (you.piety == HALF_MAX_PIETY? coinflip()
+ : you.piety > HALF_MAX_PIETY);
+ int size = abs(you.piety - HALF_MAX_PIETY);
+
+ // Piety slowly drifts towards the extremes.
+ const int delta = piety_scale(x_chance_in_y(511, 1000) ? 1 : -1);
+ size += delta;
if (size > HALF_MAX_PIETY)
size = HALF_MAX_PIETY;
- // If size was 0 to begin with, it may become negative, but that
- // doesn't really matter.
you.piety = HALF_MAX_PIETY + (good ? size : -size);
- }
-
+ std::string new_xom_favour = describe_xom_favour();
+ if (old_xom_favour != new_xom_favour)
+ {
+ // If we entered another favour state, take a big step into
+ // the new territory, to avoid oscillating favour announcements
+ // every few turns.
+ size += delta * 8;
+ if (size > HALF_MAX_PIETY)
+ size = HALF_MAX_PIETY;
+
+ // If size was 0 to begin with, it may become negative, but that
+ // doesn't really matter.
+ you.piety = HALF_MAX_PIETY + (good ? size : -size);
+ }
#ifdef DEBUG_DIAGNOSTICS
- snprintf(info, INFO_SIZE, "xom_tick(), delta: %d, piety: %d",
- delta, you.piety);
- take_note(Note(NOTE_MESSAGE, 0, 0, info), true);
+ snprintf(info, INFO_SIZE, "xom_tick(), delta: %d, piety: %d",
+ delta, you.piety);
+ take_note(Note(NOTE_MESSAGE, 0, 0, info), true);
#endif
- // ...but he gets bored...
- if (you.gift_timeout > 0 && coinflip())
- you.gift_timeout--;
+ // ...but he gets bored...
+ if (you.gift_timeout > 0 && coinflip())
+ you.gift_timeout--;
- new_xom_favour = describe_xom_favour();
- if (old_xom_favour != new_xom_favour)
- {
- const std::string msg = "You are now " + new_xom_favour;
- god_speaks(you.religion, msg.c_str());
- //updating piety status line
- you.redraw_title = true;
- }
+ new_xom_favour = describe_xom_favour();
+ if (old_xom_favour != new_xom_favour)
+ {
+ const std::string msg = "You are now " + new_xom_favour;
+ god_speaks(you.religion, msg.c_str());
+ //updating piety status line
+ you.redraw_title = true;
+ }
- if (you.gift_timeout == 1)
- {
- simple_god_message(" is getting BORED.");
- //updating piety status line
- you.redraw_title = true;
+ if (you.gift_timeout == 1)
+ {
+ simple_god_message(" is getting BORED.");
+ //updating piety status line
+ you.redraw_title = true;
+ }
}
- if (wearing_amulet(AMU_FAITH)? coinflip() : one_chance_in(3))
+ if (player_effect_faith() ? coinflip() : one_chance_in(3))
{
const int tension = get_tension(GOD_XOM);
const int chance = (tension == 0 ? 1 :
@@ -348,14 +351,14 @@ void xom_tick()
tension <= 20 ? 4
: 5);
- // If Xom is bored, the chances for Xom acting are reversed.
- if (!you.gift_timeout && x_chance_in_y(5 - chance, 5))
+ // If Xom is bored, the chances for Xom acting are sort of reversed.
+ if (!you.gift_timeout && x_chance_in_y(25 - chance*chance, 100))
{
xom_acts(abs(you.piety - HALF_MAX_PIETY), tension);
return;
}
else if (you.gift_timeout <= 1 && chance > 0
- && x_chance_in_y(chance - 1, 4))
+ && x_chance_in_y(chance - 1, 80))
{
// During tension, Xom may briefly forget about being bored.
const int interest = random2(chance * 15);
@@ -377,7 +380,7 @@ void xom_tick()
}
}
- if (x_chance_in_y(chance, 5))
+ if (x_chance_in_y(chance*chance, 100))
xom_acts(abs(you.piety - HALF_MAX_PIETY), tension);
}
}
@@ -781,143 +784,8 @@ static void _xom_acquirement(object_class_type force_class)
stop_running();
}
-static object_class_type _get_unrelated_wield_class(object_class_type ref)
-{
- object_class_type objtype = OBJ_WEAPONS;
- if (ref == OBJ_WEAPONS)
- {
- if (one_chance_in(10))
- objtype = OBJ_MISCELLANY;
- else
- objtype = OBJ_STAVES;
- }
- else if (ref == OBJ_STAVES)
- {
- if (one_chance_in(10))
- objtype = OBJ_MISCELLANY;
- else
- objtype = OBJ_WEAPONS;
- }
- else
- {
- const int temp_rand = random2(3);
- objtype = (temp_rand == 0) ? OBJ_WEAPONS :
- (temp_rand == 1) ? OBJ_STAVES
- : OBJ_MISCELLANY;
- }
-
- return (objtype);
-}
-
-// Gift an item the player can't currently use. It can still be really
-// good or even acquirement level.
-static bool _xom_annoyance_gift(int power, bool debug = false)
-{
- god_acting gdact(GOD_XOM);
-
- if (coinflip() && player_in_a_dangerous_place())
- {
- const item_def *weapon = you.weapon();
-
- // Xom has a sense of humour.
- if (coinflip() && weapon && weapon->cursed())
- {
- if (debug)
- return (true);
-
- // If you are wielding a cursed item then Xom will give you
- // an item of that same type. Ha ha!
- god_speaks(GOD_XOM, _get_xom_speech("cursed gift").c_str());
- if (coinflip())
- // For added humour, give the same sub-type.
- _xom_make_item(weapon->base_type, weapon->sub_type, power * 3);
- else
- _xom_acquirement(weapon->base_type);
- return (true);
- }
-
- const item_def *gloves = you.slot_item(EQ_GLOVES, true);
- if (coinflip() && gloves && gloves->cursed())
- {
- if (debug)
- return (true);
-
- // If you are wearing cursed gloves, then Xom will give you
- // a ring. Ha ha!
- god_speaks(GOD_XOM, _get_xom_speech("cursed gift").c_str());
- _xom_make_item(OBJ_JEWELLERY, get_random_ring_type(), power * 3);
- return (true);
- };
-
- const item_def *amulet = you.slot_item(EQ_AMULET, true);
- if (coinflip() && amulet && amulet->cursed())
- {
- if (debug)
- return (true);
-
- // If you are wearing a cursed amulet, then Xom will give
- // you an amulet. Ha ha!
- god_speaks(GOD_XOM, _get_xom_speech("cursed gift").c_str());
- _xom_make_item(OBJ_JEWELLERY, get_random_amulet_type(), power * 3);
- return (true);
- };
-
- const item_def *left_ring = you.slot_item(EQ_LEFT_RING, true);
- const item_def *right_ring = you.slot_item(EQ_RIGHT_RING, true);
- if (you.species != SP_OCTOPODE && coinflip() && ((left_ring && left_ring->cursed())
- || (right_ring && right_ring->cursed())))
- {
- if (debug)
- return (true);
-
- // If you are wearing a cursed ring, then Xom will give you
- // a ring. Ha ha!
- god_speaks(GOD_XOM, _get_xom_speech("ring gift").c_str());
- _xom_make_item(OBJ_JEWELLERY, get_random_ring_type(), power * 3);
- return (true);
- }
-
- if (one_chance_in(5) && weapon)
- {
- if (debug)
- return (true);
-
- // Xom will give you a wielded item of a type different from
- // what you are currently wielding.
- god_speaks(GOD_XOM, _get_xom_speech("weapon gift").c_str());
-
- const object_class_type objtype =
- _get_unrelated_wield_class(weapon->base_type);
-
- if (x_chance_in_y(power, 256))
- _xom_acquirement(objtype);
- else
- _xom_make_item(objtype, OBJ_RANDOM, power * 3);
- return (true);
- }
- }
-
- const item_def *cloak = you.slot_item(EQ_CLOAK, true);
- if (coinflip() && cloak && cloak->cursed())
- {
- // If you are wearing a cursed cloak, then Xom will give you a
- // cloak or body armour. Ha ha!
- god_speaks(GOD_XOM, _get_xom_speech("armour gift").c_str());
- _xom_make_item(OBJ_ARMOUR,
- one_chance_in(10) ? ARM_CLOAK :
- get_random_body_armour_type(power * 2),
- power * 3);
- return (true);
- }
-
- return (false);
-}
-
static int _xom_give_item(int power, bool debug = false)
{
- if (_xom_annoyance_gift(power, debug))
- return (XOM_GOOD_ANNOYANCE_GIFT);
-
if (!debug)
god_speaks(GOD_XOM, _get_xom_speech("general gift").c_str());
@@ -933,7 +801,8 @@ static int _xom_give_item(int power, bool debug = false)
const object_class_type types[] = {
OBJ_WEAPONS, OBJ_ARMOUR, OBJ_JEWELLERY, OBJ_BOOKS,
- OBJ_STAVES, OBJ_WANDS, OBJ_MISCELLANY, OBJ_FOOD, OBJ_GOLD
+ OBJ_STAVES, OBJ_WANDS, OBJ_MISCELLANY, OBJ_FOOD, OBJ_GOLD,
+ OBJ_MISSILES
};
god_acting gdact(GOD_XOM);
_xom_acquirement(RANDOM_ELEMENT(types));
@@ -1156,7 +1025,7 @@ static void _do_chaos_upgrade(item_def &item, const monster* mon)
static monster_type _xom_random_demon(int sever, bool use_greater_demons = true)
{
- const int roll = random2(1000 - (MAX_PIETY - sever) * 3);
+ const int roll = random2(1000 - (MAX_PIETY - sever) * 5);
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "_xom_random_demon(); sever = %d, roll: %d",
sever, roll);
@@ -1318,7 +1187,7 @@ static int _xom_send_allies(int sever, bool debug = false)
numdemons = std::min(numdemons + 2, 16);
// Limit number of demons by experience level.
- const int maxdemons = (you.experience_level * 3);
+ const int maxdemons = (you.experience_level);
if (numdemons > maxdemons)
numdemons = maxdemons;
@@ -1803,12 +1672,12 @@ static int _xom_rearrange_pieces(int sever, bool debug = false)
static int _xom_random_stickable(const int HD)
{
- int c;
+ unsigned int c;
// XXX: Unify this with the list in spl-summoning:_snakable_weapon().
// It has everything but tridents, demon tridents and bardiches, and
// puts the giant club types at the end as special cases.
- static const int arr[13] = {
- WPN_CLUB, WPN_ANKUS, WPN_SPEAR, WPN_HALBERD,
+ static const int arr[] = {
+ WPN_CLUB, WPN_SPEAR, WPN_HALBERD,
WPN_SCYTHE, WPN_GLAIVE, WPN_STAFF, WPN_QUARTERSTAFF,
WPN_BLOWGUN, WPN_BOW, WPN_LONGBOW, WPN_GIANT_CLUB,
WPN_GIANT_SPIKED_CLUB
@@ -1818,7 +1687,7 @@ static int _xom_random_stickable(const int HD)
// weapon_rarity also gives us 1-10.
do
c = random2(HD);
- while (c > 11
+ while (c >= ARRAYSZ(arr)
|| random2(HD) > weapon_rarity(arr[c]) && x_chance_in_y(c, HD));
return arr[c];
@@ -2411,22 +2280,20 @@ static int _xom_is_good(int sever, int tension, bool debug = false)
done = _xom_change_scenery(debug);
else if (x_chance_in_y(8, sever))
done = _xom_snakes_to_sticks(sever, debug);
- else if (x_chance_in_y(9, sever))
- done = _xom_give_item(sever, debug);
// It's pointless to send in help if there's no danger.
- else if (tension > random2(10) && x_chance_in_y(10, sever))
+ else if (tension > random2(10) && x_chance_in_y(9, sever))
done = _xom_send_allies(sever, debug);
- else if (tension > random2(8) && x_chance_in_y(11, sever))
+ else if (tension > random2(8) && x_chance_in_y(10, sever))
done = _xom_animate_monster_weapon(sever, debug);
- else if (x_chance_in_y(12, sever))
+ else if (x_chance_in_y(11, sever))
done = _xom_polymorph_nearby_monster(true, debug);
- else if (x_chance_in_y(13, sever))
+ else if (x_chance_in_y(12, sever))
done = _xom_inner_flame(debug);
- else if (tension > 0 && x_chance_in_y(14, sever))
+ else if (tension > 0 && x_chance_in_y(13, sever))
done = _xom_rearrange_pieces(sever, debug);
- else if (random2(tension) < 15 && x_chance_in_y(15, sever))
+ else if (random2(tension) < 15 && x_chance_in_y(14, sever))
done = _xom_give_item(sever, debug);
- else if (!player_in_branch(BRANCH_ABYSS) && x_chance_in_y(16, sever))
+ else if (!player_in_branch(BRANCH_ABYSS) && x_chance_in_y(15, sever))
{
// Try something else if teleportation is impossible.
if (!_teleportation_check())
@@ -2469,7 +2336,7 @@ static int _xom_is_good(int sever, int tension, bool debug = false)
take_note(Note(NOTE_XOM_EFFECT, you.piety, tension, tele_buf), true);
done = XOM_GOOD_TELEPORT;
}
- else if (random2(tension) < 5 && x_chance_in_y(17, sever))
+ else if (random2(tension) < 5 && x_chance_in_y(16, sever))
{
if (debug)
return (XOM_GOOD_VITRIFY);
@@ -2483,12 +2350,12 @@ static int _xom_is_good(int sever, int tension, bool debug = false)
done = XOM_GOOD_VITRIFY;
}
}
- else if (random2(tension) < 5 && x_chance_in_y(18, sever)
+ else if (random2(tension) < 5 && x_chance_in_y(17, sever)
&& x_chance_in_y(16, how_mutated()))
{
done = _xom_give_mutations(true, debug);
}
- else if (tension > 0 && x_chance_in_y(19, sever))
+ else if (tension > 0 && x_chance_in_y(18, sever))
done = _xom_throw_divine_lightning(debug);
return (done);
@@ -2954,7 +2821,7 @@ static int _xom_lose_stats(bool debug = false)
return (XOM_BAD_STATLOSS);
stat_type stat = static_cast<stat_type>(random2(NUM_STATS));
- int max = 3;
+ int max = 2; // was 3
// Don't kill the player unless Xom is being nasty.
if (!_xom_feels_nasty())
@@ -2973,9 +2840,9 @@ static int _xom_lose_stats(bool debug = false)
{
int idx = random2(3);
stat = types[idx];
- max = std::min(3, vals[idx] - 1);
+ max = std::min(max, vals[idx] - 1);
}
- while (max < 2 && (++tries < 30));
+ while (max < 1 && (++tries < 30));
if (tries >= 30)
return (XOM_DID_NOTHING);
@@ -3451,7 +3318,7 @@ static int _xom_summon_hostiles(int sever, bool debug = false)
// Limit number of demons by experience level.
if (!you.penance[GOD_XOM])
{
- const int maxdemons = (you.experience_level * 2);
+ const int maxdemons = (you.experience_level / 2);
if (numdemons > maxdemons)
numdemons = maxdemons;
}
@@ -3920,7 +3787,7 @@ int xom_acts(bool niceness, int sever, int tension, bool debug)
#endif
const bool was_bored = _xom_is_bored();
- const bool good_act = niceness && !one_chance_in(20);
+ const bool good_act = niceness;// && !one_chance_in(20);
int result = XOM_DID_NOTHING;
if (good_act)
{
@@ -4237,7 +4104,7 @@ static const std::string _xom_effect_to_name(int effect)
// good acts
"nothing", "potion", "spell (tension)", "spell (no tension)",
"divination", "confuse monsters", "single ally",
- "animate monster weapon", "annoyance gift", "random item gift",
+ "animate monster weapon", "random item gift",
"acquirement", "summon allies", "polymorph", "swap monsters",
"teleportation", "vitrification", "mutation", "lightning",
"change scenery", "snakes to sticks", "inner flame monsters",
diff --git a/crawl-ref/source/xom.h b/crawl-ref/source/xom.h
index f0c8f878ac..dcd85cb696 100644
--- a/crawl-ref/source/xom.h
+++ b/crawl-ref/source/xom.h
@@ -30,20 +30,19 @@ enum xom_event_type
XOM_GOOD_CONFUSION,
XOM_GOOD_SINGLE_ALLY,
XOM_GOOD_ANIMATE_MON_WPN,
- XOM_GOOD_ANNOYANCE_GIFT,
- XOM_GOOD_RANDOM_ITEM, // 10
- XOM_GOOD_ACQUIREMENT,
+ XOM_GOOD_RANDOM_ITEM,
+ XOM_GOOD_ACQUIREMENT, // 10
XOM_GOOD_ALLIES,
XOM_GOOD_POLYMORPH,
XOM_GOOD_SWAP_MONSTERS,
- XOM_GOOD_TELEPORT, // 15
- XOM_GOOD_VITRIFY,
+ XOM_GOOD_TELEPORT,
+ XOM_GOOD_VITRIFY, // 15
XOM_GOOD_MUTATION,
XOM_GOOD_LIGHTNING,
- XOM_GOOD_SCENERY, // 20
+ XOM_GOOD_SCENERY,
XOM_GOOD_SNAKES,
- XOM_GOOD_INNER_FLAME,
- XOM_LAST_GOOD_ACT = XOM_GOOD_INNER_FLAME, // 22
+ XOM_GOOD_INNER_FLAME, // 20
+ XOM_LAST_GOOD_ACT = XOM_GOOD_INNER_FLAME,
// bad acts
XOM_BAD_NOTHING, // bad act suppressed
diff --git a/crawl-ref/source/zap-data.h b/crawl-ref/source/zap-data.h
index 9d0ac197da..8a262fcb76 100644
--- a/crawl-ref/source/zap-data.h
+++ b/crawl-ref/source/zap-data.h
@@ -346,7 +346,7 @@
ZAP_MYSTIC_BLAST,
"orb of energy",
100,
- new calcdice_calculator<2, 15, 2, 5>,
+ new calcdice_calculator<2, 12, 1, 3>,
new tohit_calculator<10, 1, 7>,
LIGHTMAGENTA,
false,
@@ -505,8 +505,8 @@
{
ZAP_STRIKING,
"force bolt",
- 25,
- new dicedef_calculator<1, 8, 0, 1>,
+ 50,
+ new dicedef_calculator<1, 8, 1, 5>,
new tohit_calculator<8, 1, 10>,
BLACK,
false,
diff --git a/crawl-ref/source/zotdef.cc b/crawl-ref/source/zotdef.cc
index eb8505a976..417ada074f 100644
--- a/crawl-ref/source/zotdef.cc
+++ b/crawl-ref/source/zotdef.cc
@@ -928,7 +928,6 @@ bool create_trap(trap_type spec_type)
args.top_prompt += trap_name(spec_type);
args.top_prompt += " trap where?";
direction(abild, args);
- const dungeon_feature_type grid = grd(abild.target);
if (!abild.isValid)
{
if (abild.isCancel)
@@ -936,7 +935,7 @@ bool create_trap(trap_type spec_type)
return (false);
}
// only try to create on floor squares
- if (!feat_is_floor(grid))
+ if (grd(abild.target) != DNGN_FLOOR)
{
mpr("You can't create a trap there!");
return (false);